diff --git a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp index 444a4d0f13..f5b4ef4e31 100644 --- a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp +++ b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp @@ -39,7 +39,9 @@ static int sceneIdx = -1; static std::function createFunctions[] = { CL(Camera3DTestDemo), - CL(CameraClippingDemo) + CL(CameraClippingDemo), + CL(CameraArcBallDemo), + CL(FogTestDemo) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) @@ -269,6 +271,7 @@ void Camera3DTestDemo::onEnter() line->drawLine(Vec3(0, -50, 0),Vec3(0,0,0),Color4F(0,0.5,0,1)); line->drawLine(Vec3(0, 0, 0),Vec3(0,50,0),Color4F(0,1,0,1)); _layer3D->addChild(line); + _layer3D->setCameraMask(2); } void Camera3DTestDemo::onExit() @@ -303,9 +306,9 @@ void Camera3DTestDemo::backCallback(Ref* sender) Director::getInstance()->replaceScene(s); s->release(); } + void Camera3DTestDemo::addNewSpriteWithCoords(Vec3 p,std::string fileName,bool playAnimation,float scale,bool bindCamera) { - auto sprite = Sprite3D::create(fileName); _layer3D->addChild(sprite); float globalZOrder=sprite->getGlobalZOrder(); @@ -324,8 +327,7 @@ void Camera3DTestDemo::addNewSpriteWithCoords(Vec3 p,std::string fileName,bool p { _sprite3D=sprite; } - sprite->setScale(scale); - + sprite->setScale(scale); } void Camera3DTestDemo::onTouchesBegan(const std::vector& touches, cocos2d::Event *event) { @@ -708,7 +710,6 @@ void CameraClippingDemo::onEnter() { BaseTest::onEnter(); schedule(schedule_selector(CameraClippingDemo::update), 0.0f); - auto s = Director::getInstance()->getWinSize(); auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan = CC_CALLBACK_2(CameraClippingDemo::onTouchesBegan, this); @@ -963,6 +964,488 @@ void CameraClippingDemo::drawCameraFrustum() _drawFrustum->drawLine(bl_1, tl_1, color); } +//////////////////////////////////////////////////////////// +// CameraArcBallDemo +CameraArcBallDemo::CameraArcBallDemo(void) +: BaseTest() +, _layer3D(nullptr) +, _cameraType(CameraType::FreeCamera) +, _camera(nullptr) +,_drawGrid(nullptr) +,_sprite3D1(nullptr) +,_sprite3D2(nullptr) +,_fRadius(1.0f) +,_distanceX(0.0f) +,_distanceZ(50.0f) +,_operate(OperateCamType::RotateCamera) +,_center(Vec3(0,0,0)) +,_target(0) +{ +} +CameraArcBallDemo::~CameraArcBallDemo(void) +{ +} + +std::string CameraArcBallDemo::title() const +{ + return "Camera ArcBall Moving"; +} + +void CameraArcBallDemo::restartCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild(restartSpriteTestAction()); + + Director::getInstance()->replaceScene(s); + s->release(); +} + +void CameraArcBallDemo::nextCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild( nextSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); +} + +void CameraArcBallDemo::backCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild( backSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); +} + +void CameraArcBallDemo::onEnter() +{ + BaseTest::onEnter(); + _rotationQuat.set(0.0f, 0.0f, 0.0f, 1.0f); + schedule(schedule_selector(CameraArcBallDemo::update), 0.0f); + auto s = Director::getInstance()->getWinSize(); + auto listener = EventListenerTouchAllAtOnce::create(); + listener->onTouchesMoved = CC_CALLBACK_2(CameraArcBallDemo::onTouchsMoved, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); + + // swich camera + MenuItemFont::setFontName("fonts/arial.ttf"); + MenuItemFont::setFontSize(20); + + auto menuItem1 = MenuItemFont::create("Switch Operation", CC_CALLBACK_1(CameraArcBallDemo::switchOperateCallback,this)); + menuItem1->setColor(Color3B(0,200,20)); + auto menuItem2 = MenuItemFont::create("Switch Target", CC_CALLBACK_1(CameraArcBallDemo::switchTargetCallback,this)); + menuItem2->setColor(Color3B(0,200,20)); + auto menu = Menu::create(menuItem1,menuItem2,NULL); + menu->setPosition(Vec2::ZERO); + menuItem1->setPosition(VisibleRect::left().x + 80, VisibleRect::top().y -70); + menuItem2->setPosition(VisibleRect::left().x + 80, VisibleRect::top().y -100); + addChild(menu, 1); + + auto layer3D=Layer::create(); + addChild(layer3D,0); + _layer3D=layer3D; + + if (_camera == nullptr) + { + _camera=Camera::createPerspective(60, (GLfloat)s.width/s.height, 1, 1000); + _camera->setCameraFlag(CameraFlag::USER1); + _camera->setPosition3D(Vec3(0, 100, 50)); + _camera->lookAt(Vec3(0, 0, 0), Vec3(0, 1, 0)); + _camera->retain(); + _layer3D->addChild(_camera); + } + + _sprite3D1 = Sprite3D::create("Sprite3DTest/orc.c3b"); + _sprite3D1->setScale(0.5); + _sprite3D1->setRotation3D(Vec3(0,180,0)); + _sprite3D1->setPosition3D(Vec3(0,0,0)); + _layer3D->addChild(_sprite3D1); + + _sprite3D2 = Sprite3D::create("Sprite3DTest/boss.c3b"); + _sprite3D2->setScale(0.6); + _sprite3D2->setRotation3D(Vec3(-90,0,0)); + _sprite3D2->setPosition3D(Vec3(20,0,0)); + _layer3D->addChild(_sprite3D2); + + _drawGrid =DrawNode3D::create(); + + //draw x + for( int j =-20; j<=20 ;j++) + { + _drawGrid->drawLine(Vec3(-100, 0, 5*j),Vec3(100,0,5*j),Color4F(1,0,0,1)); + } + //draw z + for( int j =-20; j<=20 ;j++) + { + _drawGrid->drawLine(Vec3(5*j, 0, -100),Vec3(5*j,0,100),Color4F(0,0,1,1)); + } + //draw y + _drawGrid->drawLine(Vec3(0, 0, 0),Vec3(0,50,0),Color4F(0,1,0,1)); + _layer3D->addChild(_drawGrid); + + _layer3D->setCameraMask(2); + + updateCameraTransform(); + +} + +void CameraArcBallDemo::onExit() +{ + BaseTest::onExit(); + if (_camera) + { + _camera = nullptr; + } +} + +void CameraArcBallDemo::onTouchsMoved( const std::vector &touchs, Event *event ) +{ + if (!touchs.empty()) + { + if(_operate == OperateCamType::RotateCamera) + { + Size visibleSize = Director::getInstance()->getVisibleSize(); + Vec2 prelocation = touchs[0]->getPreviousLocationInView(); + Vec2 location = touchs[0]->getLocationInView(); + location.x = 2.0 * (location.x) / (visibleSize.width) - 1.0f; + location.y = 2.0 * (visibleSize.height - location.y) / (visibleSize.height) - 1.0f; + prelocation.x = 2.0 * (prelocation.x) / (visibleSize.width) - 1.0f; + prelocation.y = 2.0 * (visibleSize.height - prelocation.y) / (visibleSize.height) - 1.0f; + + Vec3 axes; + float angle; + calculateArcBall(axes, angle, prelocation.x, prelocation.y, location.x, location.y); + Quaternion quat(axes, angle); + _rotationQuat = quat * _rotationQuat; + + updateCameraTransform(); + } + else if(_operate == OperateCamType::MoveCamera) + { + Point newPos = touchs[0]->getPreviousLocation() - touchs[0]->getLocation(); + _distanceZ -= newPos.y*0.1f; + _distanceZ += newPos.x*0.1f; + + updateCameraTransform(); + } + } +} + +void CameraArcBallDemo::calculateArcBall( cocos2d::Vec3 & axis, float & angle, float p1x, float p1y, float p2x, float p2y ) +{ + Mat4 rotation_matrix; + Mat4::createRotation(_rotationQuat, &rotation_matrix); + + Vec3 uv = rotation_matrix * Vec3(0.0f,1.0f,0.0f); + Vec3 sv = rotation_matrix * Vec3(1.0f,0.0f,0.0f); + Vec3 lv = rotation_matrix * Vec3(0.0f,0.0f,-1.0f); + + Vec3 p1 = sv * p1x + uv * p1y - lv * projectToSphere(_fRadius, p1x, p1y); + Vec3 p2 = sv * p2x + uv * p2y - lv * projectToSphere(_fRadius, p2x, p2y); + + Vec3::cross(p2, p1, &axis); + axis.normalize(); + + float t = (p2 - p1).length() / (2.0 * _fRadius); + + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + angle = asin(t); +} + +float CameraArcBallDemo::projectToSphere( float r, float x, float y ) +{ + float d, t, z; + d = sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440) + { + z = sqrt(r*r - d*d); + } + else + { + t = r / 1.41421356237309504880; + z = t*t / d; + } + return z; +} + +void CameraArcBallDemo::updateCameraTransform() +{ + Mat4 trans, rot, center; + Mat4::createTranslation(Vec3(_distanceX, 0.0f, _distanceZ), &trans); + Mat4::createRotation(_rotationQuat, &rot); + Mat4::createTranslation(_center, ¢er); + Mat4 result = center * rot * trans; + _camera->setNodeToParentTransform(result); + +} + +void CameraArcBallDemo::switchOperateCallback(Ref* sender) +{ + if(_operate == OperateCamType::MoveCamera) + { + _operate = OperateCamType::RotateCamera; + } + else if(_operate == OperateCamType::RotateCamera) + { + _operate = OperateCamType::MoveCamera; + } +} + +void CameraArcBallDemo::switchTargetCallback(Ref* sender) +{ + if(_target == 0) + { + _target = 1; + _center = _sprite3D2->getPosition3D(); + updateCameraTransform(); + } + else if(_target == 1) + { + _target = 0; + _center = _sprite3D1->getPosition3D(); + updateCameraTransform(); + } +} + +void CameraArcBallDemo::update(float dt) +{ + //updateCameraTransform(); +} + +//////////////////////////////////////////////////////////// +// FogTestDemo +FogTestDemo::FogTestDemo(void) +: BaseTest() +, _layer3D(nullptr) +, _cameraType(CameraType::FreeCamera) +, _camera(nullptr) +, _shader(nullptr) +, _state(nullptr) +{ +} +FogTestDemo::~FogTestDemo(void) +{ +} + +std::string FogTestDemo::title() const +{ + return "Fog Test Demo"; +} + +void FogTestDemo::restartCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild(restartSpriteTestAction()); + + Director::getInstance()->replaceScene(s); + s->release(); +} + +void FogTestDemo::nextCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild( nextSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); +} + +void FogTestDemo::backCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild( backSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); +} + +void FogTestDemo::onEnter() +{ + BaseTest::onEnter(); + schedule(schedule_selector(FogTestDemo::update), 0.0f); + + auto s = Director::getInstance()->getWinSize(); + auto listener = EventListenerTouchAllAtOnce::create(); + listener->onTouchesBegan = CC_CALLBACK_2(FogTestDemo::onTouchesBegan, this); + listener->onTouchesMoved = CC_CALLBACK_2(FogTestDemo::onTouchesMoved, this); + listener->onTouchesEnded = CC_CALLBACK_2(FogTestDemo::onTouchesEnded, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); + + // swich fog type + TTFConfig ttfConfig("fonts/arial.ttf", 20); + + auto label1 = Label::createWithTTF(ttfConfig,"Linear "); + auto menuItem1 = MenuItemLabel::create(label1, CC_CALLBACK_1(FogTestDemo::switchTypeCallback,this,0)); + auto label2 = Label::createWithTTF(ttfConfig,"Exp"); + auto menuItem2 = MenuItemLabel::create(label2, CC_CALLBACK_1(FogTestDemo::switchTypeCallback,this,1)); + auto label3 = Label::createWithTTF(ttfConfig,"Exp2"); + auto menuItem3 = MenuItemLabel::create(label3, CC_CALLBACK_1(FogTestDemo::switchTypeCallback,this,2)); + auto menu = Menu::create(menuItem1, menuItem2, menuItem3, nullptr); + + menu->setPosition(Vec2::ZERO); + + menuItem1->setPosition(VisibleRect::left().x+60, VisibleRect::top().y-50); + menuItem2->setPosition(VisibleRect::left().x+60, VisibleRect::top().y -100); + menuItem3->setPosition(VisibleRect::left().x+60, VisibleRect::top().y -150); + addChild(menu, 0); + + + auto layer3D=Layer::create(); + addChild(layer3D,0); + _layer3D=layer3D; + + + glClearColor(0.5,0.5,0.5,1.0); + _shader =GLProgram::createWithFilenames("Sprite3DTest/fog.vert","Sprite3DTest/fog.frag"); + _state = GLProgramState::create(_shader); + + _sprite3D1 = Sprite3D::create("Sprite3DTest/teapot.c3b"); + _sprite3D2 = Sprite3D::create("Sprite3DTest/teapot.c3b"); + + _sprite3D1->setGLProgramState(_state); + _sprite3D2->setGLProgramState(_state); + //pass mesh's attribute to shader + long offset = 0; + auto attributeCount = _sprite3D1->getMesh()->getMeshVertexAttribCount(); + for (auto i = 0; i < attributeCount; i++) { + auto meshattribute = _sprite3D1->getMesh()->getMeshVertexAttribute(i); + _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], + meshattribute.size, + meshattribute.type, + GL_FALSE, + _sprite3D1->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); + offset += meshattribute.attribSizeBytes; + } + + long offset1 = 0; + auto attributeCount1 = _sprite3D2->getMesh()->getMeshVertexAttribCount(); + for (auto i = 0; i < attributeCount1; i++) { + auto meshattribute = _sprite3D2->getMesh()->getMeshVertexAttribute(i); + _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], + meshattribute.size, + meshattribute.type, + GL_FALSE, + _sprite3D2->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset1); + offset1 += meshattribute.attribSizeBytes; + } + + _state->setUniformVec4("fogColor", Vec4(0.5,0.5,0.5,1.0)); + _state->setUniformFloat("fStart",10); + _state->setUniformFloat("fEnd",60); + _state->setUniformInt("iEquation" ,0); + + _layer3D->addChild(_sprite3D1); + _sprite3D1->setPosition3D( Vec3( 0, 0,0 ) ); + _sprite3D1->setScale(2.0f); + _sprite3D1->setRotation3D(Vec3(-90,180,0)); + + _layer3D->addChild(_sprite3D2); + _sprite3D2->setPosition3D( Vec3( 0, 0,-20 ) ); + _sprite3D2->setScale(2.0f); + _sprite3D2->setRotation3D(Vec3(-90,180,0)); + + if (_camera == nullptr) + { + _camera=Camera::createPerspective(60, (GLfloat)s.width/s.height, 1, 1000); + _camera->setCameraFlag(CameraFlag::USER1); + _camera->setPosition3D(Vec3(0, 30, 40)); + _camera->lookAt(Vec3(0,0,0), Vec3(0, 1, 0)); + + _layer3D->addChild(_camera); + } + _layer3D->setCameraMask(2); + +} + +void FogTestDemo::switchTypeCallback(Ref* sender,int type) +{ + if(type == 0) + { + _state->setUniformVec4("fogColor", Vec4(0.5,0.5,0.5,1.0)); + _state->setUniformFloat("fStart",10); + _state->setUniformFloat("fEnd",60); + _state->setUniformInt("iEquation" ,0); + + _sprite3D1->setGLProgramState(_state); + _sprite3D2->setGLProgramState(_state); + } + else if(type == 1) + { + _state->setUniformVec4("fogColor", Vec4(0.5,0.5,0.5,1.0)); + _state->setUniformFloat("fogDensity",0.03); + _state->setUniformInt("iEquation" ,1); + + _sprite3D1->setGLProgramState(_state); + _sprite3D2->setGLProgramState(_state); + } + else if(type == 2) + { + _state->setUniformVec4("fogColor", Vec4(0.5,0.5,0.5,1.0)); + _state->setUniformFloat("fogDensity",0.03); + _state->setUniformInt("iEquation" ,2); + + _sprite3D1->setGLProgramState(_state); + _sprite3D2->setGLProgramState(_state); + } +} + +void FogTestDemo::onExit() +{ + BaseTest::onExit(); + glClearColor(0.0,0.0,0.0,1.0); + if (_camera) + { + _camera = nullptr; + } +} + +void FogTestDemo::update(float dt) +{ +} + +void FogTestDemo::onTouchesBegan(const std::vector& touches, cocos2d::Event *event) +{ + for ( auto &item: touches ) + { + auto touch = item; + auto location = touch->getLocation(); + } +} + +void FogTestDemo::onTouchesMoved(const std::vector& touches, cocos2d::Event *event) +{ + if(touches.size()==1) + { + auto touch = touches[0]; + auto location = touch->getLocation(); + Point newPos = touch->getPreviousLocation()-location; + if(_cameraType==CameraType::FreeCamera) + { + Vec3 cameraDir; + Vec3 cameraRightDir; + _camera->getNodeToWorldTransform().getForwardVector(&cameraDir); + cameraDir.normalize(); + cameraDir.y=0; + _camera->getNodeToWorldTransform().getRightVector(&cameraRightDir); + cameraRightDir.normalize(); + cameraRightDir.y=0; + Vec3 cameraPos= _camera->getPosition3D(); + cameraPos+=cameraDir*newPos.y*0.1f; + cameraPos+=cameraRightDir*newPos.x*0.1f; + _camera->setPosition3D(cameraPos); + } + } +} + +void FogTestDemo::onTouchesEnded(const std::vector& touches, cocos2d::Event *event) +{ + for ( auto &item: touches ) + { + auto touch = item; + auto location = touch->getLocationInView(); + } +} + void Camera3DTestScene::runThisTest() { auto layer = nextSpriteTestAction(); diff --git a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h index 21eb61a872..992336718c 100644 --- a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h +++ b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h @@ -52,6 +52,13 @@ enum class CameraType FirstCamera=1, ThirdCamera=2, }; + +enum class OperateCamType +{ + MoveCamera=0, + RotateCamera=1, +}; + class Camera3DTestDemo : public BaseTest { public: @@ -148,6 +155,83 @@ protected: int _row; }; +class CameraArcBallDemo : public BaseTest +{ +public: + CREATE_FUNC(CameraArcBallDemo); + CameraArcBallDemo(void); + virtual ~CameraArcBallDemo(void); + + void restartCallback(Ref* sender); + void nextCallback(Ref* sender); + void backCallback(Ref* sender); + + virtual void onEnter() override; + virtual void onExit() override; + + virtual void update(float dt) override; + + // overrides + virtual std::string title() const override; + + void switchOperateCallback(Ref* sender); + void switchTargetCallback(Ref* sender); + void onTouchsMoved(const std::vector &touchs, cocos2d::Event *event); + void updateCameraTransform(); + void calculateArcBall( cocos2d::Vec3 & axis, float & angle, float p1x, float p1y, float p2x, float p2y ); + float projectToSphere( float r, float x, float y ); + +protected: + Layer* _layer3D; + CameraType _cameraType; + Camera* _camera; + DrawNode3D* _drawGrid; + Quaternion _rotationQuat; + float _fRadius; + float _distanceX; + float _distanceZ; + OperateCamType _operate; + Vec3 _center; + int _target; + Sprite3D* _sprite3D1; + Sprite3D* _sprite3D2; +}; + +class FogTestDemo : public BaseTest +{ +public: + CREATE_FUNC(FogTestDemo); + FogTestDemo(void); + virtual ~FogTestDemo(void); + + void restartCallback(Ref* sender); + void nextCallback(Ref* sender); + void backCallback(Ref* sender); + + virtual void onEnter() override; + virtual void onExit() override; + + virtual void update(float dt) override; + + // overrides + virtual std::string title() const override; + + void onTouchesBegan(const std::vector& touches, cocos2d::Event *event); + void onTouchesMoved(const std::vector& touches, cocos2d::Event *event); + void onTouchesEnded(const std::vector& touches, cocos2d::Event *event); + + void switchTypeCallback(Ref* sender,int type); + +protected: + Layer* _layer3D; + CameraType _cameraType; + Camera* _camera; + Sprite3D* _sprite3D1; + Sprite3D* _sprite3D2; + GLProgram* _shader; + GLProgramState* _state; +}; + class Camera3DTestScene : public TestScene { public: diff --git a/tests/cpp-tests/Resources/Sprite3DTest/fog.frag b/tests/cpp-tests/Resources/Sprite3DTest/fog.frag new file mode 100644 index 0000000000..74f3951e62 --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/fog.frag @@ -0,0 +1,14 @@ +#ifdef GL_ES +varying mediump vec2 v_texture_coord; +#else +varying vec2 v_texture_coord; +#endif +varying float fogFactor; + +uniform vec4 fogColor; + +void main (void) +{ + vec4 finalColor = texture2D(CC_Texture0, v_texture_coord); + gl_FragColor = mix(fogColor, finalColor, fogFactor ); //根据雾的权重与finalColor 做混合操作 +} \ No newline at end of file diff --git a/tests/cpp-tests/Resources/Sprite3DTest/fog.vert b/tests/cpp-tests/Resources/Sprite3DTest/fog.vert new file mode 100644 index 0000000000..02c0731761 --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/fog.vert @@ -0,0 +1,29 @@ +attribute vec4 a_position; +attribute vec2 a_texCoord; +varying float fogFactor; //雾的权重 +varying vec2 v_texture_coord; + +uniform float fogDensity;// For exp and exp2 equation +uniform float fStart; // This is only for linear fog +uniform float fEnd; // This is only for linear fog +uniform int iEquation; // 0 = linear, 1 = exp, 2 = exp2 + +void main(void) +{ + gl_Position = CC_MVPMatrix * a_position; + v_texture_coord = a_texCoord; + + gl_FogFragCoord = abs(gl_Position.z); //这样获得距离效率较高 + + + if(iEquation == 0) + fogFactor = (fEnd-gl_FogFragCoord )/(fEnd-fStart); + else if(iEquation == 1) + fogFactor = exp(-fogDensity*gl_FogFragCoord ); + else if(iEquation == 2) + fogFactor = exp(-pow(fogDensity*gl_FogFragCoord , 2.0)); + + + fogFactor = clamp(fogFactor, 0.0, 1.0); //越界处理 + +}