CCCamera(可以用来做3d效果 如卡牌翻转 等需要展示物体的立体效果 )
.h
#ifndef __CCCAMERA_H__
#define __CCCAMERA_H__
#include "cocoa/CCObject.h"
#include "ccMacros.h"
#include "kazmath/mat4.h"
#include <string>
NS_CC_BEGIN
////////////////////////////////////////
A CCCamera is used in every CCNode.
Useful to look at the object from different views.
The OpenGL gluLookAt() function is used to locate the
camera.
If the object is transformed by any of the scale, rotation or
position attributes, then they will override(推翻 重写) the camera.
IMPORTANT: Either your use the camera or the rotation/scale/position properties(property 性能,道具). You can't use both.
World coordinates(坐标) won't work if you use the camera.
Limitations:(camera无效情况1和2,建议只在需要3d效果时使用camera)
-1、 Some nodes, like CCParallaxNode, CCParticle uses world node coordinates(坐标), and they won't work properly(适当的) if you move them (or any of their ancestors(祖先))
using the camera.
-2、It doesn't work on batched(batch 一批) nodes like CCSprite objects when they are parented(专利的) to a CCSpriteBatchNode object.
- It is recommended(推荐) to use it ONLY if you are going to create 3D effects. For 2D effects, use the action CCFollow or position/scale/rotate.
/////////////////////////////////////////
class CC_DLL CCCamera : public CCObject
{
protected:
float m_fEyeX;
float m_fEyeY;
float m_fEyeZ;
float m_fCenterX;
float m_fCenterY;
float m_fCenterZ;
float m_fUpX;
float m_fUpY;
float m_fUpZ;
bool m_bDirty;
kmMat4 m_lookupMatrix;
public:
CCCamera(void);
~CCCamera(void);
void init(void);
const char* description(void);//为了更方便的输出调试信息,增加了description函数
inline void setDirty(bool bValue) { m_bDirty = bValue; }
inline bool isDirty(void) { return m_bDirty; }
void restore(void);//初始化时调用 给camera赋默认初值
/** Sets the camera using gluLookAt using its eye, center and up_vector */
void locate(void);
void setEyeXYZ(float fEyeX, float fEyeY, float fEyeZ);
//朝“Center”看 center是一个向量void setCenterXYZ(float fCenterX, float fCenterY, float fCenterZ);
//沿着“Up”方向 站着看地上一个图片 转动身体后看到的图片会也会转void setUpXYZ(float fUpX, float fUpY, float fUpZ);
void getEyeXYZ(float *pEyeX, float *pEyeY, float *pEyeZ);
void getCenterXYZ(float *pCenterX, float *pCenterY, float *pCenterZ);
void getUpXYZ(float *pUpX, float *pUpY, float *pUpZ);
public:
static float getZEye();//返回一个无限趋于0的folat (用来初始化 z)
private:
DISALLOW_COPY_AND_ASSIGN(CCCamera);
};
NS_CC_END
#endif // __CCCAMERA_H__
const char* CCCamera::description(void)
{
return CCString::createWithFormat("<CCCamera | center = (%.2f,%.2f,%.2f)>", m_fCenterX, m_fCenterY, m_fCenterZ)->getCString();
}
void CCCamera::init(void)
{
restore();
}
void CCCamera::restore(void)
{
m_fEyeX = m_fEyeY = 0.0f;
m_fEyeZ = getZEye();
m_fCenterX = m_fCenterY = m_fCenterZ = 0.0f;
m_fUpX = 0.0f;
m_fUpY = 1.0f;
m_fUpZ = 0.0f;
kmMat4Identity( &m_lookupMatrix );
m_bDirty = false;
}
kmMat4* const kmMat4Identity(kmMat4* pOut)//参数是 输出参数 m_lookupMatrix
{
//将pOut->mat中前 sizeof(float) * 16个字节用 0 替换并返回 pOut->mat。
memset(pOut->mat, 0, sizeof(float) * 16);
pOut->mat[0] = pOut->mat[5] = pOut->mat[10] = pOut->mat[15] = 1.0f;
return pOut;
}
void CCCamera::locate(void)
{
if (m_bDirty)
{
kmVec3 eye, center, up;
kmVec3Fill( &eye, m_fEyeX, m_fEyeY , m_fEyeZ );
kmVec3Fill( ¢er, m_fCenterX, m_fCenterY, m_fCenterZ );
kmVec3Fill( &up, m_fUpX, m_fUpY, m_fUpZ);
kmMat4LookAt( &m_lookupMatrix, &eye, ¢er, &up);
m_bDirty = false;
}
kmGLMultMatrix( &m_lookupMatrix );
}
///////////////// (线性代数)
/**
* Fill a kmVec3 structure using 3 floating point values
* The result is store in pOut, returns pOut
*/
kmVec3* kmVec3Fill(kmVec3* pOut, kmScalar x, kmScalar y, kmScalar z)
{
pOut->x = x;
pOut->y = y;
pOut->z = z;
return pOut;
}
/**
* Builds a translation matrix in the same way as gluLookAt()
* the resulting matrix is stored in pOut. pOut is returned.
*/
kmMat4* const kmMat4LookAt(kmMat4* pOut, const kmVec3* pEye,
const kmVec3* pCenter, const kmVec3* pUp)
{
kmVec3 f, up, s, u;
kmMat4 translate;
kmVec3Subtract(&f, pCenter, pEye);
kmVec3Normalize(&f, &f);
kmVec3Assign(&up, pUp);
kmVec3Normalize(&up, &up);
kmVec3Cross(&s, &f, &up);
kmVec3Normalize(&s, &s);
kmVec3Cross(&u, &s, &f);
kmVec3Normalize(&s, &s);
kmMat4Identity(pOut);
pOut->mat[0] = s.x;
pOut->mat[4] = s.y;
pOut->mat[8] = s.z;
pOut->mat[1] = u.x;
pOut->mat[5] = u.y;
pOut->mat[9] = u.z;
pOut->mat[2] = -f.x;
pOut->mat[6] = -f.y;
pOut->mat[10] = -f.z;
kmMat4Translation(&translate, -pEye->x, -pEye->y, -pEye->z);
kmMat4Multiply(pOut, pOut, &translate);
return pOut;
}
/**
* Subtracts 2 vectors and returns the result. The result is stored in
* pOut.
*/
kmVec3* kmVec3Subtract(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2)
{
kmVec3 v;
v.x = pV1->x - pV2->x;
v.y = pV1->y - pV2->y;
v.z = pV1->z - pV2->z;
pOut->x = v.x;
pOut->y = v.y;
pOut->z = v.z;
return pOut;
}
/**
* Returns the vector passed in set to unit length
* the result is stored in pOut.
*/
kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn)
{
kmScalar l = 1.0f / kmVec3Length(pIn);
kmVec3 v;
v.x = pIn->x * l;
v.y = pIn->y * l;
v.z = pIn->z * l;
pOut->x = v.x;
pOut->y = v.y;
pOut->z = v.z;
return pOut;
}
kmVec3* kmVec3Assign(kmVec3* pOut, const kmVec3* pIn) {
if (pOut == pIn) {
return pOut;
}
pOut->x = pIn->x;
pOut->y = pIn->y;
pOut->z = pIn->z;
return pOut;
}
/**
* Returns a vector perpendicular to 2 other vectors.
* The result is stored in pOut.
*/
kmVec3* kmVec3Cross(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2)
{
kmVec3 v;
v.x = (pV1->y * pV2->z) - (pV1->z * pV2->y);
v.y = (pV1->z * pV2->x) - (pV1->x * pV2->z);
v.z = (pV1->x * pV2->y) - (pV1->y * pV2->x);
pOut->x = v.x;
pOut->y = v.y;
pOut->z = v.z;
return pOut;
}
/**
* Builds a translation matrix. All other elements in the matrix
* will be set to zero except for the diagonal which is set to 1.0
*/
kmMat4* const kmMat4Translation(kmMat4* pOut, const kmScalar x,
const kmScalar y, const kmScalar z)
{
//FIXME: Write a test for this
memset(pOut->mat, 0, sizeof(float) * 16);
pOut->mat[0] = 1.0f;
pOut->mat[5] = 1.0f;
pOut->mat[10] = 1.0f;
pOut->mat[12] = x;
pOut->mat[13] = y;
pOut->mat[14] = z;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Multiplies pM1 with pM2, stores the result in pOut, returns pOut
*/
kmMat4* const kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2)
{
#if defined(__ARM_NEON__)
float mat[16];
// Invert column-order with row-order
NEON_Matrix4Mul( &pM2->mat[0], &pM1->mat[0], &mat[0] );
#else
float mat[16];
const float *m1 = pM1->mat, *m2 = pM2->mat;
mat[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
mat[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
mat[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
mat[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
mat[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
mat[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
mat[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
mat[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
mat[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
mat[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
mat[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
mat[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
mat[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
mat[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
mat[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
mat[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
#endif
memcpy(pOut->mat, mat, sizeof(float)*16);
return pOut;
}
/////////////////
关于cocos2dx中的摄像机
1、CCCamera 默认是从前往后看(center是原点,eye的z值很小,方向是z轴),所以z值越大,越是在前面,
2、球坐标:原点是圆心,仰角theata(从z轴开始),方位角 fai,一般数学坐标系中的逆时针角
3、 CCOrbitCamera::create(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX)
参数依次是持续时间、半径初始值、半径增量、仰角初始值、仰角增量、离x轴的偏移角、离x轴的偏移角的增量
4、cocos2dx中的camera与一般3d中的camera的区别
cocos2dx中的camera是一个辅助类,主要是修改当前渲染的camera的matrix的(核心函数是locate),也就是尽管每个node有一个camera,实际上这个camera不是真的
opengl的camera,整个scene在渲染时一定是只有一台camera在渲染场景。这样做的好处:每个node可以单独的用2d来模拟3d的效果,而不会影响到别的node
3d引擎中的camera是一个真正的opengl的camera,有多个camera存在时会有效率方面的问题。
5、为什么3d引擎中不采用cocos2d中的方式来提高效率?
因为3d对视觉效果要求高,比如画中画效果、render to texture 实现的特效等,这时是必须要实现多个摄像机的;而对于cocos2dx而言基本上不存在这样的问题
6、CCOrbitCamera的实现逻辑
每帧根据输入的参数插值球坐标,之后改变节点eye的位置
Cocos2dx概念介绍(游戏开发中不同的坐标系,cocos2dx锚点)
一个cocos2dx的图片效果貌似的做法

旁边翻转角度效果:
var distance = (this.getPosition().x + scrollViewOffset.x );
var value = VisibleRect.center().x - distance;
var temp = value / VisibleRect.center().x / 2.5;
this.setScale(1 - Math.abs(temp));
this.getCamera().setEye(10 * temp ,0, 10);
var x = value / wd;
var offset = cc.p(x * x* x* 30, 0);
this._node.setPosition(offset);
浙公网安备 33010602011771号