Last active
June 14, 2025 21:37
-
-
Save undefined06855/54e849f7403fc5bc20dbcd1f16d58b57 to your computer and use it in GitHub Desktop.
cocos2d-x perspective camera node
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "PerspectiveNode.hpp" | |
| PerspectiveCamera::PerspectiveCamera() | |
| : m_dirty(true) | |
| , m_projectionViewMatrix({ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }) | |
| , m_aim({ 0.f, 0.f, 0.f }) | |
| , m_pos({ 0.f, 0.f, -100.f }) | |
| , m_fov(80.f) {} | |
| void PerspectiveCamera::setFOV(float fov) { | |
| m_fov = fov; | |
| m_dirty = true; | |
| } | |
| void PerspectiveCamera::set3DPosition(cocos2d::CCPoint3D pos) { | |
| m_pos = pos; | |
| m_dirty = true; | |
| } | |
| void PerspectiveCamera::set3DAim(cocos2d::CCPoint3D aim) { | |
| m_aim = aim; | |
| m_dirty = true; | |
| } | |
| kmMat4 PerspectiveCamera::getProjectionViewMatrix() { | |
| if (!m_dirty) return m_projectionViewMatrix; | |
| // create projection matrix | |
| kmMat4 proj; | |
| auto winSize = cocos2d::CCDirector::get()->getWinSizeInPixels(); | |
| float fov = m_fov; | |
| float aspect = winSize.width / winSize.height; | |
| float nearZ = .1f; | |
| float farZ = 2000.0f; | |
| kmMat4PerspectiveProjection(&proj, fov, aspect, nearZ, farZ); | |
| // create view matrix | |
| kmMat4 view; | |
| kmVec3 eye = { m_pos.x, m_pos.y, m_pos.z }; | |
| kmVec3 center = { m_aim.x, m_aim.y, m_aim.z }; | |
| kmVec3 up = { 0, 1, 0 }; | |
| kmMat4LookAt(&view, &eye, ¢er, &up); | |
| kmMat4Multiply(&m_projectionViewMatrix, &proj, &view); | |
| m_dirty = false; | |
| return m_projectionViewMatrix; | |
| } | |
| float PerspectiveCamera::getFOV() { | |
| return m_fov; | |
| } | |
| cocos2d::CCPoint3D PerspectiveCamera::get3DPosition() { | |
| return m_pos; | |
| } | |
| cocos2d::CCPoint3D PerspectiveCamera::get3DAim() { | |
| return m_aim; | |
| } | |
| PerspectiveNode::PerspectiveNode(PerspectiveCamera& camera) | |
| : m_dirty(true) | |
| , m_transformationMatrix({ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }) | |
| , m_rot({ 0.f, 0.f, 0.f }) | |
| , m_pos({ 0.f, 0.f, 0.f }) | |
| , m_camera(camera) {} | |
| PerspectiveNode* PerspectiveNode::create(PerspectiveCamera& camera) { | |
| auto ret = new PerspectiveNode(camera); | |
| if (ret->init(camera)) { | |
| ret->autorelease(); | |
| return ret; | |
| } | |
| delete ret; | |
| return nullptr; | |
| } | |
| bool PerspectiveNode::init(PerspectiveCamera& camera) { | |
| if (!CCNode::init()) return false; | |
| setAnchorPoint({ .5f, .5f }); | |
| return true; | |
| } | |
| void PerspectiveNode::visit() { | |
| // store original projection | |
| kmMat4 orig; | |
| kmGLGetMatrix(KM_GL_PROJECTION, &orig); | |
| // set perspective | |
| kmGLMatrixMode(KM_GL_PROJECTION); | |
| auto matrix = m_camera.getProjectionViewMatrix(); | |
| kmGLLoadMatrix(&matrix); | |
| kmGLMatrixMode(KM_GL_MODELVIEW); | |
| m_sTransform = cocos2d::CCAffineTransformMakeIdentity(); // dont use cocos | |
| kmGLPushMatrix(); | |
| matrix = getTransformationMatrix(); | |
| kmGLMultMatrix(&matrix); | |
| CCNode::visit(); | |
| kmGLPopMatrix(); | |
| // restore cocos projection (orthographic projection probably) | |
| kmGLMatrixMode(KM_GL_PROJECTION); | |
| kmGLLoadMatrix(&orig); | |
| kmGLMatrixMode(KM_GL_MODELVIEW); | |
| } | |
| void PerspectiveNode::set3DRotation(cocos2d::CCPoint3D rot) { | |
| m_rot = rot; | |
| m_dirty = true; | |
| } | |
| void PerspectiveNode::set3DPosition(cocos2d::CCPoint3D pos) { | |
| m_pos = pos; | |
| m_dirty = true; | |
| } | |
| kmMat4 PerspectiveNode::getTransformationMatrix() { | |
| if (!m_dirty) return m_transformationMatrix; | |
| kmMat4 matRotX, matRotY, matRotZ, matRot, matTranslation; | |
| kmMat4RotationX(&matRotX, kmDegreesToRadians(m_rot.x)); | |
| kmMat4RotationY(&matRotY, kmDegreesToRadians(m_rot.y)); | |
| kmMat4RotationZ(&matRotZ, kmDegreesToRadians(m_rot.z)); | |
| // z * (y * x) | |
| kmMat4Multiply(&matRot, &matRotY, &matRotX); | |
| kmMat4Multiply(&matRot, &matRotZ, &matRot); | |
| kmMat4Translation(&matTranslation, m_pos.x, m_pos.y, m_pos.z); | |
| // translation * rot | |
| kmMat4Multiply(&m_transformationMatrix, &matTranslation, &matRot); | |
| m_dirty = false; | |
| return m_transformationMatrix; | |
| } | |
| cocos2d::CCPoint3D PerspectiveNode::get3DRotation() { | |
| return m_rot; | |
| } | |
| cocos2d::CCPoint3D PerspectiveNode::get3DPosition() { | |
| return m_pos; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| namespace cocos2d { | |
| struct CCPoint3D { float x, y, z; }; | |
| } | |
| class PerspectiveCamera { | |
| bool m_dirty; | |
| kmMat4 m_projectionViewMatrix; | |
| cocos2d::CCPoint3D m_pos; | |
| cocos2d::CCPoint3D m_aim; | |
| float m_fov; | |
| public: | |
| PerspectiveCamera(); | |
| void setFOV(float fov); | |
| void set3DPosition(cocos2d::CCPoint3D pos); | |
| void set3DAim(cocos2d::CCPoint3D pos); | |
| float getFOV(); | |
| cocos2d::CCPoint3D get3DPosition(); | |
| cocos2d::CCPoint3D get3DAim(); | |
| kmMat4 getProjectionViewMatrix(); | |
| }; | |
| class PerspectiveNode : public cocos2d::CCNode { | |
| PerspectiveNode(PerspectiveCamera& camera); | |
| bool m_dirty; | |
| kmMat4 m_transformationMatrix; | |
| cocos2d::CCPoint3D m_rot; | |
| cocos2d::CCPoint3D m_pos; | |
| public: | |
| static PerspectiveNode* create(PerspectiveCamera& camera); | |
| bool init(PerspectiveCamera& camera); | |
| PerspectiveCamera& m_camera; | |
| void visit() override; | |
| void set3DRotation(cocos2d::CCPoint3D rot); | |
| void set3DPosition(cocos2d::CCPoint3D pos); | |
| cocos2d::CCPoint3D get3DRotation(); | |
| cocos2d::CCPoint3D get3DPosition(); | |
| kmMat4 getTransformationMatrix(); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment