From ee99700ec1ad3fe6894a3a0586b8263041bb825f Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Thu, 29 Jan 2015 09:28:14 +0800 Subject: [PATCH 01/27] add test case TextureCube --- build/cocos2d_libs.xcodeproj/project.pbxproj | 24 ++ cocos/2d/libcocos2d.vcxproj | 4 + cocos/2d/libcocos2d.vcxproj.filters | 9 + cocos/3d/Android.mk | 4 +- cocos/3d/CCSkybox.cpp | 278 ++++++++++++++++++ cocos/3d/CCSkybox.h | 83 ++++++ cocos/3d/CCTextureCube.cpp | 250 ++++++++++++++++ cocos/3d/CCTextureCube.h | 67 +++++ cocos/renderer/CCGLProgramState.cpp | 7 +- cocos/renderer/ccGLStateCache.cpp | 6 +- cocos/renderer/ccGLStateCache.h | 2 +- .../Classes/Sprite3DTest/Sprite3DTest.cpp | 97 +++++- .../Classes/Sprite3DTest/Sprite3DTest.h | 20 ++ .../Resources/Sprite3DTest/cube_map.frag | 8 + .../Resources/Sprite3DTest/cube_map.vert | 16 + .../Resources/Sprite3DTest/skybox.frag | 8 + .../Resources/Sprite3DTest/skybox.vert | 15 + .../Resources/Sprite3DTest/skybox/back.jpg | Bin 0 -> 24753 bytes .../Resources/Sprite3DTest/skybox/bottom.jpg | Bin 0 -> 43625 bytes .../Resources/Sprite3DTest/skybox/front.jpg | Bin 0 -> 25785 bytes .../Resources/Sprite3DTest/skybox/left.jpg | Bin 0 -> 25271 bytes .../Resources/Sprite3DTest/skybox/right.jpg | Bin 0 -> 31151 bytes .../Resources/Sprite3DTest/skybox/top.jpg | Bin 0 -> 35377 bytes 23 files changed, 891 insertions(+), 7 deletions(-) create mode 100644 cocos/3d/CCSkybox.cpp create mode 100644 cocos/3d/CCSkybox.h create mode 100644 cocos/3d/CCTextureCube.cpp create mode 100644 cocos/3d/CCTextureCube.h create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/cube_map.frag create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/cube_map.vert create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox.frag create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox.vert create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox/back.jpg create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox/bottom.jpg create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox/front.jpg create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox/left.jpg create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox/right.jpg create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/skybox/top.jpg diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj b/build/cocos2d_libs.xcodeproj/project.pbxproj index e98e05740e..bf012e3cc1 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj @@ -1936,6 +1936,14 @@ B63990CD1A490AFE00B07923 /* CCAsyncTaskPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B63990CA1A490AFE00B07923 /* CCAsyncTaskPool.cpp */; }; B63990CE1A490AFE00B07923 /* CCAsyncTaskPool.h in Headers */ = {isa = PBXBuildFile; fileRef = B63990CB1A490AFE00B07923 /* CCAsyncTaskPool.h */; }; B63990CF1A490AFE00B07923 /* CCAsyncTaskPool.h in Headers */ = {isa = PBXBuildFile; fileRef = B63990CB1A490AFE00B07923 /* CCAsyncTaskPool.h */; }; + BCB71E9E1A776E1D00B29EE0 /* CCSkybox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCB71E9C1A776E1D00B29EE0 /* CCSkybox.cpp */; }; + BCB71E9F1A776E1D00B29EE0 /* CCSkybox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCB71E9C1A776E1D00B29EE0 /* CCSkybox.cpp */; }; + BCB71EA01A776E1D00B29EE0 /* CCSkybox.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB71E9D1A776E1D00B29EE0 /* CCSkybox.h */; }; + BCB71EA11A776E1D00B29EE0 /* CCSkybox.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB71E9D1A776E1D00B29EE0 /* CCSkybox.h */; }; + BCC3E1E71A75E5140082DCDB /* CCTextureCube.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCC3E1E51A75E5140082DCDB /* CCTextureCube.cpp */; }; + BCC3E1E81A75E5140082DCDB /* CCTextureCube.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCC3E1E51A75E5140082DCDB /* CCTextureCube.cpp */; }; + BCC3E1E91A75E5140082DCDB /* CCTextureCube.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC3E1E61A75E5140082DCDB /* CCTextureCube.h */; }; + BCC3E1EA1A75E5140082DCDB /* CCTextureCube.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC3E1E61A75E5140082DCDB /* CCTextureCube.h */; }; D0FD03491A3B51AA00825BB5 /* CCAllocatorBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D0FD033B1A3B51AA00825BB5 /* CCAllocatorBase.h */; }; D0FD034A1A3B51AA00825BB5 /* CCAllocatorBase.h in Headers */ = {isa = PBXBuildFile; fileRef = D0FD033B1A3B51AA00825BB5 /* CCAllocatorBase.h */; }; D0FD034B1A3B51AA00825BB5 /* CCAllocatorDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0FD033C1A3B51AA00825BB5 /* CCAllocatorDiagnostics.cpp */; }; @@ -3033,6 +3041,10 @@ B67C624319D4186F00F11FC6 /* ccShader_3D_ColorNormal.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_ColorNormal.frag; sourceTree = ""; }; B67C624419D4186F00F11FC6 /* ccShader_3D_ColorNormalTex.frag */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_ColorNormalTex.frag; sourceTree = ""; }; B67C624519D4186F00F11FC6 /* ccShader_3D_PositionNormalTex.vert */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; path = ccShader_3D_PositionNormalTex.vert; sourceTree = ""; }; + BCB71E9C1A776E1D00B29EE0 /* CCSkybox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCSkybox.cpp; sourceTree = ""; }; + BCB71E9D1A776E1D00B29EE0 /* CCSkybox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCSkybox.h; sourceTree = ""; }; + BCC3E1E51A75E5140082DCDB /* CCTextureCube.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCTextureCube.cpp; sourceTree = ""; }; + BCC3E1E61A75E5140082DCDB /* CCTextureCube.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCTextureCube.h; sourceTree = ""; }; D0FD033B1A3B51AA00825BB5 /* CCAllocatorBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAllocatorBase.h; sourceTree = ""; }; D0FD033C1A3B51AA00825BB5 /* CCAllocatorDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCAllocatorDiagnostics.cpp; sourceTree = ""; }; D0FD033D1A3B51AA00825BB5 /* CCAllocatorDiagnostics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCAllocatorDiagnostics.h; sourceTree = ""; }; @@ -5170,6 +5182,10 @@ B29594B81926D61F003EEF37 /* 3d */ = { isa = PBXGroup; children = ( + BCB71E9C1A776E1D00B29EE0 /* CCSkybox.cpp */, + BCB71E9D1A776E1D00B29EE0 /* CCSkybox.h */, + BCC3E1E51A75E5140082DCDB /* CCTextureCube.cpp */, + BCC3E1E61A75E5140082DCDB /* CCTextureCube.h */, 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */, 5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */, 5E9F61241A3FFE3D0038DE01 /* CCPlane.cpp */, @@ -5386,10 +5402,12 @@ 1AC0269C1914068200FA920D /* ConvertUTF.h in Headers */, 15AE1A7119AAD40300C27E9E /* b2Contact.h in Headers */, 50ABBED11925AB6F00A911A9 /* TGAlib.h in Headers */, + BCC3E1E91A75E5140082DCDB /* CCTextureCube.h in Headers */, 1A57019F180BCB590088DEC7 /* CCFont.h in Headers */, DA8C62A419E52C6400000516 /* ioapi_mem.h in Headers */, 1A5701A3180BCB590088DEC7 /* CCFontAtlas.h in Headers */, 15AE18E919AAD35000C27E9E /* CCActionManagerEx.h in Headers */, + BCB71EA01A776E1D00B29EE0 /* CCSkybox.h in Headers */, 1A01C68618F57BE800EFE3A6 /* CCArray.h in Headers */, 1A5701A7180BCB590088DEC7 /* CCFontAtlasCache.h in Headers */, 15AE1A7D19AAD40300C27E9E /* b2MotorJoint.h in Headers */, @@ -6100,6 +6118,7 @@ 15B3707F19EE414C00ABE682 /* CCEventAssetsManagerEx.h in Headers */, 1AC0269D1914068200FA920D /* ConvertUTF.h in Headers */, 15AE1A4419AAD3D500C27E9E /* b2DynamicTree.h in Headers */, + BCB71EA11A776E1D00B29EE0 /* CCSkybox.h in Headers */, 1A5702FD180BCE750088DEC7 /* CCTMXXMLParser.h in Headers */, 15AE1AC519AAD40300C27E9E /* b2FrictionJoint.h in Headers */, 15AE1B8D19AADA9A00C27E9E /* UIScale9Sprite.h in Headers */, @@ -6235,6 +6254,7 @@ 50ABBE261925AB6F00A911A9 /* base64.h in Headers */, 15AE1C1619AAE2C700C27E9E /* CCPhysicsDebugNode.h in Headers */, 15AE1BF619AAE01E00C27E9E /* CCControlSlider.h in Headers */, + BCC3E1EA1A75E5140082DCDB /* CCTextureCube.h in Headers */, 1A01C68718F57BE800EFE3A6 /* CCArray.h in Headers */, 1A01C6A718F58F7500EFE3A6 /* CCNotificationCenter.h in Headers */, 50ABBEDA1925AB6F00A911A9 /* ZipUtils.h in Headers */, @@ -6528,6 +6548,7 @@ 15AE18FF19AAD35000C27E9E /* CCComAudio.cpp in Sources */, 1A5701C7180BCB5A0088DEC7 /* CCLabelTextFormatter.cpp in Sources */, 15AE18A819AAD33D00C27E9E /* CCSpriteLoader.cpp in Sources */, + BCB71E9E1A776E1D00B29EE0 /* CCSkybox.cpp in Sources */, 1A5701CB180BCB5A0088DEC7 /* CCLabelTTF.cpp in Sources */, 50ABBE711925AB6F00A911A9 /* CCEventListenerMouse.cpp in Sources */, 1A5701DE180BCB8C0088DEC7 /* CCLayer.cpp in Sources */, @@ -6693,6 +6714,7 @@ 464AD6E5197EBB1400E502D8 /* pvr.cpp in Sources */, 50ABBDA31925AB4100A911A9 /* CCQuadCommand.cpp in Sources */, 15AE19A219AAD39600C27E9E /* TextBMFontReader.cpp in Sources */, + BCC3E1E71A75E5140082DCDB /* CCTextureCube.cpp in Sources */, 382384281A2590F9002C4610 /* NodeReader.cpp in Sources */, 50ABC01D1926664800A911A9 /* CCThread.cpp in Sources */, 15AE180C19AAD2F700C27E9E /* CCAnimate3D.cpp in Sources */, @@ -6849,6 +6871,7 @@ 15AE182519AAD2F700C27E9E /* CCMesh.cpp in Sources */, 503DD8EE1926736A00CD74DD /* CCImage-ios.mm in Sources */, 46A170FC1807CECB005B8026 /* CCPhysicsBody.cpp in Sources */, + BCB71E9F1A776E1D00B29EE0 /* CCSkybox.cpp in Sources */, 15AE1BEA19AAE01E00C27E9E /* CCControlButton.cpp in Sources */, 50ABBD941925AB4100A911A9 /* CCGLProgramState.cpp in Sources */, B257B44F1989D5E800D9A687 /* CCPrimitive.cpp in Sources */, @@ -7115,6 +7138,7 @@ 15AE1C1719AAE2C700C27E9E /* CCPhysicsSprite.cpp in Sources */, 1A5702EB180BCE750088DEC7 /* CCTileMapAtlas.cpp in Sources */, 1A5702EF180BCE750088DEC7 /* CCTMXLayer.cpp in Sources */, + BCC3E1E81A75E5140082DCDB /* CCTextureCube.cpp in Sources */, 15AE1BA519AADFDF00C27E9E /* UIHBox.cpp in Sources */, 1A5702F3180BCE750088DEC7 /* CCTMXObjectGroup.cpp in Sources */, 382384221A2590DA002C4610 /* GameMapReader.cpp in Sources */, diff --git a/cocos/2d/libcocos2d.vcxproj b/cocos/2d/libcocos2d.vcxproj index fb0b1f4062..2a3490c64f 100644 --- a/cocos/2d/libcocos2d.vcxproj +++ b/cocos/2d/libcocos2d.vcxproj @@ -239,6 +239,8 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + + @@ -608,7 +610,9 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + + diff --git a/cocos/2d/libcocos2d.vcxproj.filters b/cocos/2d/libcocos2d.vcxproj.filters index 7862cbe2c6..4da4217a2c 100644 --- a/cocos/2d/libcocos2d.vcxproj.filters +++ b/cocos/2d/libcocos2d.vcxproj.filters @@ -1301,6 +1301,10 @@ + + 3d + + 3d @@ -2547,6 +2551,11 @@ physics + + 3d + + + 3d diff --git a/cocos/3d/Android.mk b/cocos/3d/Android.mk index 9710c56be0..da02ad5649 100644 --- a/cocos/3d/Android.mk +++ b/cocos/3d/Android.mk @@ -21,7 +21,9 @@ CCMeshVertexIndexData.cpp \ CCSprite3DMaterial.cpp \ CCObjLoader.cpp \ CCSkeleton3D.cpp \ -CCSprite3D.cpp +CCSprite3D.cpp \ +CCSkybox.cpp \ +CCTextureCube.cpp LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.. diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp new file mode 100644 index 0000000000..ab298c5cc1 --- /dev/null +++ b/cocos/3d/CCSkybox.cpp @@ -0,0 +1,278 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "CCSkybox.h" + +NS_CC_BEGIN + + +Skybox::Skybox() + : _vao(0) + , _vbo(0) + , _bufferCapacity(0) + , _bufferCount(0) + , _buffer(nullptr) + , _dirty(false) + ,_texture(nullptr) +{ +} + +Skybox::~Skybox() +{ + free(_buffer); + _buffer = nullptr; + + glDeleteBuffers(1, &_vbo); + _vbo = 0; + + if (Configuration::getInstance()->supportsShareableVAO()) + { + glDeleteVertexArrays(1, &_vao); + GL::bindVAO(0); + _vao = 0; + } + + _texture->release(); +} + +Skybox* Skybox::create() +{ + Skybox* ret = new (std::nothrow) Skybox(); + if (ret && ret->init()) + { + ret->autorelease(); + } + else + { + CC_SAFE_DELETE(ret); + } + + return ret; +} + +void Skybox::ensureCapacity(int count) +{ + CCASSERT(count>=0, "capacity must be >= 0"); + + if(_bufferCount + count > _bufferCapacity) + { + _bufferCapacity += MAX(_bufferCapacity, count); + _buffer = (V3F_C4B*)realloc(_buffer, _bufferCapacity*sizeof(V3F_C4B)); + } +} + +bool Skybox::init() +{ + //setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR)); + //create and set our custom shader + auto shader = GLProgram::createWithFilenames("Sprite3DTest/skybox.vert", "Sprite3DTest/skybox.frag"); + auto state = GLProgramState::create(shader); + setGLProgramState(state); + + ensureCapacity(512); + + if (Configuration::getInstance()->supportsShareableVAO()) + { + glGenVertexArrays(1, &_vao); + GL::bindVAO(_vao); + } + + glGenBuffers(1, &_vbo); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B)* _bufferCapacity, _buffer, GL_STREAM_DRAW); + + glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, vertices)); + + glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR); + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, colors)); + + glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD); + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD,2,GL_FLOAT,GL_FALSE,sizeof(V3F_C4B),(GLvoid*)offsetof(V3F_C4B, texcoord)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + if (Configuration::getInstance()->supportsShareableVAO()) + { + GL::bindVAO(0); + } + + CHECK_GL_ERROR_DEBUG(); + + _dirty = true; + +#if CC_ENABLE_CACHE_TEXTURE_DATA + // Need to listen the event only when not use batchnode, because it will use VBO + auto listener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, [this](EventCustom* event) + { + /** listen the event that coming to foreground on Android */ + this->init(); + }); + + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); +#endif + + return true; +} + +void Skybox::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) +{ + _customCommand.init(_globalZOrder); + _customCommand.func = CC_CALLBACK_0(Skybox::onDraw, this, transform, flags); + renderer->addCommand(&_customCommand); +} + +void Skybox::onDraw(const Mat4& transform, uint32_t flags) +{ + auto state = getGLProgramState(); + state->applyGLProgram(transform); + state->applyUniforms(); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + + if (_dirty) + { + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B)*_bufferCapacity, _buffer, GL_STREAM_DRAW); + _dirty = false; + } + + if (Configuration::getInstance()->supportsShareableVAO()) + { + GL::bindVAO(_vao); + } + else + { + GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); + + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + // vertex + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, vertices)); + + // color + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, colors)); + + //texcoord + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD,2,GL_FLOAT,GL_FALSE,sizeof(V3F_C4B),(GLvoid*)offsetof(V3F_C4B, texcoord)); + } + + glDrawArrays(GL_TRIANGLES, 0, _bufferCount); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _bufferCount); + + glCullFace(GL_BACK); + glDisable(GL_DEPTH_TEST); + + CHECK_GL_ERROR_DEBUG(); +} + +void Skybox::drawSlice(Vec3* points, const Color4F& color) +{ + unsigned int vertex_count = 6; + ensureCapacity(vertex_count); + + Color4B col = Color4B(color); + V3F_C4B a = {Vec3(points[0].x, points[0].y, points[0].z), col, Tex2F(0,0)}; + V3F_C4B b = {Vec3(points[1].x, points[1].y, points[1].z), col, Tex2F(1,0)}; + V3F_C4B c = {Vec3(points[2].x, points[2].y, points[2].z), col, Tex2F(1,1)}; + V3F_C4B d = {Vec3(points[3].x, points[3].y, points[3].z), col, Tex2F(0,1)}; + V3F_C4B e = {Vec3(points[0].x, points[0].y, points[0].z), col, Tex2F(0,0)}; + V3F_C4B f = {Vec3(points[2].x, points[2].y, points[2].z), col, Tex2F(1,1)}; + + V3F_C4B* slice = (V3F_C4B*)(_buffer + _bufferCount); + slice[0] = a; + slice[1] = b; + slice[2] = c; + slice[3] = d; + slice[4] = e; + slice[5] = f; + + _bufferCount += vertex_count; + _dirty = true; +} + +void Skybox::drawSphere(const Vec3& origin, const float radius, const float M, const float N, const Color4F& color) +{ + float step_y = M_PI/M; + float step_xz = 2*M_PI/N; + + Vec3 points[4]; + float angle_y = 0.0; + float angle_xz = 0.0; + int i=0, j=0; + + for(i=0; iretain(); + + auto state = getGLProgramState(); + state->setUniformTexture("u_Env", _texture); +} + +void Skybox::clear() +{ + _bufferCount = 0; + _dirty = true; +} + +NS_CC_END diff --git a/cocos/3d/CCSkybox.h b/cocos/3d/CCSkybox.h new file mode 100644 index 0000000000..99a504d139 --- /dev/null +++ b/cocos/3d/CCSkybox.h @@ -0,0 +1,83 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#ifndef __SKYBOX_H__ +#define __SKYBOX_H__ + +#include "cocos2d.h" + +NS_CC_BEGIN + +class CC_DLL Skybox : public Node +{ +public: + static Skybox* create(); + + void drawSphere(const Vec3& origin, const float radius, const float M, const float N, const Color4F& color); + + void setTexture(Texture2D*); + + /** Clear the geometry in the node's buffer. */ + void clear(); + + void onDraw(const Mat4& transform, uint32_t flags); + + // Overrides + virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + +CC_CONSTRUCTOR_ACCESS: + Skybox(); + virtual ~Skybox(); + virtual bool init(); + +protected: + struct V3F_C4B + { + Vec3 vertices; + Color4B colors; + Tex2F texcoord; + }; + + void ensureCapacity(int count); + void drawSlice(Vec3* points, const Color4F& color); + + GLuint _vao; + GLuint _vbo; + + int _bufferCapacity; + GLsizei _bufferCount; + V3F_C4B* _buffer; + + CustomCommand _customCommand; + + bool _dirty; + + Texture2D* _texture; +private: + CC_DISALLOW_COPY_AND_ASSIGN(Skybox); +}; + +NS_CC_END + +#endif // __SKYBOX_H__ diff --git a/cocos/3d/CCTextureCube.cpp b/cocos/3d/CCTextureCube.cpp new file mode 100644 index 0000000000..ed1beba2de --- /dev/null +++ b/cocos/3d/CCTextureCube.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +#include "3d/CCTextureCube.h" +#include "platform/CCImage.h" +#include "platform/CCFileUtils.h" + +NS_CC_BEGIN + +unsigned char* getImageData(Image* img, Texture2D::PixelFormat& ePixFmt) +{ + unsigned char* pTmpData = img->getData(); + unsigned int* inPixel32 = nullptr; + unsigned char* inPixel8 = nullptr; + unsigned short* outPixel16 = nullptr; + bool bHasAlpha = img->hasAlpha(); + size_t uBPP = img->getBitPerPixel(); + + int nWidth = img->getWidth(); + int nHeight = img->getHeight(); + + // compute pixel format + if (bHasAlpha) + { + ePixFmt = Texture2D::PixelFormat::DEFAULT; + } + else + { + if (uBPP >= 8) + { + ePixFmt = Texture2D::PixelFormat::RGB888; + } + else + { + ePixFmt = Texture2D::PixelFormat::RGB565; + } + } + + // Repack the pixel data into the right format + unsigned int uLen = nWidth * nHeight; + + if (ePixFmt == Texture2D::PixelFormat::RGB565) + { + if (bHasAlpha) + { + // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" + inPixel32 = (unsigned int*)img->getData(); + pTmpData = new unsigned char[nWidth * nHeight * 2]; + outPixel16 = (unsigned short*)pTmpData; + + for (unsigned int i = 0; i < uLen; ++i, ++inPixel32) + { + *outPixel16++ = + ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R + ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | // G + ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0); // B + } + } + else + { + // Convert "RRRRRRRRGGGGGGGGBBBBBBBB" to "RRRRRGGGGGGBBBBB" + pTmpData = new unsigned char[nWidth * nHeight * 2]; + outPixel16 = (unsigned short*)pTmpData; + inPixel8 = (unsigned char*)img->getData(); + + for (unsigned int i = 0; i < uLen; ++i) + { + unsigned char R = *inPixel8++; + unsigned char G = *inPixel8++; + unsigned char B = *inPixel8++; + + *outPixel16++ = + ((R >> 3) << 11) | // R + ((G >> 2) << 5) | // G + ((B >> 3) << 0); // B + } + } + } + + if (bHasAlpha && ePixFmt == Texture2D::PixelFormat::RGB888) + { + // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBBB" + inPixel32 = (unsigned int*)img->getData(); + + pTmpData = new unsigned char[nWidth * nHeight * 3]; + unsigned char* outPixel8 = pTmpData; + + for (unsigned int i = 0; i < uLen; ++i, ++inPixel32) + { + *outPixel8++ = (*inPixel32 >> 0) & 0xFF; // R + *outPixel8++ = (*inPixel32 >> 8) & 0xFF; // G + *outPixel8++ = (*inPixel32 >> 16) & 0xFF; // B + } + } + + return pTmpData; +} + +Image* createImage(const std::string& path) +{ + // Split up directory and filename + // MUTEX: + // Needed since addImageAsync calls this method from a different thread + + std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path); + if (fullpath.size() == 0) + { + return nullptr; + } + + // all images are handled by UIImage except PVR extension that is handled by our own handler + Image* image = nullptr; + do + { + image = new (std::nothrow) Image(); + CC_BREAK_IF(nullptr == image); + + bool bRet = image->initWithImageFile(fullpath); + CC_BREAK_IF(!bRet); + } + while (0); + + return image; +} + +TextureCube::TextureCube() +{ +} + +TextureCube::~TextureCube() +{ +} + +TextureCube* TextureCube::create(const std::string& path1, const std::string& path2, + const std::string& path3, const std::string& path4, + const std::string& path5, const std::string& path6) +{ + auto ret = new (std::nothrow) TextureCube(); + if (ret && ret->init(path1, path2, path3, path4, path5, path6)) + { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; +} + +bool TextureCube::init(const std::string& path1, const std::string& path2, + const std::string& path3, const std::string& path4, + const std::string& path5, const std::string& path6) +{ + std::vector images(6); + + images[0] = createImage(path1); + images[1] = createImage(path2); + images[2] = createImage(path3); + images[3] = createImage(path4); + images[4] = createImage(path5); + images[5] = createImage(path6); + + GLuint handle; + glGenTextures(1, &handle); + glBindTexture(GL_TEXTURE_CUBE_MAP, handle); + + for (int i = 0; i < 6; i++) + { + Image* img = images[i]; + + Texture2D::PixelFormat ePixelFmt; + unsigned char* pData = getImageData(img, ePixelFmt); + if (ePixelFmt == Texture2D::PixelFormat::RGBA8888) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, // level + GL_RGBA, // internal format + img->getWidth(), // width + img->getHeight(), // height + 0, // border + GL_RGBA, // format + GL_UNSIGNED_BYTE, // type + pData); // pixel data + } + else if (ePixelFmt == Texture2D::PixelFormat::RGB888) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, // level + GL_RGB, // internal format + img->getWidth(), // width + img->getHeight(), // height + 0, // border + GL_RGB, // format + GL_UNSIGNED_BYTE, // type + pData); // pixel data + } + + if (pData != img->getData()) + delete[] pData; + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + _name = handle; + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + + for (auto img: images) + { + CC_SAFE_RELEASE(img); + } + + return true; +} + +void TextureCube::setTexParameters(const TexParams& texParams) +{ + CCASSERT(_name != 0, __FUNCTION__); + + glBindTexture(GL_TEXTURE_CUBE_MAP, _name); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, texParams.wrapS); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, texParams.wrapS); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, texParams.wrapS); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, texParams.wrapT); + + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +NS_CC_END diff --git a/cocos/3d/CCTextureCube.h b/cocos/3d/CCTextureCube.h new file mode 100644 index 0000000000..6e4272a536 --- /dev/null +++ b/cocos/3d/CCTextureCube.h @@ -0,0 +1,67 @@ +/**************************************************************************** + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +#ifndef __CCTEXTURECUBE_H__ +#define __CCTEXTURECUBE_H__ + +#include "renderer/CCTexture2D.h" + +#include +#include +#include "base/ccTypes.h" + +NS_CC_BEGIN + +/** + texture cube map. + It wraps the cocos2d::Texture2D +*/ +class CC_DLL TextureCube: public Texture2D +{ +public: + /** + create cube texture from 6 textures. + + @param path The image resource path. + @create cube texture from 6 textures. + */ + static TextureCube* create(const std::string& positive_x, const std::string& negative_x, + const std::string& positive_y, const std::string& negative_y, + const std::string& positive_z, const std::string& negative_z); + + void setTexParameters(const TexParams&); +CC_CONSTRUCTOR_ACCESS: + TextureCube(); + TextureCube(const TextureCube&); + virtual ~TextureCube(); +protected: + + bool init(const std::string& positive_x, const std::string& negative_x, + const std::string& positive_y, const std::string& negative_y, + const std::string& positive_z, const std::string& negative_z); +}; + +NS_CC_END + +#endif // __CCTEXTURECUBE_H__ diff --git a/cocos/renderer/CCGLProgramState.cpp b/cocos/renderer/CCGLProgramState.cpp index 0682cd47ef..95e406ac3b 100644 --- a/cocos/renderer/CCGLProgramState.cpp +++ b/cocos/renderer/CCGLProgramState.cpp @@ -80,6 +80,11 @@ void UniformValue::apply() GL::bindTexture2DN(_value.tex.textureUnit, _value.tex.textureId); break; + case GL_SAMPLER_CUBE: + _glprogram->setUniformLocationWith1i(_uniform->location, _value.tex.textureUnit); + GL::bindTexture2DN(_value.tex.textureUnit, _value.tex.textureId, GL_TEXTURE_CUBE_MAP); + break; + case GL_INT: _glprogram->setUniformLocationWith1i(_uniform->location, _value.intValue); break; @@ -135,7 +140,7 @@ void UniformValue::setFloat(float value) void UniformValue::setTexture(GLuint textureId, GLuint textureUnit) { - CCASSERT(_uniform->type == GL_SAMPLER_2D, "Wrong type. expecting GL_SAMPLER_2D"); + //CCASSERT(_uniform->type == GL_SAMPLER_2D, "Wrong type. expecting GL_SAMPLER_2D"); _value.tex.textureId = textureId; _value.tex.textureUnit = textureUnit; _useCallback = false; diff --git a/cocos/renderer/ccGLStateCache.cpp b/cocos/renderer/ccGLStateCache.cpp index dc28a6870a..cab24cbe64 100644 --- a/cocos/renderer/ccGLStateCache.cpp +++ b/cocos/renderer/ccGLStateCache.cpp @@ -146,7 +146,7 @@ void bindTexture2D(GLuint textureId) GL::bindTexture2DN(0, textureId); } -void bindTexture2DN(GLuint textureUnit, GLuint textureId) +void bindTexture2DN(GLuint textureUnit, GLuint textureId, GLuint textureType/* = GL_TEXTURE_2D*/) { #if CC_ENABLE_GL_STATE_CACHE CCASSERT(textureUnit < MAX_ACTIVE_TEXTURE, "textureUnit is too big"); @@ -154,11 +154,11 @@ void bindTexture2DN(GLuint textureUnit, GLuint textureId) { s_currentBoundTexture[textureUnit] = textureId; activeTexture(GL_TEXTURE0 + textureUnit); - glBindTexture(GL_TEXTURE_2D, textureId); + glBindTexture(textureType, textureId); } #else glActiveTexture(GL_TEXTURE0 + textureUnit); - glBindTexture(GL_TEXTURE_2D, textureId); + glBindTexture(textureType, textureId); #endif } diff --git a/cocos/renderer/ccGLStateCache.h b/cocos/renderer/ccGLStateCache.h index 07b25bfe3d..3b8871e512 100644 --- a/cocos/renderer/ccGLStateCache.h +++ b/cocos/renderer/ccGLStateCache.h @@ -120,7 +120,7 @@ void CC_DLL bindTexture2D(GLuint textureId); If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. @since v2.1.0 */ -void CC_DLL bindTexture2DN(GLuint textureUnit, GLuint textureId); +void CC_DLL bindTexture2DN(GLuint textureUnit, GLuint textureId, GLuint textureType = GL_TEXTURE_2D); /** It will delete a given texture. If the texture was bound, it will invalidate the cached. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index b633f9252d..7bf4766850 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -30,6 +30,8 @@ #include "3d/CCAttachNode.h" #include "3d/CCRay.h" #include "3d/CCSprite3D.h" +#include "3d/CCTextureCube.h" +#include "3d/CCSkybox.h" #include "renderer/CCVertexIndexBuffer.h" #include "DrawNode3D.h" @@ -70,7 +72,8 @@ static std::function createFunctions[] = CL(Sprite3DMirrorTest), CL(QuaternionTest), CL(Sprite3DEmptyTest), - CL(UseCaseSprite3D) + CL(UseCaseSprite3D), + CL(Sprite3DCubeMapTest) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) @@ -2286,3 +2289,95 @@ void UseCaseSprite3D::update(float delta) circle->setPositionZ(z); } } + +Sprite3DCubeMapTest::Sprite3DCubeMapTest() : +_sprite(nullptr), +_textureCube(nullptr) +{ + auto s = Director::getInstance()->getWinSize(); + addNewSpriteWithCoords(Vec2(s.width / 2, s.height / 2)); +} + +Sprite3DCubeMapTest::~Sprite3DCubeMapTest() +{ + _textureCube->release(); +} + +std::string Sprite3DCubeMapTest::title() const +{ + return "CubeMap && Skybox Test"; +} + +std::string Sprite3DCubeMapTest::subtitle() const +{ + return ""; +} + +void Sprite3DCubeMapTest::addNewSpriteWithCoords(Vec2 p) +{ + Size visibleSize = Director::getInstance()->getVisibleSize(); + auto _camera = Camera::createPerspective(60, visibleSize.width / visibleSize.height, 0.1, 200); + _camera->setCameraFlag(CameraFlag::USER1); + + // create a teapot + auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + + //create and set our custom shader + auto shader = GLProgram::createWithFilenames("Sprite3DTest/cube_map.vert", "Sprite3DTest/cube_map.frag"); + auto _state = GLProgramState::create(shader); + + // create the second texture for cylinder + _textureCube = TextureCube::create("Sprite3DTest/skybox/left.jpg", "Sprite3DTest/skybox/right.jpg", + "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", + "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); + + // temporary solution + _textureCube->retain(); + + //set texture parameters + Texture2D::TexParams tRepeatParams; + tRepeatParams.magFilter = GL_NEAREST; + tRepeatParams.minFilter = GL_NEAREST; + tRepeatParams.wrapS = GL_MIRRORED_REPEAT; + tRepeatParams.wrapT = GL_MIRRORED_REPEAT; + _textureCube->setTexParameters(tRepeatParams); + + // pass the texture sampler to our custom shader + _state->setUniformTexture("u_cubeTex", _textureCube); + + teapot->setGLProgramState(_state); + teapot->setPosition3D(Vec3(0, -5, -20)); + teapot->setRotation3D(Vec3(-90, 180, 0)); + + auto rotate_action = RotateBy::create(1.5, Vec3(0, 30, 0)); + teapot->runAction(RepeatForever::create(rotate_action)); + + //pass mesh's attribute to shader + long offset = 0; + auto attributeCount = teapot->getMesh()->getMeshVertexAttribCount(); + for (auto i = 0; i < attributeCount; i++) + { + auto meshattribute = teapot->getMesh()->getMeshVertexAttribute(i); + _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], + meshattribute.size, + meshattribute.type, + GL_FALSE, + teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); + offset += meshattribute.attribSizeBytes; + } + addChild(teapot); + addChild(_camera); + setCameraMask(2); + + { + // config skybox + Skybox* box = Skybox::create(); + box->setTexture(_textureCube); + box->drawSphere(Vec3::ZERO, 1.6f, 20, 20, Color4F(0, 0, 0, 0)); + addChild(box); + + //auto rotate_action = RotateBy::create(1.5, Vec3(0, -30, 0)); + //box->runAction(RepeatForever::create(rotate_action)); + } +} diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 812e84171c..7a7ff1a74d 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -489,4 +489,24 @@ public: virtual void runThisTest(); }; +namespace cocos2d +{ + class TextureCube; +} +class Sprite3DCubeMapTest : public Sprite3DTestDemo +{ +public: + CREATE_FUNC(Sprite3DCubeMapTest); + Sprite3DCubeMapTest(); + ~Sprite3DCubeMapTest(); + virtual std::string title() const override; + virtual std::string subtitle() const override; + + void addNewSpriteWithCoords(Vec2); + +protected: + cocos2d::Sprite3D* _sprite; + cocos2d::TextureCube* _textureCube; +}; + #endif diff --git a/tests/cpp-tests/Resources/Sprite3DTest/cube_map.frag b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.frag new file mode 100644 index 0000000000..69f05b6cdb --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.frag @@ -0,0 +1,8 @@ + +varying vec3 v_reflect; +uniform samplerCube u_cubeTex; + +void main(void) +{ + gl_FragColor = textureCube(u_cubeTex, v_reflect); +} \ No newline at end of file diff --git a/tests/cpp-tests/Resources/Sprite3DTest/cube_map.vert b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.vert new file mode 100644 index 0000000000..500e9ffc9d --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/cube_map.vert @@ -0,0 +1,16 @@ +attribute vec4 a_position; +attribute vec3 a_normal; + +varying vec3 v_reflect; + +void main(void) +{ + gl_Position = CC_MVPMatrix * a_position; + + // compute reflect + vec4 positionWorldViewSpace = CC_MVMatrix * a_position;; + vec3 vEyeVertex = normalize(positionWorldViewSpace.xyz / positionWorldViewSpace.w); + + vec3 v_normalVector = CC_NormalMatrix * a_normal; + v_reflect = normalize(reflect(vEyeVertex, v_normalVector)); +} diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox.frag b/tests/cpp-tests/Resources/Sprite3DTest/skybox.frag new file mode 100644 index 0000000000..988ab74d80 --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/skybox.frag @@ -0,0 +1,8 @@ + +varying vec3 v_reflect; +uniform samplerCube u_Env; + +void main(void) +{ + gl_FragColor = textureCube(u_Env, v_reflect); +} \ No newline at end of file diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert b/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert new file mode 100644 index 0000000000..735ddb55ed --- /dev/null +++ b/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert @@ -0,0 +1,15 @@ +attribute vec4 a_position; +varying vec3 v_reflect; + +void main(void) +{ + mat4 MVMatrixLimited = CC_MVMatrix; + MVMatrixLimited[0][3] = 0; + MVMatrixLimited[1][3] = 0; + MVMatrixLimited[2][3] = 0; + + vec4 position = MVMatrixLimited* a_position; + + v_reflect = a_position.xyz; + gl_Position = position.xyww; +} diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/back.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/back.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d91cbd31635751034e7b91e94595e620cfb691d7 GIT binary patch literal 24753 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 Ytvk(Fa)dCAKs#_p9+aJ%xsyNt*_ZK_NdN!< literal 0 HcmV?d00001 diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/bottom.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/bottom.jpg new file mode 100644 index 0000000000000000000000000000000000000000..47db53c695c83a82ce0f5f50b163b10fd27c60a6 GIT binary patch literal 43625 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 z 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 literal 0 HcmV?d00001 diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/front.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/front.jpg new file mode 100644 index 0000000000000000000000000000000000000000..35b4796f89a164385ea944cc1eaea3b72e45b241 GIT binary patch literal 25785 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 F|JkCjs}KMH literal 0 HcmV?d00001 diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/left.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/left.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e500248c48114d51157c7f9fb4133a4243984e98 GIT binary patch literal 25271 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 TxDHjpC(C5}!n9IMmXH70tlr}- literal 0 HcmV?d00001 diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/right.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/right.jpg new file mode 100644 index 0000000000000000000000000000000000000000..68d235b79ae2cdf2fed9703a3f5ea7f1f12dcd03 GIT binary patch literal 31151 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 UbGvp5*0Gberc#c#TR*`6**@HdlK=n! literal 0 HcmV?d00001 diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox/top.jpg b/tests/cpp-tests/Resources/Sprite3DTest/skybox/top.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e15efede83355f77691590dd0b72298b4de81ed8 GIT binary patch literal 35377 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 Date: Thu, 29 Jan 2015 17:31:57 +0800 Subject: [PATCH 02/27] Simpilify skybox --- cocos/2d/libcocos2d.vcxproj | 4 +- cocos/2d/libcocos2d.vcxproj.filters | 9 +- cocos/3d/CCSkybox.cpp | 205 ++++-------------- cocos/3d/CCSkybox.h | 23 +- .../Classes/Sprite3DTest/Sprite3DTest.cpp | 1 - .../Resources/Sprite3DTest/skybox.vert | 6 +- 6 files changed, 62 insertions(+), 186 deletions(-) diff --git a/cocos/2d/libcocos2d.vcxproj b/cocos/2d/libcocos2d.vcxproj index 2a3490c64f..17a7c31dcd 100644 --- a/cocos/2d/libcocos2d.vcxproj +++ b/cocos/2d/libcocos2d.vcxproj @@ -237,10 +237,10 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + - @@ -608,11 +608,11 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + - diff --git a/cocos/2d/libcocos2d.vcxproj.filters b/cocos/2d/libcocos2d.vcxproj.filters index 4da4217a2c..3c3a28643b 100644 --- a/cocos/2d/libcocos2d.vcxproj.filters +++ b/cocos/2d/libcocos2d.vcxproj.filters @@ -1301,12 +1301,14 @@ - 3d 3d + + 3d + @@ -2551,12 +2553,13 @@ physics - - 3d 3d + + 3d + diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index ab298c5cc1..06ad532217 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -26,25 +26,21 @@ NS_CC_BEGIN - Skybox::Skybox() : _vao(0) , _vbo(0) - , _bufferCapacity(0) - , _bufferCount(0) - , _buffer(nullptr) - , _dirty(false) + , _vio(0) ,_texture(nullptr) { } Skybox::~Skybox() { - free(_buffer); - _buffer = nullptr; - glDeleteBuffers(1, &_vbo); + glDeleteBuffers(1, &_vio); + _vbo = 0; + _vio = 0; if (Configuration::getInstance()->supportsShareableVAO()) { @@ -56,86 +52,57 @@ Skybox::~Skybox() _texture->release(); } -Skybox* Skybox::create() -{ - Skybox* ret = new (std::nothrow) Skybox(); - if (ret && ret->init()) - { - ret->autorelease(); - } - else - { - CC_SAFE_DELETE(ret); - } - - return ret; -} - -void Skybox::ensureCapacity(int count) -{ - CCASSERT(count>=0, "capacity must be >= 0"); - - if(_bufferCount + count > _bufferCapacity) - { - _bufferCapacity += MAX(_bufferCapacity, count); - _buffer = (V3F_C4B*)realloc(_buffer, _bufferCapacity*sizeof(V3F_C4B)); - } -} - bool Skybox::init() { - //setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_TEXTURE_COLOR)); - //create and set our custom shader + // create and set our custom shader auto shader = GLProgram::createWithFilenames("Sprite3DTest/skybox.vert", "Sprite3DTest/skybox.frag"); auto state = GLProgramState::create(shader); setGLProgramState(state); - ensureCapacity(512); - if (Configuration::getInstance()->supportsShareableVAO()) { glGenVertexArrays(1, &_vao); GL::bindVAO(_vao); } - glGenBuffers(1, &_vbo); - glBindBuffer(GL_ARRAY_BUFFER, _vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B)* _bufferCapacity, _buffer, GL_STREAM_DRAW); - - glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, vertices)); - - glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR); - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, colors)); - - glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_TEX_COORD); - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD,2,GL_FLOAT,GL_FALSE,sizeof(V3F_C4B),(GLvoid*)offsetof(V3F_C4B, texcoord)); - - glBindBuffer(GL_ARRAY_BUFFER, 0); + initBuffers(); if (Configuration::getInstance()->supportsShareableVAO()) { + glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); + GL::bindVAO(0); } CHECK_GL_ERROR_DEBUG(); - _dirty = true; - -#if CC_ENABLE_CACHE_TEXTURE_DATA - // Need to listen the event only when not use batchnode, because it will use VBO - auto listener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, [this](EventCustom* event) - { - /** listen the event that coming to foreground on Android */ - this->init(); - }); - - _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); -#endif - return true; } +void Skybox::initBuffers() +{ + // init vertex buffer object + Vec3 vexBuf[] = + { + Vec3(1, -1, 1), Vec3(1, 1, 1), Vec3(-1, 1, 1), Vec3(-1, -1, 1), + Vec3(1, -1, -1), Vec3(1, 1, -1), Vec3(-1, 1, -1), Vec3(-1, -1, -1) + }; + + glGenBuffers(1, &_vbo); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STREAM_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + // init index buffer object + unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, 1, 5, 4, 1, 4, 0, 4, 5, 6, 4, 6, 7, 7, 6, 2, 7, 2, 3 }; + + glGenBuffers(1, &_vio); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vio); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxBuf), idxBuf, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + void Skybox::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) { _customCommand.init(_globalZOrder); @@ -153,14 +120,6 @@ void Skybox::onDraw(const Mat4& transform, uint32_t flags) glDepthFunc(GL_LEQUAL); glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); - - if (_dirty) - { - glBindBuffer(GL_ARRAY_BUFFER, _vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(V3F_C4B)*_bufferCapacity, _buffer, GL_STREAM_DRAW); - _dirty = false; - } if (Configuration::getInstance()->supportsShareableVAO()) { @@ -168,96 +127,34 @@ void Skybox::onDraw(const Mat4& transform, uint32_t flags) } else { - GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX); + GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION); glBindBuffer(GL_ARRAY_BUFFER, _vbo); - // vertex - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, vertices)); + glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); - // color - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B), (GLvoid*)offsetof(V3F_C4B, colors)); - - //texcoord - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD,2,GL_FLOAT,GL_FALSE,sizeof(V3F_C4B),(GLvoid*)offsetof(V3F_C4B, texcoord)); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vio); } - glDrawArrays(GL_TRIANGLES, 0, _bufferCount); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glDrawElements(GL_TRIANGLES, (GLsizei)36, GL_UNSIGNED_BYTE, nullptr); - CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _bufferCount); + if (Configuration::getInstance()->supportsShareableVAO()) + { + GL::bindVAO(0); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } - glCullFace(GL_BACK); + CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 8); + + glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR_DEBUG(); } -void Skybox::drawSlice(Vec3* points, const Color4F& color) -{ - unsigned int vertex_count = 6; - ensureCapacity(vertex_count); - - Color4B col = Color4B(color); - V3F_C4B a = {Vec3(points[0].x, points[0].y, points[0].z), col, Tex2F(0,0)}; - V3F_C4B b = {Vec3(points[1].x, points[1].y, points[1].z), col, Tex2F(1,0)}; - V3F_C4B c = {Vec3(points[2].x, points[2].y, points[2].z), col, Tex2F(1,1)}; - V3F_C4B d = {Vec3(points[3].x, points[3].y, points[3].z), col, Tex2F(0,1)}; - V3F_C4B e = {Vec3(points[0].x, points[0].y, points[0].z), col, Tex2F(0,0)}; - V3F_C4B f = {Vec3(points[2].x, points[2].y, points[2].z), col, Tex2F(1,1)}; - - V3F_C4B* slice = (V3F_C4B*)(_buffer + _bufferCount); - slice[0] = a; - slice[1] = b; - slice[2] = c; - slice[3] = d; - slice[4] = e; - slice[5] = f; - - _bufferCount += vertex_count; - _dirty = true; -} - -void Skybox::drawSphere(const Vec3& origin, const float radius, const float M, const float N, const Color4F& color) -{ - float step_y = M_PI/M; - float step_xz = 2*M_PI/N; - - Vec3 points[4]; - float angle_y = 0.0; - float angle_xz = 0.0; - int i=0, j=0; - - for(i=0; isetUniformTexture("u_Env", _texture); } -void Skybox::clear() -{ - _bufferCount = 0; - _dirty = true; -} - NS_CC_END diff --git a/cocos/3d/CCSkybox.h b/cocos/3d/CCSkybox.h index 99a504d139..2b6e115f38 100644 --- a/cocos/3d/CCSkybox.h +++ b/cocos/3d/CCSkybox.h @@ -32,15 +32,10 @@ NS_CC_BEGIN class CC_DLL Skybox : public Node { public: - static Skybox* create(); - - void drawSphere(const Vec3& origin, const float radius, const float M, const float N, const Color4F& color); + CREATE_FUNC(Skybox); void setTexture(Texture2D*); - /** Clear the geometry in the node's buffer. */ - void clear(); - void onDraw(const Mat4& transform, uint32_t flags); // Overrides @@ -52,27 +47,15 @@ CC_CONSTRUCTOR_ACCESS: virtual bool init(); protected: - struct V3F_C4B - { - Vec3 vertices; - Color4B colors; - Tex2F texcoord; - }; - void ensureCapacity(int count); - void drawSlice(Vec3* points, const Color4F& color); + void initBuffers(); GLuint _vao; GLuint _vbo; - - int _bufferCapacity; - GLsizei _bufferCount; - V3F_C4B* _buffer; + GLuint _vio; CustomCommand _customCommand; - bool _dirty; - Texture2D* _texture; private: CC_DISALLOW_COPY_AND_ASSIGN(Skybox); diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 7bf4766850..edbb889330 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -2374,7 +2374,6 @@ void Sprite3DCubeMapTest::addNewSpriteWithCoords(Vec2 p) // config skybox Skybox* box = Skybox::create(); box->setTexture(_textureCube); - box->drawSphere(Vec3::ZERO, 1.6f, 20, 20, Color4F(0, 0, 0, 0)); addChild(box); //auto rotate_action = RotateBy::create(1.5, Vec3(0, -30, 0)); diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert b/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert index 735ddb55ed..eb11185ebb 100644 --- a/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert +++ b/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert @@ -4,9 +4,9 @@ varying vec3 v_reflect; void main(void) { mat4 MVMatrixLimited = CC_MVMatrix; - MVMatrixLimited[0][3] = 0; - MVMatrixLimited[1][3] = 0; - MVMatrixLimited[2][3] = 0; + MVMatrixLimited[0][3] = 0.0; + MVMatrixLimited[1][3] = 0.0; + MVMatrixLimited[2][3] = 0.0; vec4 position = MVMatrixLimited* a_position; From 806a5011e577772368da7d3d022db92b596183f0 Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Fri, 30 Jan 2015 17:23:30 +0800 Subject: [PATCH 03/27] solve the problems noted in comments --- cocos/3d/CCSkybox.cpp | 38 ++++++++++++++++------------- cocos/3d/CCSkybox.h | 10 +++++--- cocos/3d/CCTextureCube.cpp | 26 ++++++++++---------- cocos/renderer/CCGLProgramState.cpp | 2 +- cocos/renderer/ccGLStateCache.cpp | 18 +++++++++++++- cocos/renderer/ccGLStateCache.h | 8 ++++-- 6 files changed, 64 insertions(+), 38 deletions(-) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index 06ad532217..ad5945769d 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -23,24 +23,25 @@ ****************************************************************************/ #include "CCSkybox.h" +#include "CCTextureCube.h" NS_CC_BEGIN Skybox::Skybox() : _vao(0) - , _vbo(0) - , _vio(0) + , _vertexBuffer(0) + , _indexBuffer(0) ,_texture(nullptr) { } Skybox::~Skybox() { - glDeleteBuffers(1, &_vbo); - glDeleteBuffers(1, &_vio); + glDeleteBuffers(1, &_vertexBuffer); + glDeleteBuffers(1, &_indexBuffer); - _vbo = 0; - _vio = 0; + _vertexBuffer = 0; + _indexBuffer = 0; if (Configuration::getInstance()->supportsShareableVAO()) { @@ -89,16 +90,16 @@ void Skybox::initBuffers() Vec3(1, -1, -1), Vec3(1, 1, -1), Vec3(-1, 1, -1), Vec3(-1, -1, -1) }; - glGenBuffers(1, &_vbo); - glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STREAM_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // init index buffer object unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, 1, 5, 4, 1, 4, 0, 4, 5, 6, 4, 6, 7, 7, 6, 2, 7, 2, 3 }; - glGenBuffers(1, &_vio); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vio); + glGenBuffers(1, &_indexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxBuf), idxBuf, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } @@ -116,11 +117,13 @@ void Skybox::onDraw(const Mat4& transform, uint32_t flags) state->applyGLProgram(transform); state->applyUniforms(); + GLboolean depthFlag = glIsEnabled(GL_DEPTH_TEST); + GLint depthFunc; + glGetIntegerv(GL_DEPTH_FUNC, &depthFunc); + glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - glEnable(GL_CULL_FACE); - if (Configuration::getInstance()->supportsShareableVAO()) { GL::bindVAO(_vao); @@ -129,10 +132,10 @@ void Skybox::onDraw(const Mat4& transform, uint32_t flags) { GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION); - glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vio); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); } glDrawElements(GL_TRIANGLES, (GLsizei)36, GL_UNSIGNED_BYTE, nullptr); @@ -149,13 +152,14 @@ void Skybox::onDraw(const Mat4& transform, uint32_t flags) CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 8); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); + glDepthFunc(depthFunc); + if (!depthFlag) + glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR_DEBUG(); } -void Skybox::setTexture(Texture2D* texture) +void Skybox::setTexture(TextureCube* texture) { CCASSERT(texture != nullptr, __FUNCTION__); diff --git a/cocos/3d/CCSkybox.h b/cocos/3d/CCSkybox.h index 2b6e115f38..5fd019ac73 100644 --- a/cocos/3d/CCSkybox.h +++ b/cocos/3d/CCSkybox.h @@ -29,12 +29,14 @@ NS_CC_BEGIN +class TextureCube; + class CC_DLL Skybox : public Node { public: CREATE_FUNC(Skybox); - void setTexture(Texture2D*); + void setTexture(TextureCube*); void onDraw(const Mat4& transform, uint32_t flags); @@ -51,12 +53,12 @@ protected: void initBuffers(); GLuint _vao; - GLuint _vbo; - GLuint _vio; + GLuint _vertexBuffer; + GLuint _indexBuffer; CustomCommand _customCommand; - Texture2D* _texture; + TextureCube* _texture; private: CC_DISALLOW_COPY_AND_ASSIGN(Skybox); }; diff --git a/cocos/3d/CCTextureCube.cpp b/cocos/3d/CCTextureCube.cpp index ed1beba2de..6c91d63cf9 100644 --- a/cocos/3d/CCTextureCube.cpp +++ b/cocos/3d/CCTextureCube.cpp @@ -152,12 +152,12 @@ TextureCube::~TextureCube() { } -TextureCube* TextureCube::create(const std::string& path1, const std::string& path2, - const std::string& path3, const std::string& path4, - const std::string& path5, const std::string& path6) +TextureCube* TextureCube::create(const std::string& positive_x, const std::string& negative_x, + const std::string& positive_y, const std::string& negative_y, + const std::string& positive_z, const std::string& negative_z) { auto ret = new (std::nothrow) TextureCube(); - if (ret && ret->init(path1, path2, path3, path4, path5, path6)) + if (ret && ret->init(positive_x, negative_x, positive_y, negative_y, positive_z, negative_z)) { ret->autorelease(); return ret; @@ -166,18 +166,18 @@ TextureCube* TextureCube::create(const std::string& path1, const std::string& pa return nullptr; } -bool TextureCube::init(const std::string& path1, const std::string& path2, - const std::string& path3, const std::string& path4, - const std::string& path5, const std::string& path6) +bool TextureCube::init(const std::string& positive_x, const std::string& negative_x, + const std::string& positive_y, const std::string& negative_y, + const std::string& positive_z, const std::string& negative_z) { std::vector images(6); - images[0] = createImage(path1); - images[1] = createImage(path2); - images[2] = createImage(path3); - images[3] = createImage(path4); - images[4] = createImage(path5); - images[5] = createImage(path6); + images[0] = createImage(positive_x); + images[1] = createImage(negative_x); + images[2] = createImage(positive_y); + images[3] = createImage(negative_y); + images[4] = createImage(positive_z); + images[5] = createImage(negative_z); GLuint handle; glGenTextures(1, &handle); diff --git a/cocos/renderer/CCGLProgramState.cpp b/cocos/renderer/CCGLProgramState.cpp index 95e406ac3b..34b94140d2 100644 --- a/cocos/renderer/CCGLProgramState.cpp +++ b/cocos/renderer/CCGLProgramState.cpp @@ -82,7 +82,7 @@ void UniformValue::apply() case GL_SAMPLER_CUBE: _glprogram->setUniformLocationWith1i(_uniform->location, _value.tex.textureUnit); - GL::bindTexture2DN(_value.tex.textureUnit, _value.tex.textureId, GL_TEXTURE_CUBE_MAP); + GL::bindTextureN(_value.tex.textureUnit, _value.tex.textureId, GL_TEXTURE_CUBE_MAP); break; case GL_INT: diff --git a/cocos/renderer/ccGLStateCache.cpp b/cocos/renderer/ccGLStateCache.cpp index cab24cbe64..25eedc382f 100644 --- a/cocos/renderer/ccGLStateCache.cpp +++ b/cocos/renderer/ccGLStateCache.cpp @@ -146,7 +146,23 @@ void bindTexture2D(GLuint textureId) GL::bindTexture2DN(0, textureId); } -void bindTexture2DN(GLuint textureUnit, GLuint textureId, GLuint textureType/* = GL_TEXTURE_2D*/) +void bindTexture2DN(GLuint textureUnit, GLuint textureId) +{ +#if CC_ENABLE_GL_STATE_CACHE + CCASSERT(textureUnit < MAX_ACTIVE_TEXTURE, "textureUnit is too big"); + if (s_currentBoundTexture[textureUnit] != textureId) + { + s_currentBoundTexture[textureUnit] = textureId; + activeTexture(GL_TEXTURE0 + textureUnit); + glBindTexture(GL_TEXTURE_2D, textureId); + } +#else + glActiveTexture(GL_TEXTURE0 + textureUnit); + glBindTexture(GL_TEXTURE_2D, textureId); +#endif +} + +void bindTextureN(GLuint textureUnit, GLuint textureId, GLuint textureType/* = GL_TEXTURE_2D*/) { #if CC_ENABLE_GL_STATE_CACHE CCASSERT(textureUnit < MAX_ACTIVE_TEXTURE, "textureUnit is too big"); diff --git a/cocos/renderer/ccGLStateCache.h b/cocos/renderer/ccGLStateCache.h index 3b8871e512..163ddb1d74 100644 --- a/cocos/renderer/ccGLStateCache.h +++ b/cocos/renderer/ccGLStateCache.h @@ -115,12 +115,16 @@ void CC_DLL enableVertexAttribs(uint32_t flags); */ void CC_DLL bindTexture2D(GLuint textureId); - /** If the texture is not already bound to a given unit, it binds it. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. @since v2.1.0 */ -void CC_DLL bindTexture2DN(GLuint textureUnit, GLuint textureId, GLuint textureType = GL_TEXTURE_2D); +void CC_DLL bindTexture2DN(GLuint textureUnit, GLuint textureId); + +/** If the texture is not already bound to a given unit, it binds it. +If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. +*/ +void CC_DLL bindTextureN(GLuint textureUnit, GLuint textureId, GLuint textureType = GL_TEXTURE_2D); /** It will delete a given texture. If the texture was bound, it will invalidate the cached. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. From f608377bdbd81c88478f9688b4882465b908a5c1 Mon Sep 17 00:00:00 2001 From: yangxiao Date: Mon, 2 Feb 2015 15:44:47 +0800 Subject: [PATCH 04/27] make vao work --- cocos/3d/CCSkybox.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index ad5945769d..82e3501dc0 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -58,6 +58,7 @@ bool Skybox::init() // create and set our custom shader auto shader = GLProgram::createWithFilenames("Sprite3DTest/skybox.vert", "Sprite3DTest/skybox.frag"); auto state = GLProgramState::create(shader); + state->setVertexAttribPointer(GLProgram::ATTRIBUTE_NAME_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); setGLProgramState(state); if (Configuration::getInstance()->supportsShareableVAO()) @@ -71,7 +72,7 @@ bool Skybox::init() if (Configuration::getInstance()->supportsShareableVAO()) { glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); + state->applyAttributes(false); GL::bindVAO(0); } @@ -92,8 +93,7 @@ void Skybox::initBuffers() glGenBuffers(1, &_vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STREAM_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); + glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STATIC_DRAW); // init index buffer object unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, 1, 5, 4, 1, 4, 0, 4, 5, 6, 4, 6, 7, 7, 6, 2, 7, 2, 3 }; @@ -101,7 +101,6 @@ void Skybox::initBuffers() glGenBuffers(1, &_indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxBuf), idxBuf, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } void Skybox::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) @@ -114,8 +113,7 @@ void Skybox::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) void Skybox::onDraw(const Mat4& transform, uint32_t flags) { auto state = getGLProgramState(); - state->applyGLProgram(transform); - state->applyUniforms(); + state->apply(transform); GLboolean depthFlag = glIsEnabled(GL_DEPTH_TEST); GLint depthFunc; From 265e6fec1a0d38b70725f71e5c946f77a309455e Mon Sep 17 00:00:00 2001 From: yangxiao Date: Mon, 2 Feb 2015 16:54:55 +0800 Subject: [PATCH 05/27] fix index --- cocos/3d/CCSkybox.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index 82e3501dc0..caf7f95a48 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -96,7 +96,13 @@ void Skybox::initBuffers() glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STATIC_DRAW); // init index buffer object - unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, 1, 5, 4, 1, 4, 0, 4, 5, 6, 4, 6, 7, 7, 6, 2, 7, 2, 3 }; + unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, // font + 1, 5, 4, 1, 4, 0, // right + 4, 5, 6, 4, 6, 7, // back + 7, 6, 2, 7, 2, 3, // left + 2, 6, 5, 2, 5, 1, // up + 3, 0, 4, 3, 4, 7 // down + }; glGenBuffers(1, &_indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); From 0587122ccc82dd1bb4d0c2fb8f9769b753c8fada Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Thu, 19 Mar 2015 15:10:33 +0800 Subject: [PATCH 06/27] Move Skybox.shader from Sprite3DTest to Shader3D folder --- cocos/3d/CCSkybox.cpp | 2 +- .../{Sprite3DTest/skybox.frag => Shaders3D/Skybox.frag} | 0 .../{Sprite3DTest/skybox.vert => Shaders3D/Skybox.vert} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename tests/cpp-tests/Resources/{Sprite3DTest/skybox.frag => Shaders3D/Skybox.frag} (100%) rename tests/cpp-tests/Resources/{Sprite3DTest/skybox.vert => Shaders3D/Skybox.vert} (100%) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index caf7f95a48..e32fb0e287 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -56,7 +56,7 @@ Skybox::~Skybox() bool Skybox::init() { // create and set our custom shader - auto shader = GLProgram::createWithFilenames("Sprite3DTest/skybox.vert", "Sprite3DTest/skybox.frag"); + auto shader = GLProgram::createWithFilenames("Shaders3D/Skybox.vert", "Shaders3D/Skybox.frag"); auto state = GLProgramState::create(shader); state->setVertexAttribPointer(GLProgram::ATTRIBUTE_NAME_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); setGLProgramState(state); diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox.frag b/tests/cpp-tests/Resources/Shaders3D/Skybox.frag similarity index 100% rename from tests/cpp-tests/Resources/Sprite3DTest/skybox.frag rename to tests/cpp-tests/Resources/Shaders3D/Skybox.frag diff --git a/tests/cpp-tests/Resources/Sprite3DTest/skybox.vert b/tests/cpp-tests/Resources/Shaders3D/Skybox.vert similarity index 100% rename from tests/cpp-tests/Resources/Sprite3DTest/skybox.vert rename to tests/cpp-tests/Resources/Shaders3D/Skybox.vert From 52280e637684627215eb7dc7031299a9bd4809c7 Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Fri, 20 Mar 2015 17:53:05 +0800 Subject: [PATCH 07/27] add 3d test case(skybox and texture cube) for lua project --- cocos/cocos2d.h | 2 + .../auto/lua_cocos2dx_3d_auto.cpp | 218 ++++++++++++++++-- .../src/Sprite3DTest/Sprite3DTest.lua | 68 +++++- 3 files changed, 263 insertions(+), 25 deletions(-) diff --git a/cocos/cocos2d.h b/cocos/cocos2d.h index 4ce3defc65..48d53380df 100644 --- a/cocos/cocos2d.h +++ b/cocos/cocos2d.h @@ -285,6 +285,8 @@ THE SOFTWARE. #include "3d/CCBillBoard.h" #include "3d/CCFrustum.h" #include "3d/CCPlane.h" +#include "3d/CCTextureCube.h" +#include "3d/CCSkybox.h" // Deprecated include #include "deprecated/CCDictionary.h" diff --git a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp index 9968e1800a..e500da44bb 100644 --- a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp +++ b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp @@ -1293,14 +1293,14 @@ int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* tolua_S) if (!ok) { break; } std::function arg2; do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if (!ok) { break; } void* arg3; #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; + ok = false; if (!ok) { break; } cocos2d::Sprite3D::createAsync(arg0, arg1, arg2, arg3); lua_settop(tolua_S, 1); @@ -1317,14 +1317,14 @@ int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* tolua_S) if (!ok) { break; } std::function arg1; do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if (!ok) { break; } void* arg2; #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; + ok = false; if (!ok) { break; } cocos2d::Sprite3D::createAsync(arg0, arg1, arg2); lua_settop(tolua_S, 1); @@ -2871,22 +2871,192 @@ int lua_register_cocos2dx_3d_BillBoard(lua_State* tolua_S) g_typeCast["BillBoard"] = "cc.BillBoard"; return 1; } -TOLUA_API int register_all_cocos2dx_3d(lua_State* tolua_S) + +int lua_cocos2dx_3d_TextureCube_create(lua_State* tolua_S) { - tolua_open(tolua_S); - - tolua_module(tolua_S,"cc",0); - tolua_beginmodule(tolua_S,"cc"); + int argc = 0; + bool ok = true; +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; +#endif - lua_register_cocos2dx_3d_Animate3D(tolua_S); - lua_register_cocos2dx_3d_Sprite3D(tolua_S); - lua_register_cocos2dx_3d_AttachNode(tolua_S); - lua_register_cocos2dx_3d_BillBoard(tolua_S); - lua_register_cocos2dx_3d_Animation3D(tolua_S); - lua_register_cocos2dx_3d_Skeleton3D(tolua_S); - lua_register_cocos2dx_3d_Mesh(tolua_S); +#if COCOS2D_DEBUG >= 1 + if (!tolua_isusertable(tolua_S, 1, "cc.TextureCube", 0, &tolua_err)) goto tolua_lerror; +#endif - tolua_endmodule(tolua_S); - return 1; + argc = lua_gettop(tolua_S) - 1; + + do + { + if (argc == 6) + { + std::string positive_x; + ok &= luaval_to_std_string(tolua_S, 2, &positive_x, "cc.TextureCube:create"); + if (!ok) { break; } + + std::string negative_x; + ok &= luaval_to_std_string(tolua_S, 3, &negative_x, "cc.TextureCube:create"); + if (!ok){ break; } + + std::string positive_y; + ok &= luaval_to_std_string(tolua_S, 4, &positive_y, "cc.TextureCube:create"); + if (!ok) { break; } + + std::string negative_y; + ok &= luaval_to_std_string(tolua_S, 5, &negative_y, "cc.TextureCube:create"); + if (!ok){ break; } + + std::string positive_z; + ok &= luaval_to_std_string(tolua_S, 6, &positive_z, "cc.TextureCube:create"); + if (!ok) { break; } + + std::string negative_z; + ok &= luaval_to_std_string(tolua_S, 7, &negative_z, "cc.TextureCube:create"); + if (!ok){ break; } + + cocos2d::TextureCube* ret = cocos2d::TextureCube::create(positive_x, negative_x, + positive_y, negative_y, + positive_z, negative_z); + object_to_luaval(tolua_S, "cc.TextureCube", (cocos2d::TextureCube*)ret); + return 1; + } + } while (0); + + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "cc.TextureCube:create", argc, 6); + return 0; +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S, "#ferror in function 'lua_cocos2dx_3d_TextureCube_create'.", &tolua_err); +#endif + return 0; +} + +int lua_register_cocos2dx_3d_TextureCube(lua_State* tolua_S) +{ + tolua_usertype(tolua_S, "cc.TextureCube"); + tolua_cclass(tolua_S, "TextureCube", "cc.TextureCube", "cc.Texture2D", nullptr); + + tolua_beginmodule(tolua_S, "TextureCube"); + tolua_function(tolua_S, "create", lua_cocos2dx_3d_TextureCube_create); + tolua_endmodule(tolua_S); + std::string typeName = typeid(cocos2d::TextureCube).name(); + g_luaType[typeName] = "cc.TextureCube"; + g_typeCast["TextureCube"] = "cc.TextureCube"; + return 1; +} + +int lua_cocos2dx_3d_Skybox_create(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if COCOS2D_DEBUG >= 1 + if (!tolua_isusertable(tolua_S, 1, "cc.Skybox", 0, &tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + do + { + if (argc == 0) + { + cocos2d::Skybox* ret = cocos2d::Skybox::create(); + object_to_luaval(tolua_S, "cc.Skybox", (cocos2d::Skybox*)ret); + return 1; + } + } while (0); + + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "cc.Skybox:create", argc, 0); + return 0; +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S, "#ferror in function 'lua_cocos2dx_3d_Skybox_create'.", &tolua_err); +#endif + return 0; +} + +int lua_cocos2dx_3d_Skybox_setTexture(lua_State* tolua_S) +{ + int argc = 0; + cocos2d::Skybox* cobj = nullptr; + bool ok = true; +#if COCOS2D_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if COCOS2D_DEBUG >= 1 + if (!tolua_isusertype(tolua_S, 1, "cc.Skybox", 0, &tolua_err)) goto tolua_lerror; +#endif + cobj = (cocos2d::Skybox*)tolua_tousertype(tolua_S, 1, 0); +#if COCOS2D_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S, "invalid 'cobj' in function 'lua_cocos2dx_3d_Skybox_setTexture'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S) - 1; + do{ + if (argc == 1) + { + cocos2d::TextureCube* arg0; + ok &= luaval_to_object(tolua_S, 2, "cc.TextureCube", &arg0); + + if (!ok) { break; } + cobj->setTexture(arg0); + lua_settop(tolua_S, 1); + return 1; + } + } while (0); + + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Skybox:setTexture", argc, 1); + return 0; + +#if COCOS2D_DEBUG >= 1 +tolua_lerror: + tolua_error(tolua_S, "#ferror in function 'lua_cocos2dx_3d_Skybox_setTexture'.", &tolua_err); +#endif + + return 0; +} + +int lua_register_cocos2dx_3d_Skybox(lua_State* tolua_S) +{ + tolua_usertype(tolua_S, "cc.Skybox"); + tolua_cclass(tolua_S, "Skybox", "cc.Skybox", "cc.Node", nullptr); + + tolua_beginmodule(tolua_S, "Skybox"); + tolua_function(tolua_S, "create", lua_cocos2dx_3d_Skybox_create); + tolua_function(tolua_S, "setTexture", lua_cocos2dx_3d_Skybox_setTexture); + tolua_endmodule(tolua_S); + + std::string typeName = typeid(cocos2d::Skybox).name(); + g_luaType[typeName] = "cc.Skybox"; + g_typeCast["Skybox"] = "cc.Skybox"; + return 1; +} + +TOLUA_API int register_all_cocos2dx_3d(lua_State* tolua_S) +{ + tolua_open(tolua_S); + + tolua_module(tolua_S,"cc",0); + tolua_beginmodule(tolua_S,"cc"); + + lua_register_cocos2dx_3d_Animate3D(tolua_S); + lua_register_cocos2dx_3d_Sprite3D(tolua_S); + lua_register_cocos2dx_3d_AttachNode(tolua_S); + lua_register_cocos2dx_3d_BillBoard(tolua_S); + lua_register_cocos2dx_3d_Animation3D(tolua_S); + lua_register_cocos2dx_3d_Skeleton3D(tolua_S); + lua_register_cocos2dx_3d_Mesh(tolua_S); + lua_register_cocos2dx_3d_TextureCube(tolua_S); + lua_register_cocos2dx_3d_Skybox(tolua_S); + + tolua_endmodule(tolua_S); + return 1; } diff --git a/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua b/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua index bb95144f61..efdf34dbb4 100644 --- a/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua +++ b/tests/lua-tests/src/Sprite3DTest/Sprite3DTest.lua @@ -919,10 +919,75 @@ function Sprite3DMirrorTest.create() return layer end + +---------------------------------------- +----Sprite3DCubeTexture +---------------------------------------- +local Sprite3DCubeMap = {} +Sprite3DCubeMap.__index = Sprite3DCubeMap + +function Sprite3DCubeMap.create() +local layer = cc.Layer:create() +Helper.initWithLayer(layer) +Helper.titleLabel:setString("Sprite3D CubeMap/Skybox Test") + +local visSize = cc.Director:getInstance():getVisibleSize() +local camera = cc.Camera:createPerspective(68, visSize.width / visSize.height, 0.1, 200) +camera:setCameraFlag(2) +layer:addChild(camera) + +local fileName = "Sprite3DTest/teapot.c3b" +local teapot = cc.Sprite3D:create(fileName) +teapot:setPosition3D({x = 0, y = -5, z = -20}) +teapot:setRotation3D({x = -90, y = 180, z = 0}) + +local texCube = cc.TextureCube:create("Sprite3DTest/skybox/left.jpg", "Sprite3DTest/skybox/right.jpg", + "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", + "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); + +local program = cc.GLProgram:createWithFilenames("Sprite3DTest/cube_map.vert", "Sprite3DTest/cube_map.frag") +local state = cc.GLProgramState:create(program) + +attriNames = { + "a_position", "a_color", + "a_texCoord", "a_texCoord1", "a_texCoord2", "a_texCoord3", + "a_normal", "a_blendWeight", "a_blendIndex" + } + +--pass mesh's attribute to shader +local offset = 0 +local attributeCount = teapot:getMesh():getMeshVertexAttribCount() +for i = 0, attributeCount-1 do + local meshattribute = teapot:getMesh():getMeshVertexAttribute(i) + state:setVertexAttribPointer(attriNames[meshattribute.vertexAttrib+1], + meshattribute.size, + meshattribute.type, + false, + teapot:getMesh():getVertexSizeInBytes(), + offset); + offset = offset + meshattribute.attribSizeBytes +end + +state:setUniformTexture("u_cubeTex", texCube:getName()) + +teapot:setGLProgramState(state) +teapot:setCameraMask(2) + +local rotate_action = cc.RotateBy:create(1.5, { x = 0.0, y = 30.0, z = 0.0}) +teapot:runAction(cc.RepeatForever:create(rotate_action)); +layer:addChild(teapot) + +local skybox = cc.Skybox:create() +skybox:setTexture(texCube) +layer:addChild(skybox) + +return layer +end + function Sprite3DTest() local scene = cc.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { Sprite3DBasicTest.create, Sprite3DHitTest.create, @@ -932,6 +997,7 @@ function Sprite3DTest() Sprite3DReskinTest.create, Sprite3DWithOBBPerfromanceTest.create, Sprite3DMirrorTest.create, + Sprite3DCubeMap.create, } scene:addChild(Sprite3DBasicTest.create()) From 6eaa78d1cbc8742654301f9d971e306833fa139b Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Tue, 24 Mar 2015 15:43:59 +0800 Subject: [PATCH 08/27] add reload mechanism for TextureCube and Skybox --- cocos/3d/CCSkybox.cpp | 64 +- cocos/3d/CCSkybox.h | 2 + cocos/3d/CCTextureCube.cpp | 13 + cocos/3d/CCTextureCube.h | 4 + .../Classes/Sprite3DTest/Sprite3DTest.cpp | 699 +++++++++--------- .../Classes/Sprite3DTest/Sprite3DTest.h | 204 ++--- 6 files changed, 529 insertions(+), 457 deletions(-) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index e32fb0e287..d871a971e5 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -61,22 +61,8 @@ bool Skybox::init() state->setVertexAttribPointer(GLProgram::ATTRIBUTE_NAME_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(Vec3), nullptr); setGLProgramState(state); - if (Configuration::getInstance()->supportsShareableVAO()) - { - glGenVertexArrays(1, &_vao); - GL::bindVAO(_vao); - } - initBuffers(); - if (Configuration::getInstance()->supportsShareableVAO()) - { - glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); - state->applyAttributes(false); - - GL::bindVAO(0); - } - CHECK_GL_ERROR_DEBUG(); return true; @@ -84,6 +70,12 @@ bool Skybox::init() void Skybox::initBuffers() { + if (Configuration::getInstance()->supportsShareableVAO()) + { + glGenVertexArrays(1, &_vao); + GL::bindVAO(_vao); + } + // init vertex buffer object Vec3 vexBuf[] = { @@ -97,16 +89,24 @@ void Skybox::initBuffers() // init index buffer object unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, // font - 1, 5, 4, 1, 4, 0, // right - 4, 5, 6, 4, 6, 7, // back - 7, 6, 2, 7, 2, 3, // left - 2, 6, 5, 2, 5, 1, // up - 3, 0, 4, 3, 4, 7 // down - }; + 1, 5, 4, 1, 4, 0, // right + 4, 5, 6, 4, 6, 7, // back + 7, 6, 2, 7, 2, 3, // left + 2, 6, 5, 2, 5, 1, // up + 3, 0, 4, 3, 4, 7 // down + }; glGenBuffers(1, &_indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idxBuf), idxBuf, GL_STATIC_DRAW); + + if (Configuration::getInstance()->supportsShareableVAO()) + { + glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); + getGLProgramState()->applyAttributes(false); + + GL::bindVAO(0); + } } void Skybox::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) @@ -122,7 +122,7 @@ void Skybox::onDraw(const Mat4& transform, uint32_t flags) state->apply(transform); GLboolean depthFlag = glIsEnabled(GL_DEPTH_TEST); - GLint depthFunc; + GLint depthFunc; glGetIntegerv(GL_DEPTH_FUNC, &depthFunc); glEnable(GL_DEPTH_TEST); @@ -167,11 +167,25 @@ void Skybox::setTexture(TextureCube* texture) { CCASSERT(texture != nullptr, __FUNCTION__); - _texture = texture; - _texture->retain(); + texture->retain(); - auto state = getGLProgramState(); - state->setUniformTexture("u_Env", _texture); + if (_texture) + _texture->release(); + + _texture = texture; + + getGLProgramState()->setUniformTexture("u_Env", _texture); +} + +void Skybox::reload() +{ + auto glProgram = getGLProgramState()->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Shaders3D/Skybox.vert", "Shaders3D/Skybox.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + initBuffers(); } NS_CC_END diff --git a/cocos/3d/CCSkybox.h b/cocos/3d/CCSkybox.h index 5fd019ac73..55954e42c4 100644 --- a/cocos/3d/CCSkybox.h +++ b/cocos/3d/CCSkybox.h @@ -43,6 +43,8 @@ public: // Overrides virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void reload(); + CC_CONSTRUCTOR_ACCESS: Skybox(); virtual ~Skybox(); diff --git a/cocos/3d/CCTextureCube.cpp b/cocos/3d/CCTextureCube.cpp index 6c91d63cf9..5cd5e80322 100644 --- a/cocos/3d/CCTextureCube.cpp +++ b/cocos/3d/CCTextureCube.cpp @@ -146,6 +146,7 @@ Image* createImage(const std::string& path) TextureCube::TextureCube() { + _imgPath.resize(6); } TextureCube::~TextureCube() @@ -170,6 +171,13 @@ bool TextureCube::init(const std::string& positive_x, const std::string& negativ const std::string& positive_y, const std::string& negative_y, const std::string& positive_z, const std::string& negative_z) { + _imgPath[0] = positive_x; + _imgPath[1] = negative_x; + _imgPath[2] = positive_y; + _imgPath[3] = negative_y; + _imgPath[4] = positive_z; + _imgPath[5] = negative_z; + std::vector images(6); images[0] = createImage(positive_x); @@ -247,4 +255,9 @@ void TextureCube::setTexParameters(const TexParams& texParams) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } +bool TextureCube::reloadTexture() +{ + return init(_imgPath[0], _imgPath[1], _imgPath[2], _imgPath[3], _imgPath[4], _imgPath[5]); +} + NS_CC_END diff --git a/cocos/3d/CCTextureCube.h b/cocos/3d/CCTextureCube.h index 6e4272a536..460b4c6f0a 100644 --- a/cocos/3d/CCTextureCube.h +++ b/cocos/3d/CCTextureCube.h @@ -51,6 +51,8 @@ public: const std::string& positive_z, const std::string& negative_z); void setTexParameters(const TexParams&); + + bool reloadTexture(); CC_CONSTRUCTOR_ACCESS: TextureCube(); TextureCube(const TextureCube&); @@ -60,6 +62,8 @@ protected: bool init(const std::string& positive_x, const std::string& negative_x, const std::string& positive_y, const std::string& negative_y, const std::string& positive_z, const std::string& negative_z); +private: + std::vector _imgPath; }; NS_CC_END diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index edbb889330..059d9b055e 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -1,26 +1,26 @@ /**************************************************************************** - Copyright (c) 2012 cocos2d-x.org - Copyright (c) 2013-2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2012 cocos2d-x.org + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ #include "Sprite3DTest.h" @@ -54,7 +54,7 @@ static std::function createFunctions[] = CL(Sprite3DHitTest), CL(AsyncLoadSprite3DTest), #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) - // 3DEffect use custom shader which is not supported on WP8/WinRT yet. + // 3DEffect use custom shader which is not supported on WP8/WinRT yet. CL(Sprite3DEffectTest), CL(Sprite3DUVAnimationTest), CL(Sprite3DFakeShadowTest), @@ -82,7 +82,7 @@ static Layer* nextSpriteTestAction() { sceneIdx++; sceneIdx = sceneIdx % MAX_LAYER; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -93,7 +93,7 @@ static Layer* backSpriteTestAction() int total = MAX_LAYER; if( sceneIdx < 0 ) sceneIdx += total; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -111,7 +111,7 @@ static Layer* restartSpriteTestAction() //------------------------------------------------------------------ Sprite3DTestDemo::Sprite3DTestDemo(void) -: BaseTest() + : BaseTest() { } @@ -138,7 +138,7 @@ void Sprite3DTestDemo::restartCallback(Ref* sender) { auto s = new (std::nothrow) Sprite3DTestScene(); s->addChild(restartSpriteTestAction()); - + Director::getInstance()->replaceScene(s); s->release(); } @@ -195,7 +195,7 @@ Sprite3DBasicTest::Sprite3DBasicTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DBasicTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -205,26 +205,26 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) //int idx = (int)(CCRANDOM_0_1() * 1400.0f / 100.0f); //int x = (idx%5) * 85; //int y = (idx/5) * 121; - -// //option 1: load a obj that contain the texture in it -// auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); - + + // //option 1: load a obj that contain the texture in it + // auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); + //option 2: load obj and assign the texture auto sprite = Sprite3D::create("Sprite3DTest/boss1.obj"); sprite->setScale(3.f); sprite->setTexture("Sprite3DTest/boss.png"); - + // //sprite->setEffect(cocos2d::EFFECT_OUTLINE); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -237,7 +237,7 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -246,7 +246,7 @@ void Sprite3DBasicTest::onTouchesEnded(const std::vector& touches, Event for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -294,11 +294,11 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() for (auto i = 0; i < attributeCount; i++) { auto meshattribute = cylinder->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - cylinder->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + cylinder->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } @@ -309,13 +309,13 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() tRepeatParams.minFilter = GL_NEAREST; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; - shining_texture->setTexParameters(tRepeatParams); + shining_texture->setTexParameters(tRepeatParams); //pass the texture sampler to our custom shader _state->setUniformTexture("caustics",shining_texture); this->addChild(cylinder); - this->setCameraMask(2); + this->setCameraMask(2); this->addChild(camera); //adjust cylinder's position & rotation @@ -324,18 +324,18 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() //the callback function update cylinder's texcoord schedule(schedule_selector(Sprite3DUVAnimationTest::cylinderUpdate)); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -347,12 +347,12 @@ Sprite3DUVAnimationTest::~Sprite3DUVAnimationTest() #endif } -std::string Sprite3DUVAnimationTest::title() const +std::string Sprite3DUVAnimationTest::title() const { return "Testing UV Animation"; } -std::string Sprite3DUVAnimationTest::subtitle() const +std::string Sprite3DUVAnimationTest::subtitle() const { return ""; } @@ -387,13 +387,13 @@ void Sprite3DUVAnimationTest::cylinderUpdate(float dt) Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() { Size visibleSize = Director::getInstance()->getVisibleSize(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesBegan, this); listener->onTouchesMoved = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesMoved, this); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto layer = Layer::create(); addChild(layer,0); //create Camera @@ -412,18 +412,18 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() _plane->setGLProgramState(_state); //pass mesh's attribute to shader - long offset = 0; + long offset = 0; auto attributeCount = _plane->getMesh()->getMeshVertexAttribCount(); for (auto i = 0; i < attributeCount; i++) { auto meshattribute = _plane->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - _plane->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + _plane->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; - } + } _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); //create shadow texture @@ -433,9 +433,9 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); + shadowTexture->setTexParameters(tRepeatParams); _state->setUniformTexture("u_shadowTexture",shadowTexture); - layer->addChild(_plane); + layer->addChild(_plane); //create the orc _orc = Sprite3D::create("Sprite3DTest/orc.c3b"); @@ -449,30 +449,30 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() layer->setCameraMask(2); schedule(CC_SCHEDULE_SELECTOR(Sprite3DFakeShadowTest::updateCamera), 0.0f); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); - glProgram->link(); - glProgram->updateUniforms(); - - _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); - - //create shadow texture - auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); - Texture2D::TexParams tRepeatParams;//set texture parameters - tRepeatParams.magFilter = GL_LINEAR; - tRepeatParams.minFilter = GL_LINEAR; - tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; - tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); - _state->setUniformTexture("u_shadowTexture",shadowTexture); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); + + //create shadow texture + auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); + Texture2D::TexParams tRepeatParams;//set texture parameters + tRepeatParams.magFilter = GL_LINEAR; + tRepeatParams.minFilter = GL_LINEAR; + tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; + tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; + shadowTexture->setTexParameters(tRepeatParams); + _state->setUniformTexture("u_shadowTexture",shadowTexture); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -484,12 +484,12 @@ Sprite3DFakeShadowTest::~Sprite3DFakeShadowTest() #endif } -std::string Sprite3DFakeShadowTest::title() const +std::string Sprite3DFakeShadowTest::title() const { return "fake shadow effect"; } -std::string Sprite3DFakeShadowTest::subtitle() const +std::string Sprite3DFakeShadowTest::subtitle() const { return "touch the screen to move around"; } @@ -594,18 +594,18 @@ bool Sprite3DFakeShadowTest::isState(unsigned int state,unsigned int bit) const return (state & bit) == bit; } -void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event *event) +void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event* event) { } -void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event *event) +void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event* event) { } -void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event *event) +void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event* event) { - for ( auto &item: touches ) + for ( auto& item: touches ) { auto touch = item; auto location = touch->getLocationInView(); @@ -653,43 +653,43 @@ Sprite3DBasicToonShaderTest::Sprite3DBasicToonShaderTest() auto _camera = Camera::createPerspective(60, visibleSize.width/visibleSize.height, 0.1f, 200); _camera->setCameraFlag(CameraFlag::USER1); // create a teapot - auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); - //create and set our custom shader + auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + //create and set our custom shader auto shader =GLProgram::createWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); _state = GLProgramState::create(shader); teapot->setGLProgramState(_state); teapot->setPosition3D(Vec3(0,-5,-20)); - teapot->setRotation3D(Vec3(-90,180,0)); + teapot->setRotation3D(Vec3(-90,180,0)); auto rotate_action = RotateBy::create(1.5,Vec3(0,30,0)); - teapot->runAction(RepeatForever::create(rotate_action)); + teapot->runAction(RepeatForever::create(rotate_action)); //pass mesh's attribute to shader long offset = 0; auto attributeCount = teapot->getMesh()->getMeshVertexAttribCount(); for (auto i = 0; i < attributeCount; i++) { auto meshattribute = teapot->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - teapot->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } addChild(teapot); addChild(_camera); setCameraMask(2); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -701,19 +701,19 @@ Sprite3DBasicToonShaderTest::~Sprite3DBasicToonShaderTest() #endif } -std::string Sprite3DBasicToonShaderTest::title() const +std::string Sprite3DBasicToonShaderTest::title() const { return "basic toon shader test"; } -std::string Sprite3DBasicToonShaderTest::subtitle() const +std::string Sprite3DBasicToonShaderTest::subtitle() const { return " "; } //------------------------------------------------------------------ // -// Sprite3DLightMapTest +// Sprite3DLightMapTest // //------------------------------------------------------------------ Sprite3DLightMapTest::Sprite3DLightMapTest() @@ -725,16 +725,16 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() _camera->setCameraFlag(CameraFlag::USER1); _camera->setPosition3D(Vec3(0,25,15)); _camera->setRotation3D(Vec3(-35,0,0)); - auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); - LightMapScene->setScale(0.1f); + auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); + LightMapScene->setScale(0.1f); addChild(LightMapScene); - addChild(_camera); - setCameraMask(2); + addChild(_camera); + setCameraMask(2); //add a point light auto light = PointLight::create(Vec3(35,75,-20.5),Color3B(255,255,255),150); addChild(light); - //set the ambient light + //set the ambient light auto ambient = AmbientLight::create(Color3B(55,55,55)); addChild(ambient); @@ -745,14 +745,14 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() } Sprite3DLightMapTest::~Sprite3DLightMapTest() { - + } std::string Sprite3DLightMapTest::title() const { return "light map test"; } -std::string Sprite3DLightMapTest::subtitle() const +std::string Sprite3DLightMapTest::subtitle() const { return "drag the screen to move around"; } @@ -776,9 +776,9 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to cameraRightDir.normalize(); cameraRightDir.y=0; Vec3 cameraPos= _camera->getPosition3D(); - cameraPos+=cameraDir*newPos.y*delta; + cameraPos+=cameraDir*newPos.y*delta; cameraPos+=cameraRightDir*newPos.x*delta; - _camera->setPosition3D(cameraPos); + _camera->setPosition3D(cameraPos); } } @@ -790,33 +790,33 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to Sprite3DHitTest::Sprite3DHitTest() { auto s = Director::getInstance()->getWinSize(); - + auto sprite1 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite1->setScale(4.f); sprite1->setTexture("Sprite3DTest/boss.png"); sprite1->setPosition( Vec2(s.width/2, s.height/2) ); - + //add to scene addChild( sprite1 ); sprite1->runAction(RepeatForever::create(RotateBy::create(3, 360))); - + auto sprite2 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite2->setScale(4.f); sprite2->setTexture("Sprite3DTest/boss.png"); sprite2->setPosition( Vec2(s.width/2, s.height/2) ); sprite2->setAnchorPoint(Vec2(0.5, 0.5)); - + //add to scene addChild( sprite2 ); sprite2->runAction(RepeatForever::create(RotateBy::create(3, -360))); - - + + // Make sprite1 touchable auto listener1 = EventListenerTouchOneByOne::create(); listener1->setSwallowTouches(true); - + listener1->onTouchBegan = [](Touch* touch, Event* event){ auto target = static_cast(event->getCurrentTarget()); @@ -840,10 +840,10 @@ Sprite3DHitTest::Sprite3DHitTest() log("sprite3d onTouchesEnded.. "); target->setOpacity(255); }; - + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2); - + } std::string Sprite3DHitTest::title() const @@ -860,21 +860,21 @@ void Sprite3DTestScene::runThisTest() { auto layer = nextSpriteTestAction(); addChild(layer); - + Director::getInstance()->replaceScene(this); } Sprite3DTestScene::Sprite3DTestScene() { - + } -static int tuple_sort( const std::tuple &tuple1, const std::tuple &tuple2 ) +static int tuple_sort( const std::tuple& tuple1, const std::tuple& tuple2 ) { return std::get<0>(tuple1) < std::get<0>(tuple2); } -EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &objFilePath, const std::string &textureFilePath) +EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath) { auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(objFilePath)) @@ -888,11 +888,11 @@ EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &o return nullptr; } -EffectSprite3D* EffectSprite3D::create(const std::string &path) +EffectSprite3D* EffectSprite3D::create(const std::string& path) { if (path.length() < 4) CCASSERT(false, "improper name specified when creating Sprite3D"); - + auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(path)) { @@ -904,9 +904,9 @@ EffectSprite3D* EffectSprite3D::create(const std::string &path) } EffectSprite3D::EffectSprite3D() -: _defaultEffect(nullptr) + : _defaultEffect(nullptr) { - + } EffectSprite3D::~EffectSprite3D() @@ -918,7 +918,7 @@ EffectSprite3D::~EffectSprite3D() CC_SAFE_RELEASE(_defaultEffect); } -void EffectSprite3D::setEffect3D(Effect3D *effect) +void EffectSprite3D::setEffect3D(Effect3D* effect) { if(_defaultEffect == effect) return; CC_SAFE_RETAIN(effect); @@ -931,7 +931,7 @@ void EffectSprite3D::addEffect(Effect3DOutline* effect, ssize_t order) if(nullptr == effect) return; effect->retain(); effect->setTarget(this); - + _effects.push_back(std::make_tuple(order,effect,CustomCommand())); std::sort(std::begin(_effects), std::end(_effects), tuple_sort); @@ -986,26 +986,26 @@ Effect3DOutline* Effect3DOutline::create() bool Effect3DOutline::init() { - + return true; } Effect3DOutline::Effect3DOutline() -: _outlineWidth(1.0f) -, _outlineColor(1, 1, 1) -, _sprite(nullptr) + : _outlineWidth(1.0f) + , _outlineColor(1, 1, 1) + , _sprite(nullptr) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _glProgramState->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _glProgramState->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -1037,10 +1037,10 @@ void Effect3DOutline::setOutlineWidth(float width) } } -void Effect3DOutline::setTarget(EffectSprite3D *sprite) +void Effect3DOutline::setTarget(EffectSprite3D* sprite) { CCASSERT(nullptr != sprite && nullptr != sprite->getMesh(),"Error: Setting a null pointer or a null mesh EffectSprite3D to Effect3D"); - + if(sprite != _sprite) { GLProgram* glprogram; @@ -1054,16 +1054,16 @@ void Effect3DOutline::setTarget(EffectSprite3D *sprite) _glProgramState->retain(); _glProgramState->setUniformVec3("OutLineColor", _outlineColor); _glProgramState->setUniformFloat("OutlineWidth", _outlineWidth); - - + + _sprite = sprite; - + auto mesh = sprite->getMesh(); long offset = 0; for (auto i = 0; i < mesh->getMeshVertexAttribCount(); i++) { auto meshvertexattrib = mesh->getMeshVertexAttribute(i); - + _glProgramState->setVertexAttribPointer(s_attributeNames[meshvertexattrib.vertexAttrib], meshvertexattrib.size, meshvertexattrib.type, @@ -1072,12 +1072,12 @@ void Effect3DOutline::setTarget(EffectSprite3D *sprite) (void*)offset); offset += meshvertexattrib.attribSizeBytes; } - + Color4F color(_sprite->getDisplayedColor()); color.a = _sprite->getDisplayedOpacity() / 255.0f; _glProgramState->setUniformVec4("u_color", Vec4(color.r, color.g, color.b, color.a)); } - + } static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int paletteSize, const float* palette) @@ -1085,7 +1085,7 @@ static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int p glUniform4fv( uniform->location, (GLsizei)paletteSize, (const float*)palette ); } -void Effect3DOutline::draw(const Mat4 &transform) +void Effect3DOutline::draw(const Mat4& transform) { //draw Color4F color(_sprite->getDisplayedColor()); @@ -1096,10 +1096,10 @@ void Effect3DOutline::draw(const Mat4 &transform) glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glEnable(GL_DEPTH_TEST); - + auto mesh = _sprite->getMesh(); glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer()); - + auto skin = _sprite->getMesh()->getSkin(); if(_sprite && skin) { @@ -1107,14 +1107,14 @@ void Effect3DOutline::draw(const Mat4 &transform) skin->getMatrixPaletteSize(), (float*)skin->getMatrixPalette()); _glProgramState->setUniformCallback("u_matrixPalette", function); } - + if(_sprite) _glProgramState->apply(transform); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getIndexBuffer()); glDrawElements(mesh->getPrimitiveType(), (GLsizei)mesh->getIndexCount(), mesh->getIndexFormat(), 0); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, mesh->getIndexCount()); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_DEPTH_TEST); @@ -1123,18 +1123,18 @@ void Effect3DOutline::draw(const Mat4 &transform) } } -void EffectSprite3D::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) +void EffectSprite3D::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) { - for(auto &effect : _effects) + for(auto& effect : _effects) { if(std::get<0>(effect) >=0) break; - CustomCommand &cc = std::get<2>(effect); + CustomCommand& cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } - + if(!_defaultEffect) { Sprite3D::draw(renderer, transform, flags); @@ -1145,15 +1145,15 @@ void EffectSprite3D::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &tran _command.func = CC_CALLBACK_0(Effect3D::draw, _defaultEffect, transform); renderer->addCommand(&_command); } - - for(auto &effect : _effects) + + for(auto& effect : _effects) { if(std::get<0>(effect) <=0) continue; - CustomCommand &cc = std::get<2>(effect); + CustomCommand& cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } } @@ -1161,7 +1161,7 @@ Sprite3DEffectTest::Sprite3DEffectTest() { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DEffectTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1184,22 +1184,22 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) sprite->addEffect(effect, -1); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); - + Effect3DOutline* effect2 = Effect3DOutline::create(); sprite->addEffect(effect2, -2); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); //sprite->setEffect3D(effect); sprite->setScale(6.f); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -1212,7 +1212,7 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -1221,7 +1221,7 @@ void Sprite3DEffectTest::onTouchesEnded(const std::vector& touches, Even for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1233,22 +1233,22 @@ AsyncLoadSprite3DTest::AsyncLoadSprite3DTest() _paths.push_back("Sprite3DTest/orc.c3b"); _paths.push_back("Sprite3DTest/ReskinGirl.c3b"); _paths.push_back("Sprite3DTest/axe.c3b"); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"AsyncLoad Sprite3D"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite,this) ); - + auto s = Director::getInstance()->getWinSize(); item1->setPosition( s.width * .5f, s.height * .8f); - + auto pMenu1 = CCMenu::create(item1, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + auto node = Node::create(); node->setTag(101); this->addChild(node); - + menuCallback_asyncLoadSprite(nullptr); } @@ -1269,10 +1269,10 @@ void AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite(Ref* sender) { //Note that you must stop the tasks before leaving the scene. AsyncTaskPool::getInstance()->stopTasks(AsyncTaskPool::TaskType::TASK_IO); - + auto node = getChildByTag(101); node->removeAllChildren(); //remove all loaded sprite - + //remove cache data Sprite3DCache::getInstance()->removeAllSprite3DData(); long index = 0; @@ -1298,7 +1298,7 @@ Sprite3DWithSkinTest::Sprite3DWithSkinTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1347,7 +1347,7 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector& touches, Ev for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1357,7 +1357,7 @@ Sprite3DWithSkinOutlineTest::Sprite3DWithSkinOutlineTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinOutlineTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1372,33 +1372,33 @@ std::string Sprite3DWithSkinOutlineTest::subtitle() const void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) { - + std::string fileName = "Sprite3DTest/orc.c3b"; auto sprite = EffectSprite3D::create(fileName); - + Effect3DOutline* effect = Effect3DOutline::create(); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); sprite->addEffect(effect, -1); - + Effect3DOutline* effect2 = Effect3DOutline::create(); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); sprite->addEffect(effect2, -2); - + sprite->setScale(3); sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); bool inverse = (std::rand() % 3 == 0); - + int rand2 = std::rand(); float speed = 1.0f; if(rand2 % 3 == 1) @@ -1410,7 +1410,7 @@ void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) speed = animate->getSpeed() - 0.5 * CCRANDOM_0_1(); } animate->setSpeed(inverse ? -speed : speed); - + sprite->runAction(RepeatForever::create(animate)); } } @@ -1420,24 +1420,24 @@ void Sprite3DWithSkinOutlineTest::onTouchesEnded(const std::vector& touc for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } Animate3DTest::Animate3DTest() -: _hurt(nullptr) -, _swim(nullptr) -, _sprite(nullptr) -, _moveAction(nullptr) -, _elapseTransTime(0.f) + : _hurt(nullptr) + , _swim(nullptr) + , _sprite(nullptr) + , _moveAction(nullptr) + , _elapseTransTime(0.f) { addSprite3D(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Animate3DTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + scheduleUpdate(); } @@ -1463,7 +1463,7 @@ void Animate3DTest::update(float dt) if (_state == State::HURT_TO_SWIMMING) { _elapseTransTime += dt; - + if (_elapseTransTime >= Animate3D::getTransitionTime()) { _sprite->stopAction(_hurt); @@ -1496,13 +1496,13 @@ void Animate3DTest::addSprite3D() auto animate = Animate3D::create(animation, 0.f, 1.933f); _swim = RepeatForever::create(animate); sprite->runAction(_swim); - + _swim->retain(); _hurt = Animate3D::create(animation, 1.933f, 2.8f); _hurt->retain(); _state = State::SWIMMING; } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr); @@ -1536,7 +1536,7 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev for (auto touch: touches) { auto location = touch->getLocation(); - + if (_sprite) { float len = (_sprite->getPosition() - location).length(); @@ -1561,12 +1561,12 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev } AttachmentTest::AttachmentTest() -: _hasWeapon(false) -, _sprite(nullptr) + : _hasWeapon(false) + , _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(AttachmentTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1588,16 +1588,16 @@ void AttachmentTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; @@ -1618,11 +1618,11 @@ void AttachmentTest::onTouchesEnded(const std::vector& touches, Event* e _hasWeapon = !_hasWeapon; } Sprite3DReskinTest::Sprite3DReskinTest() -: _sprite(nullptr) + : _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DReskinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1630,11 +1630,11 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto label1 = Label::createWithTTF(ttfConfig,"Hair"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Glasses"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label3 = Label::createWithTTF(ttfConfig,"Coat"); auto item3 = MenuItemLabel::create(label3,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label4 = Label::createWithTTF(ttfConfig,"Pants"); - auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label5 = Label::createWithTTF(ttfConfig,"Shoes"); auto item5 = MenuItemLabel::create(label5,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); item1->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*4 ) ); @@ -1650,7 +1650,7 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto pMenu1 = CCMenu::create(item1, item2, item3, item4, item5, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + } void Sprite3DReskinTest::menuCallback_reSkin(Ref* sender) { @@ -1683,41 +1683,41 @@ void Sprite3DReskinTest::addNewSpriteWithCoords(Vec2 p) if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; - + auto& body = _skins[(int)SkinType::UPPER_BODY]; body.push_back("Girl_UpperBody01"); body.push_back("Girl_UpperBody02"); - + auto& pants = _skins[(int)SkinType::PANTS]; pants.push_back("Girl_LowerBody01"); pants.push_back("Girl_LowerBody02"); - + auto& shoes = _skins[(int)SkinType::SHOES]; shoes.push_back("Girl_Shoes01"); shoes.push_back("Girl_Shoes02"); - + auto& hair = _skins[(int)SkinType::HAIR]; hair.push_back("Girl_Hair01"); hair.push_back("Girl_Hair02"); - + auto& face = _skins[(int)SkinType::FACE]; face.push_back("Girl_Face01"); face.push_back("Girl_Face02"); - + auto& hand = _skins[(int)SkinType::HAND]; hand.push_back("Girl_Hand01"); hand.push_back("Girl_Hand02"); - + auto& glasses = _skins[(int)SkinType::GLASSES]; glasses.push_back(""); glasses.push_back("Girl_Glasses01"); - + memset(_curSkin, 0, (int)SkinType::MAX_TYPE * sizeof(int)); - + applyCurSkin(); } @@ -1750,7 +1750,7 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto s = Director::getInstance()->getWinSize(); initDrawBox(); - + addNewSpriteWithCoords(Vec2(s.width/2, s.height/2)); MenuItemFont::setFontName("fonts/arial.ttf"); MenuItemFont::setFontSize(65); @@ -1758,12 +1758,12 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() decrease->setColor(Color3B(0,200,20)); auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(Sprite3DWithOBBPerformanceTest::addOBBCallback, this)); increase->setColor(Color3B(0,200,20)); - + auto menu = Menu::create(decrease, increase, nullptr); menu->alignItemsHorizontally(); menu->setPosition(Vec2(s.width/2, s.height-65)); addChild(menu, 1); - + TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); _labelCubeCount = Label::createWithTTF(ttfCount,"0 cubes"); _labelCubeCount->setColor(Color3B(0,200,20)); @@ -1815,14 +1815,14 @@ void Sprite3DWithOBBPerformanceTest::onTouchesBegan(const std::vector& t void Sprite3DWithOBBPerformanceTest::onTouchesEnded(const std::vector& touches, Event* event) { - + } void Sprite3DWithOBBPerformanceTest::onTouchesMoved(const std::vector& touches, Event* event) { for (const auto& touch: touches) { - auto location = touch->getLocation(); + auto location = touch->getLocation(); auto obbSize = _obb.size(); for(decltype(obbSize) i = 0; i < obbSize; i++) @@ -1838,23 +1838,23 @@ void Sprite3DWithOBBPerformanceTest::update(float dt) char szText[16]; sprintf(szText,"%lu cubes",_obb.size()); _labelCubeCount->setString(szText); - + if (_drawDebug) { _drawDebug->clear(); - + Mat4 mat = _sprite->getNodeToWorldTransform(); mat.getRightVector(&_obbt._xAxis); _obbt._xAxis.normalize(); - + mat.getUpVector(&_obbt._yAxis); _obbt._yAxis.normalize(); - + mat.getForwardVector(&_obbt._zAxis); _obbt._zAxis.normalize(); - + _obbt._center = _sprite->getPosition3D(); - + Vec3 corners[8] = {}; _obbt.getCorners(corners); _drawDebug->drawCube(corners, Color4F(0,0,1,1)); @@ -1893,16 +1893,16 @@ void Sprite3DWithOBBPerformanceTest::addNewSpriteWithCoords(Vec2 p) auto animate = Animate3D::create(animation, 0.f, 1.933f); sprite->runAction(RepeatForever::create(animate)); } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Sprite3DWithOBBPerformanceTest::reachEndCallBack, this)), nullptr); seq->setTag(100); sprite->runAction(seq); - + AABB aabb = _sprite->getAABB(); _obbt = OBB(aabb); - + _drawDebug = DrawNode3D::create(); addChild(_drawDebug); } @@ -1956,23 +1956,23 @@ void Sprite3DWithOBBPerformanceTest::delOBBWithCount(float value) void Sprite3DWithOBBPerformanceTest::unproject(const Mat4& viewProjection, const Size* viewport, Vec3* src, Vec3* dst) { assert(dst); - + assert(viewport->width != 0.0f && viewport->height != 0.0f); Vec4 screen(src->x / viewport->width, ((viewport->height - src->y)) / viewport->height, src->z, 1.0f); - + screen.x = screen.x * 2.0f - 1.0f; screen.y = screen.y * 2.0f - 1.0f; screen.z = screen.z * 2.0f - 1.0f; - + viewProjection.getInversed().transformVector(screen, &screen); - + if (screen.w != 0.0f) { screen.x /= screen.w; screen.y /= screen.w; screen.z /= screen.w; } - + dst->set(screen.x, screen.y, screen.z); } @@ -1981,26 +1981,26 @@ void Sprite3DWithOBBPerformanceTest::calculateRayByLocationInView(Ray* ray, cons auto dir = Director::getInstance(); auto view = dir->getWinSize(); auto mat = dir->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - + Vec3 src = Vec3(location.x, location.y, -1); Vec3 nearPoint; unproject(mat, &view, &src, &nearPoint); - + src = Vec3(location.x, location.y, 1); Vec3 farPoint; unproject(mat, &view, &src, &farPoint); - + Vec3 direction; Vec3::subtract(farPoint, nearPoint, &direction); direction.normalize(); - + ray->_origin = nearPoint; ray->_direction = direction; } Sprite3DMirrorTest::Sprite3DMirrorTest() -: _sprite(nullptr) -, _mirrorSprite(nullptr) + : _sprite(nullptr) + , _mirrorSprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); @@ -2022,21 +2022,21 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x - 80, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; _hasWeapon = true; - + //create mirror Sprite3D sprite = Sprite3D::create(fileName); sprite->setScale(5); @@ -2045,25 +2045,25 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x + 80, p.y) ); - + //test attach sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _mirrorSprite = sprite; } QuaternionTest::QuaternionTest() -: _arcSpeed(CC_DEGREES_TO_RADIANS(90)) -, _radius(100.f) -, _accAngle(0.f) + : _arcSpeed(CC_DEGREES_TO_RADIANS(90)) + , _radius(100.f) + , _accAngle(0.f) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords(Vec2(s.width / 2.f, s.height / 2.f)); @@ -2101,20 +2101,20 @@ void QuaternionTest::update(float delta) const float pi = M_PI; if (_accAngle >= 2 * pi) _accAngle -= 2 * pi; - + auto s = Director::getInstance()->getWinSize(); _sprite->setPosition(Vec2(s.width / 2.f + _radius * cosf(_accAngle), s.height / 2.f + _radius * sinf(_accAngle))); - + Quaternion quat; Quaternion::createFromAxisAngle(Vec3(0.f, 0.f, 1.f), _accAngle - pi * 0.5f, &quat); _sprite->setRotationQuat(quat); } UseCaseSprite3D::UseCaseSprite3D() -: _caseIdx(0) + : _caseIdx(0) { auto s = Director::getInstance()->getWinSize(); - + _useCaseTitles[0] = "transparent 3d sprite and 2d sprite"; _useCaseTitles[1] = "ui - 3d - ui"; @@ -2131,28 +2131,28 @@ UseCaseSprite3D::UseCaseSprite3D() _caseIdx++; if (_caseIdx >= (int)USECASE::MAX_CASE_NUM) _caseIdx = 0; - this->switchCase(); - }); - + this->switchCase(); + }); + auto menu = Menu::create(itemPrev, itemNext, nullptr); menu->alignItemsHorizontally(); menu->setScale(0.5); menu->setAnchorPoint(Vec2(0,0)); menu->setPosition(Vec2(s.width/2,70)); - + _label = Label::create(); _label->setPosition(s.width * 0.5f, s.height * 0.8f); addChild(_label); - + addChild(menu); - + //setup camera auto camera = Camera::createPerspective(40, s.width / s.height, 0.01f, 1000.f); camera->setCameraFlag(CameraFlag::USER1); camera->setPosition3D(Vec3(0.f, 30.f, 100.f)); camera->lookAt(Vec3(0.f, 0.f, 0.f)); addChild(camera); - + switchCase(); } @@ -2169,7 +2169,7 @@ std::string UseCaseSprite3D::subtitle() const void UseCaseSprite3D::switchCase() { removeChildByTag(101); - + auto s = Director::getInstance()->getWinSize(); _label->setString(_useCaseTitles[_caseIdx]); if (_caseIdx == 0) // use case 1, 3d transparent sprite + 2d sprite @@ -2181,33 +2181,33 @@ void UseCaseSprite3D::switchCase() if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } - + auto circleBack = Sprite3D::create(); auto circle = Sprite::create("Sprite3DTest/circle.png"); circleBack->setScale(0.5f); circleBack->addChild(circle); circle->runAction(RepeatForever::create(RotateBy::create(3, Vec3(0.f, 0.f, 360.f)))); - + circleBack->setRotation3D(Vec3(90, 0, 0)); - + auto pos = sprite->getPosition3D(); circleBack->setPosition3D(Vec3(pos.x, pos.y, pos.z - 1)); - + sprite->setOpacity(250); sprite->setCameraMask(2); circleBack->setCameraMask(2); sprite->setTag(3); circleBack->setTag(2); - + auto node = Node::create(); node->addChild(sprite); node->addChild(circleBack); node->setTag(101); addChild(node); - + scheduleUpdate(); update(0.f); } @@ -2217,7 +2217,7 @@ void UseCaseSprite3D::switchCase() layer->setPosition(s.width * 0.25f, s.height * 0.25f); layer->setGlobalZOrder(-1); addChild(layer); - + std::string filename = "Sprite3DTest/girl.c3b"; auto sprite = Sprite3D::create(filename); sprite->setScale(0.5f); @@ -2229,20 +2229,20 @@ void UseCaseSprite3D::switchCase() } sprite->setPosition(s.width * 0.25f, s.height * 0.125f); layer->addChild(sprite); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"Message"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Message"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); - + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); + item1->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height ) ); item2->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height * 2.f ) ); - + auto pMenu1 = CCMenu::create(item1, item2, nullptr); pMenu1->setPosition(Vec2(0,0)); layer->addChild(pMenu1); - + layer->setTag(101); } } @@ -2275,14 +2275,14 @@ void UseCaseSprite3D::update(float delta) { static float accAngle = 0.f; accAngle += delta * CC_DEGREES_TO_RADIANS(60); - + float radius = 30.f; float x = cosf(accAngle) * radius, z = sinf(accAngle) * radius; - + auto node = getChildByTag(101); auto sprite3d = node->getChildByTag(3); auto circle = node->getChildByTag(2); - + sprite3d->setPositionX(x); sprite3d->setPositionZ(z); circle->setPositionX(x); @@ -2291,8 +2291,9 @@ void UseCaseSprite3D::update(float delta) } Sprite3DCubeMapTest::Sprite3DCubeMapTest() : -_sprite(nullptr), -_textureCube(nullptr) + _textureCube(nullptr), + _skyBox(nullptr), + _teapot(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords(Vec2(s.width / 2, s.height / 2)); @@ -2300,6 +2301,12 @@ _textureCube(nullptr) Sprite3DCubeMapTest::~Sprite3DCubeMapTest() { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener); +#endif + + _teapot->release(); + _skyBox->release(); _textureCube->release(); } @@ -2320,18 +2327,18 @@ void Sprite3DCubeMapTest::addNewSpriteWithCoords(Vec2 p) _camera->setCameraFlag(CameraFlag::USER1); // create a teapot - auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + _teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + _teapot->retain(); //create and set our custom shader auto shader = GLProgram::createWithFilenames("Sprite3DTest/cube_map.vert", "Sprite3DTest/cube_map.frag"); - auto _state = GLProgramState::create(shader); + auto state = GLProgramState::create(shader); // create the second texture for cylinder _textureCube = TextureCube::create("Sprite3DTest/skybox/left.jpg", "Sprite3DTest/skybox/right.jpg", - "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", - "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); + "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", + "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); - // temporary solution _textureCube->retain(); //set texture parameters @@ -2343,40 +2350,66 @@ void Sprite3DCubeMapTest::addNewSpriteWithCoords(Vec2 p) _textureCube->setTexParameters(tRepeatParams); // pass the texture sampler to our custom shader - _state->setUniformTexture("u_cubeTex", _textureCube); + state->setUniformTexture("u_cubeTex", _textureCube); - teapot->setGLProgramState(_state); - teapot->setPosition3D(Vec3(0, -5, -20)); - teapot->setRotation3D(Vec3(-90, 180, 0)); + _teapot->setGLProgramState(state); + _teapot->setPosition3D(Vec3(0, -5, -20)); + _teapot->setRotation3D(Vec3(-90, 180, 0)); auto rotate_action = RotateBy::create(1.5, Vec3(0, 30, 0)); - teapot->runAction(RepeatForever::create(rotate_action)); + _teapot->runAction(RepeatForever::create(rotate_action)); //pass mesh's attribute to shader long offset = 0; - auto attributeCount = teapot->getMesh()->getMeshVertexAttribCount(); + auto attributeCount = _teapot->getMesh()->getMeshVertexAttribCount(); for (auto i = 0; i < attributeCount; i++) { - auto meshattribute = teapot->getMesh()->getMeshVertexAttribute(i); - _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - teapot->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + auto meshattribute = _teapot->getMesh()->getMeshVertexAttribute(i); + state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], + meshattribute.size, + meshattribute.type, + GL_FALSE, + _teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } - addChild(teapot); + addChild(_teapot); addChild(_camera); setCameraMask(2); { - // config skybox - Skybox* box = Skybox::create(); - box->setTexture(_textureCube); - addChild(box); + // config skybox + _skyBox = Skybox::create(); + _skyBox->retain(); - //auto rotate_action = RotateBy::create(1.5, Vec3(0, -30, 0)); - //box->runAction(RepeatForever::create(rotate_action)); + _skyBox->setTexture(_textureCube); + addChild(_skyBox); } + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, + [this](EventCustom*) + { + auto state = _teapot->getGLProgramState(); + auto glProgram = state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/cube_map.vert", "Sprite3DTest/cube_map.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + _textureCube->reloadTexture(); + + Texture2D::TexParams tRepeatParams; + tRepeatParams.magFilter = GL_NEAREST; + tRepeatParams.minFilter = GL_NEAREST; + tRepeatParams.wrapS = GL_MIRRORED_REPEAT; + tRepeatParams.wrapT = GL_MIRRORED_REPEAT; + _textureCube->setTexParameters(tRepeatParams); + state->setUniformTexture("u_cubeTex", _textureCube); + + _skyBox->reload(); + _skyBox->setTexture(_textureCube); + }); + Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); +#endif } diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 7a7ff1a74d..8e1cbf20f3 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -1,25 +1,25 @@ /**************************************************************************** - Copyright (c) 2013 cocos2d-x.org - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ #ifndef _SPRITE3D_TEST_H_ @@ -30,12 +30,12 @@ #include namespace cocos2d { - class Animate3D; - class Sprite3D; - class Delay; - class Ray; - class DrawNode3D; - class GLProgramState; +class Animate3D; +class Sprite3D; +class Delay; +class Ray; +class DrawNode3D; +class GLProgramState; } class Sprite3DTestDemo : public BaseTest @@ -43,11 +43,11 @@ class Sprite3DTestDemo : public BaseTest public: Sprite3DTestDemo(void); virtual ~Sprite3DTestDemo(void); - + void restartCallback(Ref* sender); void nextCallback(Ref* sender); void backCallback(Ref* sender); - + // overrides virtual std::string title() const override; virtual std::string subtitle() const override; @@ -70,7 +70,7 @@ public: Sprite3DBasicTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -83,14 +83,14 @@ public: virtual ~Sprite3DUVAnimationTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + protected: void cylinderUpdate(float dt); - + float _cylinder_texture_offset; float _shining_duraion; - GLProgramState * _state; - + GLProgramState* _state; + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif @@ -116,17 +116,17 @@ public: void move3D(float elapsedTime); void updateState(float elapsedTime); bool isState(unsigned int state,unsigned int bit) const; - 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 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); private: - cocos2d::Camera * _camera; + cocos2d::Camera* _camera; Vec3 _targetPos; unsigned int _curState; - cocos2d::Sprite3D * _plane; - cocos2d::Sprite3D * _orc; - GLProgramState * _state; - + cocos2d::Sprite3D* _plane; + cocos2d::Sprite3D* _orc; + GLProgramState* _state; + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif @@ -142,7 +142,7 @@ public: virtual std::string subtitle() const override; void onTouchesMoved(const std::vector& touches, cocos2d::Event* event); private: - Camera * _camera; + Camera* _camera; }; class Sprite3DBasicToonShaderTest : public Sprite3DTestDemo @@ -153,10 +153,10 @@ public: virtual ~Sprite3DBasicToonShaderTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + protected: - GLProgramState * _state; - + GLProgramState* _state; + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif @@ -167,8 +167,8 @@ class EffectSprite3D; class Effect3D : public Ref { public: - virtual void draw(const Mat4 &transform) = 0; - virtual void setTarget(EffectSprite3D *sprite) = 0; + virtual void draw(const Mat4& transform) = 0; + virtual void setTarget(EffectSprite3D* sprite) = 0; protected: Effect3D() : _glProgramState(nullptr) {} virtual ~Effect3D() @@ -183,20 +183,20 @@ class Effect3DOutline: public Effect3D { public: static Effect3DOutline* create(); - + void setOutlineColor(const Vec3& color); - + void setOutlineWidth(float width); - - virtual void draw(const Mat4 &transform) override; - virtual void setTarget(EffectSprite3D *sprite) override; + + virtual void draw(const Mat4& transform) override; + virtual void setTarget(EffectSprite3D* sprite) override; protected: - + Effect3DOutline(); virtual ~Effect3DOutline(); - + bool init(); - + Vec3 _outlineColor; float _outlineWidth; //weak reference @@ -204,16 +204,16 @@ protected: #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif - + protected: static const std::string _vertShaderFile; static const std::string _fragShaderFile; static const std::string _keyInGLProgramCache; - + static const std::string _vertSkinnedShaderFile; static const std::string _fragSkinnedShaderFile; static const std::string _keySkinnedInGLProgramCache; - + static GLProgram* getOrCreateProgram(bool isSkinned = false); }; @@ -231,14 +231,14 @@ class EffectSprite3D : public Sprite3D public: static EffectSprite3D* createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath); static EffectSprite3D* create(const std::string& path); - + void setEffect3D(Effect3D* effect); void addEffect(Effect3DOutline* effect, ssize_t order); - virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override; + virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; protected: EffectSprite3D(); virtual ~EffectSprite3D(); - + std::vector> _effects; Effect3D* _defaultEffect; CustomCommand _command; @@ -251,9 +251,9 @@ public: Sprite3DEffectTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -265,11 +265,11 @@ public: virtual ~AsyncLoadSprite3DTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void menuCallback_asyncLoadSprite(Ref* sender); - + void asyncLoad_Callback(Sprite3D* sprite, void* param); - + protected: std::vector _paths; //model paths to be loaded }; @@ -281,9 +281,9 @@ public: Sprite3DWithSkinTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -294,9 +294,9 @@ public: Sprite3DWithSkinOutlineTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -308,14 +308,14 @@ public: ~Animate3DTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void onTouchesEnded(const std::vector& touches, Event* event); - + virtual void update(float dt) override; - + protected: void addSprite3D(); - + enum class State { SWIMMING, @@ -323,20 +323,20 @@ protected: HURT, HURT_TO_SWIMMING, }; - + void reachEndCallBack(); - + void renewCallBack(); - + cocos2d::Sprite3D* _sprite; - + cocos2d::Action* _swim; cocos2d::Animate3D* _hurt; float _elapseTransTime; - + State _state; - + MoveTo* _moveAction; }; @@ -347,11 +347,11 @@ public: AttachmentTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void onTouchesEnded(const std::vector& touches, Event* event); - + void addNewSpriteWithCoords(Vec2 p); - + protected: bool _hasWeapon; cocos2d::Sprite3D* _sprite; @@ -366,11 +366,11 @@ public: virtual std::string subtitle() const override; void onTouchesEnded(const std::vector& touches, Event* event); void addNewSpriteWithCoords(Vec2 p); - + void menuCallback_reSkin(Ref* sender); protected: void applyCurSkin(); - + enum class SkinType { UPPER_BODY = 0, @@ -382,7 +382,7 @@ protected: GLASSES, MAX_TYPE, }; - + std::vector _skins[(int)SkinType::MAX_TYPE]; //all skins int _curSkin[(int)SkinType::MAX_TYPE]; //current skin index cocos2d::Sprite3D* _sprite; @@ -416,7 +416,7 @@ protected: std::set _intersetList; void initDrawBox(); void reachEndCallBack(); - + void unproject(const Mat4& viewProjection, const Size* viewport, Vec3* src, Vec3* dst); void calculateRayByLocationInView(Ray* ray, const Vec2& location); }; @@ -428,9 +428,9 @@ public: Sprite3DMirrorTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + protected: bool _hasWeapon; cocos2d::Sprite3D* _sprite; @@ -444,10 +444,10 @@ public: QuaternionTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); virtual void update(float delta) override; - + protected: cocos2d::Sprite3D* _sprite; float _arcSpeed; @@ -463,15 +463,15 @@ public: UseCaseSprite3D(); virtual std::string title() const override; virtual std::string subtitle() const override; - + virtual void update(float delta) override; - + void menuCallback_Message(Ref* sender); - + protected: - + void switchCase(); - + enum class USECASE{ _3D_WITH_2D, _UI_3D_UI, @@ -491,7 +491,8 @@ public: namespace cocos2d { - class TextureCube; +class TextureCube; +class Skybox; } class Sprite3DCubeMapTest : public Sprite3DTestDemo { @@ -505,8 +506,13 @@ public: void addNewSpriteWithCoords(Vec2); protected: - cocos2d::Sprite3D* _sprite; cocos2d::TextureCube* _textureCube; + Skybox* _skyBox; + Sprite3D* _teapot; + +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) + EventListenerCustom* _backToForegroundListener; +#endif }; #endif From aa0193044b36d00f2392a300ce7d232a86ad99b0 Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Tue, 24 Mar 2015 15:49:24 +0800 Subject: [PATCH 09/27] discard modify of lua_cocos2dx_3d_auto.cpp --- .../auto/lua_cocos2dx_3d_auto.cpp | 216 ++---------------- 1 file changed, 23 insertions(+), 193 deletions(-) diff --git a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp index e500da44bb..9968e1800a 100644 --- a/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp +++ b/cocos/scripting/lua-bindings/auto/lua_cocos2dx_3d_auto.cpp @@ -1293,14 +1293,14 @@ int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* tolua_S) if (!ok) { break; } std::function arg2; do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if (!ok) { break; } void* arg3; #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; + ok = false; if (!ok) { break; } cocos2d::Sprite3D::createAsync(arg0, arg1, arg2, arg3); lua_settop(tolua_S, 1); @@ -1317,14 +1317,14 @@ int lua_cocos2dx_3d_Sprite3D_createAsync(lua_State* tolua_S) if (!ok) { break; } std::function arg1; do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if (!ok) { break; } void* arg2; #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; + ok = false; if (!ok) { break; } cocos2d::Sprite3D::createAsync(arg0, arg1, arg2); lua_settop(tolua_S, 1); @@ -2871,192 +2871,22 @@ int lua_register_cocos2dx_3d_BillBoard(lua_State* tolua_S) g_typeCast["BillBoard"] = "cc.BillBoard"; return 1; } - -int lua_cocos2dx_3d_TextureCube_create(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; -#if COCOS2D_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if COCOS2D_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "cc.TextureCube", 0, &tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - do - { - if (argc == 6) - { - std::string positive_x; - ok &= luaval_to_std_string(tolua_S, 2, &positive_x, "cc.TextureCube:create"); - if (!ok) { break; } - - std::string negative_x; - ok &= luaval_to_std_string(tolua_S, 3, &negative_x, "cc.TextureCube:create"); - if (!ok){ break; } - - std::string positive_y; - ok &= luaval_to_std_string(tolua_S, 4, &positive_y, "cc.TextureCube:create"); - if (!ok) { break; } - - std::string negative_y; - ok &= luaval_to_std_string(tolua_S, 5, &negative_y, "cc.TextureCube:create"); - if (!ok){ break; } - - std::string positive_z; - ok &= luaval_to_std_string(tolua_S, 6, &positive_z, "cc.TextureCube:create"); - if (!ok) { break; } - - std::string negative_z; - ok &= luaval_to_std_string(tolua_S, 7, &negative_z, "cc.TextureCube:create"); - if (!ok){ break; } - - cocos2d::TextureCube* ret = cocos2d::TextureCube::create(positive_x, negative_x, - positive_y, negative_y, - positive_z, negative_z); - object_to_luaval(tolua_S, "cc.TextureCube", (cocos2d::TextureCube*)ret); - return 1; - } - } while (0); - - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "cc.TextureCube:create", argc, 6); - return 0; -#if COCOS2D_DEBUG >= 1 -tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'lua_cocos2dx_3d_TextureCube_create'.", &tolua_err); -#endif - return 0; -} - -int lua_register_cocos2dx_3d_TextureCube(lua_State* tolua_S) -{ - tolua_usertype(tolua_S, "cc.TextureCube"); - tolua_cclass(tolua_S, "TextureCube", "cc.TextureCube", "cc.Texture2D", nullptr); - - tolua_beginmodule(tolua_S, "TextureCube"); - tolua_function(tolua_S, "create", lua_cocos2dx_3d_TextureCube_create); - tolua_endmodule(tolua_S); - std::string typeName = typeid(cocos2d::TextureCube).name(); - g_luaType[typeName] = "cc.TextureCube"; - g_typeCast["TextureCube"] = "cc.TextureCube"; - return 1; -} - -int lua_cocos2dx_3d_Skybox_create(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; -#if COCOS2D_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if COCOS2D_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "cc.Skybox", 0, &tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - do - { - if (argc == 0) - { - cocos2d::Skybox* ret = cocos2d::Skybox::create(); - object_to_luaval(tolua_S, "cc.Skybox", (cocos2d::Skybox*)ret); - return 1; - } - } while (0); - - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "cc.Skybox:create", argc, 0); - return 0; -#if COCOS2D_DEBUG >= 1 -tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'lua_cocos2dx_3d_Skybox_create'.", &tolua_err); -#endif - return 0; -} - -int lua_cocos2dx_3d_Skybox_setTexture(lua_State* tolua_S) -{ - int argc = 0; - cocos2d::Skybox* cobj = nullptr; - bool ok = true; -#if COCOS2D_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if COCOS2D_DEBUG >= 1 - if (!tolua_isusertype(tolua_S, 1, "cc.Skybox", 0, &tolua_err)) goto tolua_lerror; -#endif - cobj = (cocos2d::Skybox*)tolua_tousertype(tolua_S, 1, 0); -#if COCOS2D_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S, "invalid 'cobj' in function 'lua_cocos2dx_3d_Skybox_setTexture'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S) - 1; - do{ - if (argc == 1) - { - cocos2d::TextureCube* arg0; - ok &= luaval_to_object(tolua_S, 2, "cc.TextureCube", &arg0); - - if (!ok) { break; } - cobj->setTexture(arg0); - lua_settop(tolua_S, 1); - return 1; - } - } while (0); - - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Skybox:setTexture", argc, 1); - return 0; - -#if COCOS2D_DEBUG >= 1 -tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'lua_cocos2dx_3d_Skybox_setTexture'.", &tolua_err); -#endif - - return 0; -} - -int lua_register_cocos2dx_3d_Skybox(lua_State* tolua_S) -{ - tolua_usertype(tolua_S, "cc.Skybox"); - tolua_cclass(tolua_S, "Skybox", "cc.Skybox", "cc.Node", nullptr); - - tolua_beginmodule(tolua_S, "Skybox"); - tolua_function(tolua_S, "create", lua_cocos2dx_3d_Skybox_create); - tolua_function(tolua_S, "setTexture", lua_cocos2dx_3d_Skybox_setTexture); - tolua_endmodule(tolua_S); - - std::string typeName = typeid(cocos2d::Skybox).name(); - g_luaType[typeName] = "cc.Skybox"; - g_typeCast["Skybox"] = "cc.Skybox"; - return 1; -} - TOLUA_API int register_all_cocos2dx_3d(lua_State* tolua_S) { - tolua_open(tolua_S); - - tolua_module(tolua_S,"cc",0); - tolua_beginmodule(tolua_S,"cc"); + tolua_open(tolua_S); + + tolua_module(tolua_S,"cc",0); + tolua_beginmodule(tolua_S,"cc"); - lua_register_cocos2dx_3d_Animate3D(tolua_S); - lua_register_cocos2dx_3d_Sprite3D(tolua_S); - lua_register_cocos2dx_3d_AttachNode(tolua_S); - lua_register_cocos2dx_3d_BillBoard(tolua_S); - lua_register_cocos2dx_3d_Animation3D(tolua_S); - lua_register_cocos2dx_3d_Skeleton3D(tolua_S); - lua_register_cocos2dx_3d_Mesh(tolua_S); - lua_register_cocos2dx_3d_TextureCube(tolua_S); - lua_register_cocos2dx_3d_Skybox(tolua_S); + lua_register_cocos2dx_3d_Animate3D(tolua_S); + lua_register_cocos2dx_3d_Sprite3D(tolua_S); + lua_register_cocos2dx_3d_AttachNode(tolua_S); + lua_register_cocos2dx_3d_BillBoard(tolua_S); + lua_register_cocos2dx_3d_Animation3D(tolua_S); + lua_register_cocos2dx_3d_Skeleton3D(tolua_S); + lua_register_cocos2dx_3d_Mesh(tolua_S); - tolua_endmodule(tolua_S); - return 1; + tolua_endmodule(tolua_S); + return 1; } From 3b8a796404f06e4be1819f1e52c34098ef8cf2a6 Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Tue, 24 Mar 2015 16:01:06 +0800 Subject: [PATCH 10/27] config project config file for cocos2d-win8.1-universal --- .../libcocos2d_8_1.Shared.vcxitems | 4 ++++ .../libcocos2d_8_1.Shared.vcxitems.filters | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems index 37ebf55506..ca8763fcb5 100644 --- a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems +++ b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems @@ -78,8 +78,10 @@ + + @@ -504,8 +506,10 @@ + + NotUsing diff --git a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters index 41cc21558d..2df2089162 100644 --- a/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters +++ b/cocos/2d/libcocos2d_8_1/libcocos2d_8_1/libcocos2d_8_1.Shared/libcocos2d_8_1.Shared.vcxitems.filters @@ -1291,6 +1291,12 @@ physics + + 3d + + + 3d + @@ -2378,6 +2384,12 @@ base\allocator + + 3d + + + 3d + From 2ebc854335b62b11d0f8eadd4a5177cb1f2eee44 Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Wed, 25 Mar 2015 11:36:11 +0800 Subject: [PATCH 11/27] Modify code style --- .../Classes/Sprite3DTest/Sprite3DTest.cpp | 612 +++++++++--------- 1 file changed, 306 insertions(+), 306 deletions(-) diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 059d9b055e..2aa3c7a972 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -1,26 +1,26 @@ /**************************************************************************** - Copyright (c) 2012 cocos2d-x.org - Copyright (c) 2013-2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2012 cocos2d-x.org + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ #include "Sprite3DTest.h" @@ -54,7 +54,7 @@ static std::function createFunctions[] = CL(Sprite3DHitTest), CL(AsyncLoadSprite3DTest), #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) - // 3DEffect use custom shader which is not supported on WP8/WinRT yet. + // 3DEffect use custom shader which is not supported on WP8/WinRT yet. CL(Sprite3DEffectTest), CL(Sprite3DUVAnimationTest), CL(Sprite3DFakeShadowTest), @@ -82,7 +82,7 @@ static Layer* nextSpriteTestAction() { sceneIdx++; sceneIdx = sceneIdx % MAX_LAYER; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -93,7 +93,7 @@ static Layer* backSpriteTestAction() int total = MAX_LAYER; if( sceneIdx < 0 ) sceneIdx += total; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -111,7 +111,7 @@ static Layer* restartSpriteTestAction() //------------------------------------------------------------------ Sprite3DTestDemo::Sprite3DTestDemo(void) - : BaseTest() +: BaseTest() { } @@ -138,7 +138,7 @@ void Sprite3DTestDemo::restartCallback(Ref* sender) { auto s = new (std::nothrow) Sprite3DTestScene(); s->addChild(restartSpriteTestAction()); - + Director::getInstance()->replaceScene(s); s->release(); } @@ -195,7 +195,7 @@ Sprite3DBasicTest::Sprite3DBasicTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DBasicTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -205,26 +205,26 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) //int idx = (int)(CCRANDOM_0_1() * 1400.0f / 100.0f); //int x = (idx%5) * 85; //int y = (idx/5) * 121; - - // //option 1: load a obj that contain the texture in it - // auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); - + +// //option 1: load a obj that contain the texture in it +// auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); + //option 2: load obj and assign the texture auto sprite = Sprite3D::create("Sprite3DTest/boss1.obj"); sprite->setScale(3.f); sprite->setTexture("Sprite3DTest/boss.png"); - + // //sprite->setEffect(cocos2d::EFFECT_OUTLINE); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -237,7 +237,7 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -246,7 +246,7 @@ void Sprite3DBasicTest::onTouchesEnded(const std::vector& touches, Event for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -294,11 +294,11 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() for (auto i = 0; i < attributeCount; i++) { auto meshattribute = cylinder->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - cylinder->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + cylinder->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } @@ -309,13 +309,13 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() tRepeatParams.minFilter = GL_NEAREST; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; - shining_texture->setTexParameters(tRepeatParams); + shining_texture->setTexParameters(tRepeatParams); //pass the texture sampler to our custom shader _state->setUniformTexture("caustics",shining_texture); this->addChild(cylinder); - this->setCameraMask(2); + this->setCameraMask(2); this->addChild(camera); //adjust cylinder's position & rotation @@ -324,18 +324,18 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() //the callback function update cylinder's texcoord schedule(schedule_selector(Sprite3DUVAnimationTest::cylinderUpdate)); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -347,12 +347,12 @@ Sprite3DUVAnimationTest::~Sprite3DUVAnimationTest() #endif } -std::string Sprite3DUVAnimationTest::title() const +std::string Sprite3DUVAnimationTest::title() const { return "Testing UV Animation"; } -std::string Sprite3DUVAnimationTest::subtitle() const +std::string Sprite3DUVAnimationTest::subtitle() const { return ""; } @@ -387,13 +387,13 @@ void Sprite3DUVAnimationTest::cylinderUpdate(float dt) Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() { Size visibleSize = Director::getInstance()->getVisibleSize(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesBegan, this); listener->onTouchesMoved = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesMoved, this); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto layer = Layer::create(); addChild(layer,0); //create Camera @@ -412,18 +412,18 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() _plane->setGLProgramState(_state); //pass mesh's attribute to shader - long offset = 0; + long offset = 0; auto attributeCount = _plane->getMesh()->getMeshVertexAttribCount(); for (auto i = 0; i < attributeCount; i++) { auto meshattribute = _plane->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - _plane->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + _plane->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; - } + } _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); //create shadow texture @@ -433,9 +433,9 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); + shadowTexture->setTexParameters(tRepeatParams); _state->setUniformTexture("u_shadowTexture",shadowTexture); - layer->addChild(_plane); + layer->addChild(_plane); //create the orc _orc = Sprite3D::create("Sprite3DTest/orc.c3b"); @@ -449,30 +449,30 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() layer->setCameraMask(2); schedule(CC_SCHEDULE_SELECTOR(Sprite3DFakeShadowTest::updateCamera), 0.0f); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); - glProgram->link(); - glProgram->updateUniforms(); - - _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); - - //create shadow texture - auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); - Texture2D::TexParams tRepeatParams;//set texture parameters - tRepeatParams.magFilter = GL_LINEAR; - tRepeatParams.minFilter = GL_LINEAR; - tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; - tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); - _state->setUniformTexture("u_shadowTexture",shadowTexture); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); + + //create shadow texture + auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); + Texture2D::TexParams tRepeatParams;//set texture parameters + tRepeatParams.magFilter = GL_LINEAR; + tRepeatParams.minFilter = GL_LINEAR; + tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; + tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; + shadowTexture->setTexParameters(tRepeatParams); + _state->setUniformTexture("u_shadowTexture",shadowTexture); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -484,12 +484,12 @@ Sprite3DFakeShadowTest::~Sprite3DFakeShadowTest() #endif } -std::string Sprite3DFakeShadowTest::title() const +std::string Sprite3DFakeShadowTest::title() const { return "fake shadow effect"; } -std::string Sprite3DFakeShadowTest::subtitle() const +std::string Sprite3DFakeShadowTest::subtitle() const { return "touch the screen to move around"; } @@ -594,18 +594,18 @@ bool Sprite3DFakeShadowTest::isState(unsigned int state,unsigned int bit) const return (state & bit) == bit; } -void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event* event) +void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event *event) { } -void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event* event) +void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event *event) { } -void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event* event) +void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event *event) { - for ( auto& item: touches ) + for ( auto &item: touches ) { auto touch = item; auto location = touch->getLocationInView(); @@ -653,43 +653,43 @@ Sprite3DBasicToonShaderTest::Sprite3DBasicToonShaderTest() auto _camera = Camera::createPerspective(60, visibleSize.width/visibleSize.height, 0.1f, 200); _camera->setCameraFlag(CameraFlag::USER1); // create a teapot - auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); - //create and set our custom shader + auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + //create and set our custom shader auto shader =GLProgram::createWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); _state = GLProgramState::create(shader); teapot->setGLProgramState(_state); teapot->setPosition3D(Vec3(0,-5,-20)); - teapot->setRotation3D(Vec3(-90,180,0)); + teapot->setRotation3D(Vec3(-90,180,0)); auto rotate_action = RotateBy::create(1.5,Vec3(0,30,0)); - teapot->runAction(RepeatForever::create(rotate_action)); + teapot->runAction(RepeatForever::create(rotate_action)); //pass mesh's attribute to shader long offset = 0; auto attributeCount = teapot->getMesh()->getMeshVertexAttribCount(); for (auto i = 0; i < attributeCount; i++) { auto meshattribute = teapot->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - teapot->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } addChild(teapot); addChild(_camera); setCameraMask(2); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -701,19 +701,19 @@ Sprite3DBasicToonShaderTest::~Sprite3DBasicToonShaderTest() #endif } -std::string Sprite3DBasicToonShaderTest::title() const +std::string Sprite3DBasicToonShaderTest::title() const { return "basic toon shader test"; } -std::string Sprite3DBasicToonShaderTest::subtitle() const +std::string Sprite3DBasicToonShaderTest::subtitle() const { return " "; } //------------------------------------------------------------------ // -// Sprite3DLightMapTest +// Sprite3DLightMapTest // //------------------------------------------------------------------ Sprite3DLightMapTest::Sprite3DLightMapTest() @@ -725,16 +725,16 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() _camera->setCameraFlag(CameraFlag::USER1); _camera->setPosition3D(Vec3(0,25,15)); _camera->setRotation3D(Vec3(-35,0,0)); - auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); - LightMapScene->setScale(0.1f); + auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); + LightMapScene->setScale(0.1f); addChild(LightMapScene); - addChild(_camera); - setCameraMask(2); + addChild(_camera); + setCameraMask(2); //add a point light auto light = PointLight::create(Vec3(35,75,-20.5),Color3B(255,255,255),150); addChild(light); - //set the ambient light + //set the ambient light auto ambient = AmbientLight::create(Color3B(55,55,55)); addChild(ambient); @@ -745,14 +745,14 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() } Sprite3DLightMapTest::~Sprite3DLightMapTest() { - + } std::string Sprite3DLightMapTest::title() const { return "light map test"; } -std::string Sprite3DLightMapTest::subtitle() const +std::string Sprite3DLightMapTest::subtitle() const { return "drag the screen to move around"; } @@ -776,9 +776,9 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to cameraRightDir.normalize(); cameraRightDir.y=0; Vec3 cameraPos= _camera->getPosition3D(); - cameraPos+=cameraDir*newPos.y*delta; + cameraPos+=cameraDir*newPos.y*delta; cameraPos+=cameraRightDir*newPos.x*delta; - _camera->setPosition3D(cameraPos); + _camera->setPosition3D(cameraPos); } } @@ -790,33 +790,33 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to Sprite3DHitTest::Sprite3DHitTest() { auto s = Director::getInstance()->getWinSize(); - + auto sprite1 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite1->setScale(4.f); sprite1->setTexture("Sprite3DTest/boss.png"); sprite1->setPosition( Vec2(s.width/2, s.height/2) ); - + //add to scene addChild( sprite1 ); sprite1->runAction(RepeatForever::create(RotateBy::create(3, 360))); - + auto sprite2 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite2->setScale(4.f); sprite2->setTexture("Sprite3DTest/boss.png"); sprite2->setPosition( Vec2(s.width/2, s.height/2) ); sprite2->setAnchorPoint(Vec2(0.5, 0.5)); - + //add to scene addChild( sprite2 ); sprite2->runAction(RepeatForever::create(RotateBy::create(3, -360))); - - + + // Make sprite1 touchable auto listener1 = EventListenerTouchOneByOne::create(); listener1->setSwallowTouches(true); - + listener1->onTouchBegan = [](Touch* touch, Event* event){ auto target = static_cast(event->getCurrentTarget()); @@ -840,10 +840,10 @@ Sprite3DHitTest::Sprite3DHitTest() log("sprite3d onTouchesEnded.. "); target->setOpacity(255); }; - + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2); - + } std::string Sprite3DHitTest::title() const @@ -860,21 +860,21 @@ void Sprite3DTestScene::runThisTest() { auto layer = nextSpriteTestAction(); addChild(layer); - + Director::getInstance()->replaceScene(this); } Sprite3DTestScene::Sprite3DTestScene() { - + } -static int tuple_sort( const std::tuple& tuple1, const std::tuple& tuple2 ) +static int tuple_sort( const std::tuple &tuple1, const std::tuple &tuple2 ) { return std::get<0>(tuple1) < std::get<0>(tuple2); } -EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath) +EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &objFilePath, const std::string &textureFilePath) { auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(objFilePath)) @@ -888,11 +888,11 @@ EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string& o return nullptr; } -EffectSprite3D* EffectSprite3D::create(const std::string& path) +EffectSprite3D* EffectSprite3D::create(const std::string &path) { if (path.length() < 4) CCASSERT(false, "improper name specified when creating Sprite3D"); - + auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(path)) { @@ -904,9 +904,9 @@ EffectSprite3D* EffectSprite3D::create(const std::string& path) } EffectSprite3D::EffectSprite3D() - : _defaultEffect(nullptr) +: _defaultEffect(nullptr) { - + } EffectSprite3D::~EffectSprite3D() @@ -918,7 +918,7 @@ EffectSprite3D::~EffectSprite3D() CC_SAFE_RELEASE(_defaultEffect); } -void EffectSprite3D::setEffect3D(Effect3D* effect) +void EffectSprite3D::setEffect3D(Effect3D *effect) { if(_defaultEffect == effect) return; CC_SAFE_RETAIN(effect); @@ -931,7 +931,7 @@ void EffectSprite3D::addEffect(Effect3DOutline* effect, ssize_t order) if(nullptr == effect) return; effect->retain(); effect->setTarget(this); - + _effects.push_back(std::make_tuple(order,effect,CustomCommand())); std::sort(std::begin(_effects), std::end(_effects), tuple_sort); @@ -986,26 +986,26 @@ Effect3DOutline* Effect3DOutline::create() bool Effect3DOutline::init() { - + return true; } Effect3DOutline::Effect3DOutline() - : _outlineWidth(1.0f) - , _outlineColor(1, 1, 1) - , _sprite(nullptr) +: _outlineWidth(1.0f) +, _outlineColor(1, 1, 1) +, _sprite(nullptr) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _glProgramState->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _glProgramState->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -1037,10 +1037,10 @@ void Effect3DOutline::setOutlineWidth(float width) } } -void Effect3DOutline::setTarget(EffectSprite3D* sprite) +void Effect3DOutline::setTarget(EffectSprite3D *sprite) { CCASSERT(nullptr != sprite && nullptr != sprite->getMesh(),"Error: Setting a null pointer or a null mesh EffectSprite3D to Effect3D"); - + if(sprite != _sprite) { GLProgram* glprogram; @@ -1054,16 +1054,16 @@ void Effect3DOutline::setTarget(EffectSprite3D* sprite) _glProgramState->retain(); _glProgramState->setUniformVec3("OutLineColor", _outlineColor); _glProgramState->setUniformFloat("OutlineWidth", _outlineWidth); - - + + _sprite = sprite; - + auto mesh = sprite->getMesh(); long offset = 0; for (auto i = 0; i < mesh->getMeshVertexAttribCount(); i++) { auto meshvertexattrib = mesh->getMeshVertexAttribute(i); - + _glProgramState->setVertexAttribPointer(s_attributeNames[meshvertexattrib.vertexAttrib], meshvertexattrib.size, meshvertexattrib.type, @@ -1072,12 +1072,12 @@ void Effect3DOutline::setTarget(EffectSprite3D* sprite) (void*)offset); offset += meshvertexattrib.attribSizeBytes; } - + Color4F color(_sprite->getDisplayedColor()); color.a = _sprite->getDisplayedOpacity() / 255.0f; _glProgramState->setUniformVec4("u_color", Vec4(color.r, color.g, color.b, color.a)); } - + } static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int paletteSize, const float* palette) @@ -1085,7 +1085,7 @@ static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int p glUniform4fv( uniform->location, (GLsizei)paletteSize, (const float*)palette ); } -void Effect3DOutline::draw(const Mat4& transform) +void Effect3DOutline::draw(const Mat4 &transform) { //draw Color4F color(_sprite->getDisplayedColor()); @@ -1096,10 +1096,10 @@ void Effect3DOutline::draw(const Mat4& transform) glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glEnable(GL_DEPTH_TEST); - + auto mesh = _sprite->getMesh(); glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer()); - + auto skin = _sprite->getMesh()->getSkin(); if(_sprite && skin) { @@ -1107,14 +1107,14 @@ void Effect3DOutline::draw(const Mat4& transform) skin->getMatrixPaletteSize(), (float*)skin->getMatrixPalette()); _glProgramState->setUniformCallback("u_matrixPalette", function); } - + if(_sprite) _glProgramState->apply(transform); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getIndexBuffer()); glDrawElements(mesh->getPrimitiveType(), (GLsizei)mesh->getIndexCount(), mesh->getIndexFormat(), 0); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, mesh->getIndexCount()); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_DEPTH_TEST); @@ -1123,18 +1123,18 @@ void Effect3DOutline::draw(const Mat4& transform) } } -void EffectSprite3D::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) +void EffectSprite3D::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) { - for(auto& effect : _effects) + for(auto &effect : _effects) { if(std::get<0>(effect) >=0) break; - CustomCommand& cc = std::get<2>(effect); + CustomCommand &cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } - + if(!_defaultEffect) { Sprite3D::draw(renderer, transform, flags); @@ -1145,15 +1145,15 @@ void EffectSprite3D::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& tran _command.func = CC_CALLBACK_0(Effect3D::draw, _defaultEffect, transform); renderer->addCommand(&_command); } - - for(auto& effect : _effects) + + for(auto &effect : _effects) { if(std::get<0>(effect) <=0) continue; - CustomCommand& cc = std::get<2>(effect); + CustomCommand &cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } } @@ -1161,7 +1161,7 @@ Sprite3DEffectTest::Sprite3DEffectTest() { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DEffectTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1184,22 +1184,22 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) sprite->addEffect(effect, -1); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); - + Effect3DOutline* effect2 = Effect3DOutline::create(); sprite->addEffect(effect2, -2); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); //sprite->setEffect3D(effect); sprite->setScale(6.f); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -1212,7 +1212,7 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -1221,7 +1221,7 @@ void Sprite3DEffectTest::onTouchesEnded(const std::vector& touches, Even for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1233,22 +1233,22 @@ AsyncLoadSprite3DTest::AsyncLoadSprite3DTest() _paths.push_back("Sprite3DTest/orc.c3b"); _paths.push_back("Sprite3DTest/ReskinGirl.c3b"); _paths.push_back("Sprite3DTest/axe.c3b"); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"AsyncLoad Sprite3D"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite,this) ); - + auto s = Director::getInstance()->getWinSize(); item1->setPosition( s.width * .5f, s.height * .8f); - + auto pMenu1 = CCMenu::create(item1, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + auto node = Node::create(); node->setTag(101); this->addChild(node); - + menuCallback_asyncLoadSprite(nullptr); } @@ -1269,10 +1269,10 @@ void AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite(Ref* sender) { //Note that you must stop the tasks before leaving the scene. AsyncTaskPool::getInstance()->stopTasks(AsyncTaskPool::TaskType::TASK_IO); - + auto node = getChildByTag(101); node->removeAllChildren(); //remove all loaded sprite - + //remove cache data Sprite3DCache::getInstance()->removeAllSprite3DData(); long index = 0; @@ -1298,7 +1298,7 @@ Sprite3DWithSkinTest::Sprite3DWithSkinTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1347,7 +1347,7 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector& touches, Ev for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1357,7 +1357,7 @@ Sprite3DWithSkinOutlineTest::Sprite3DWithSkinOutlineTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinOutlineTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1372,33 +1372,33 @@ std::string Sprite3DWithSkinOutlineTest::subtitle() const void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) { - + std::string fileName = "Sprite3DTest/orc.c3b"; auto sprite = EffectSprite3D::create(fileName); - + Effect3DOutline* effect = Effect3DOutline::create(); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); sprite->addEffect(effect, -1); - + Effect3DOutline* effect2 = Effect3DOutline::create(); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); sprite->addEffect(effect2, -2); - + sprite->setScale(3); sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); bool inverse = (std::rand() % 3 == 0); - + int rand2 = std::rand(); float speed = 1.0f; if(rand2 % 3 == 1) @@ -1410,7 +1410,7 @@ void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) speed = animate->getSpeed() - 0.5 * CCRANDOM_0_1(); } animate->setSpeed(inverse ? -speed : speed); - + sprite->runAction(RepeatForever::create(animate)); } } @@ -1420,24 +1420,24 @@ void Sprite3DWithSkinOutlineTest::onTouchesEnded(const std::vector& touc for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } Animate3DTest::Animate3DTest() - : _hurt(nullptr) - , _swim(nullptr) - , _sprite(nullptr) - , _moveAction(nullptr) - , _elapseTransTime(0.f) +: _hurt(nullptr) +, _swim(nullptr) +, _sprite(nullptr) +, _moveAction(nullptr) +, _elapseTransTime(0.f) { addSprite3D(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Animate3DTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + scheduleUpdate(); } @@ -1463,7 +1463,7 @@ void Animate3DTest::update(float dt) if (_state == State::HURT_TO_SWIMMING) { _elapseTransTime += dt; - + if (_elapseTransTime >= Animate3D::getTransitionTime()) { _sprite->stopAction(_hurt); @@ -1496,13 +1496,13 @@ void Animate3DTest::addSprite3D() auto animate = Animate3D::create(animation, 0.f, 1.933f); _swim = RepeatForever::create(animate); sprite->runAction(_swim); - + _swim->retain(); _hurt = Animate3D::create(animation, 1.933f, 2.8f); _hurt->retain(); _state = State::SWIMMING; } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr); @@ -1536,7 +1536,7 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev for (auto touch: touches) { auto location = touch->getLocation(); - + if (_sprite) { float len = (_sprite->getPosition() - location).length(); @@ -1561,12 +1561,12 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev } AttachmentTest::AttachmentTest() - : _hasWeapon(false) - , _sprite(nullptr) +: _hasWeapon(false) +, _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(AttachmentTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1588,16 +1588,16 @@ void AttachmentTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; @@ -1618,11 +1618,11 @@ void AttachmentTest::onTouchesEnded(const std::vector& touches, Event* e _hasWeapon = !_hasWeapon; } Sprite3DReskinTest::Sprite3DReskinTest() - : _sprite(nullptr) +: _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DReskinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1630,11 +1630,11 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto label1 = Label::createWithTTF(ttfConfig,"Hair"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Glasses"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label3 = Label::createWithTTF(ttfConfig,"Coat"); auto item3 = MenuItemLabel::create(label3,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label4 = Label::createWithTTF(ttfConfig,"Pants"); - auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label5 = Label::createWithTTF(ttfConfig,"Shoes"); auto item5 = MenuItemLabel::create(label5,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); item1->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*4 ) ); @@ -1650,7 +1650,7 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto pMenu1 = CCMenu::create(item1, item2, item3, item4, item5, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + } void Sprite3DReskinTest::menuCallback_reSkin(Ref* sender) { @@ -1683,41 +1683,41 @@ void Sprite3DReskinTest::addNewSpriteWithCoords(Vec2 p) if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; - + auto& body = _skins[(int)SkinType::UPPER_BODY]; body.push_back("Girl_UpperBody01"); body.push_back("Girl_UpperBody02"); - + auto& pants = _skins[(int)SkinType::PANTS]; pants.push_back("Girl_LowerBody01"); pants.push_back("Girl_LowerBody02"); - + auto& shoes = _skins[(int)SkinType::SHOES]; shoes.push_back("Girl_Shoes01"); shoes.push_back("Girl_Shoes02"); - + auto& hair = _skins[(int)SkinType::HAIR]; hair.push_back("Girl_Hair01"); hair.push_back("Girl_Hair02"); - + auto& face = _skins[(int)SkinType::FACE]; face.push_back("Girl_Face01"); face.push_back("Girl_Face02"); - + auto& hand = _skins[(int)SkinType::HAND]; hand.push_back("Girl_Hand01"); hand.push_back("Girl_Hand02"); - + auto& glasses = _skins[(int)SkinType::GLASSES]; glasses.push_back(""); glasses.push_back("Girl_Glasses01"); - + memset(_curSkin, 0, (int)SkinType::MAX_TYPE * sizeof(int)); - + applyCurSkin(); } @@ -1750,7 +1750,7 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto s = Director::getInstance()->getWinSize(); initDrawBox(); - + addNewSpriteWithCoords(Vec2(s.width/2, s.height/2)); MenuItemFont::setFontName("fonts/arial.ttf"); MenuItemFont::setFontSize(65); @@ -1758,12 +1758,12 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() decrease->setColor(Color3B(0,200,20)); auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(Sprite3DWithOBBPerformanceTest::addOBBCallback, this)); increase->setColor(Color3B(0,200,20)); - + auto menu = Menu::create(decrease, increase, nullptr); menu->alignItemsHorizontally(); menu->setPosition(Vec2(s.width/2, s.height-65)); addChild(menu, 1); - + TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); _labelCubeCount = Label::createWithTTF(ttfCount,"0 cubes"); _labelCubeCount->setColor(Color3B(0,200,20)); @@ -1815,14 +1815,14 @@ void Sprite3DWithOBBPerformanceTest::onTouchesBegan(const std::vector& t void Sprite3DWithOBBPerformanceTest::onTouchesEnded(const std::vector& touches, Event* event) { - + } void Sprite3DWithOBBPerformanceTest::onTouchesMoved(const std::vector& touches, Event* event) { for (const auto& touch: touches) { - auto location = touch->getLocation(); + auto location = touch->getLocation(); auto obbSize = _obb.size(); for(decltype(obbSize) i = 0; i < obbSize; i++) @@ -1838,23 +1838,23 @@ void Sprite3DWithOBBPerformanceTest::update(float dt) char szText[16]; sprintf(szText,"%lu cubes",_obb.size()); _labelCubeCount->setString(szText); - + if (_drawDebug) { _drawDebug->clear(); - + Mat4 mat = _sprite->getNodeToWorldTransform(); mat.getRightVector(&_obbt._xAxis); _obbt._xAxis.normalize(); - + mat.getUpVector(&_obbt._yAxis); _obbt._yAxis.normalize(); - + mat.getForwardVector(&_obbt._zAxis); _obbt._zAxis.normalize(); - + _obbt._center = _sprite->getPosition3D(); - + Vec3 corners[8] = {}; _obbt.getCorners(corners); _drawDebug->drawCube(corners, Color4F(0,0,1,1)); @@ -1893,16 +1893,16 @@ void Sprite3DWithOBBPerformanceTest::addNewSpriteWithCoords(Vec2 p) auto animate = Animate3D::create(animation, 0.f, 1.933f); sprite->runAction(RepeatForever::create(animate)); } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Sprite3DWithOBBPerformanceTest::reachEndCallBack, this)), nullptr); seq->setTag(100); sprite->runAction(seq); - + AABB aabb = _sprite->getAABB(); _obbt = OBB(aabb); - + _drawDebug = DrawNode3D::create(); addChild(_drawDebug); } @@ -1956,23 +1956,23 @@ void Sprite3DWithOBBPerformanceTest::delOBBWithCount(float value) void Sprite3DWithOBBPerformanceTest::unproject(const Mat4& viewProjection, const Size* viewport, Vec3* src, Vec3* dst) { assert(dst); - + assert(viewport->width != 0.0f && viewport->height != 0.0f); Vec4 screen(src->x / viewport->width, ((viewport->height - src->y)) / viewport->height, src->z, 1.0f); - + screen.x = screen.x * 2.0f - 1.0f; screen.y = screen.y * 2.0f - 1.0f; screen.z = screen.z * 2.0f - 1.0f; - + viewProjection.getInversed().transformVector(screen, &screen); - + if (screen.w != 0.0f) { screen.x /= screen.w; screen.y /= screen.w; screen.z /= screen.w; } - + dst->set(screen.x, screen.y, screen.z); } @@ -1981,26 +1981,26 @@ void Sprite3DWithOBBPerformanceTest::calculateRayByLocationInView(Ray* ray, cons auto dir = Director::getInstance(); auto view = dir->getWinSize(); auto mat = dir->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - + Vec3 src = Vec3(location.x, location.y, -1); Vec3 nearPoint; unproject(mat, &view, &src, &nearPoint); - + src = Vec3(location.x, location.y, 1); Vec3 farPoint; unproject(mat, &view, &src, &farPoint); - + Vec3 direction; Vec3::subtract(farPoint, nearPoint, &direction); direction.normalize(); - + ray->_origin = nearPoint; ray->_direction = direction; } Sprite3DMirrorTest::Sprite3DMirrorTest() - : _sprite(nullptr) - , _mirrorSprite(nullptr) +: _sprite(nullptr) +, _mirrorSprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); @@ -2022,21 +2022,21 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x - 80, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; _hasWeapon = true; - + //create mirror Sprite3D sprite = Sprite3D::create(fileName); sprite->setScale(5); @@ -2045,25 +2045,25 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x + 80, p.y) ); - + //test attach sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _mirrorSprite = sprite; } QuaternionTest::QuaternionTest() - : _arcSpeed(CC_DEGREES_TO_RADIANS(90)) - , _radius(100.f) - , _accAngle(0.f) +: _arcSpeed(CC_DEGREES_TO_RADIANS(90)) +, _radius(100.f) +, _accAngle(0.f) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords(Vec2(s.width / 2.f, s.height / 2.f)); @@ -2101,20 +2101,20 @@ void QuaternionTest::update(float delta) const float pi = M_PI; if (_accAngle >= 2 * pi) _accAngle -= 2 * pi; - + auto s = Director::getInstance()->getWinSize(); _sprite->setPosition(Vec2(s.width / 2.f + _radius * cosf(_accAngle), s.height / 2.f + _radius * sinf(_accAngle))); - + Quaternion quat; Quaternion::createFromAxisAngle(Vec3(0.f, 0.f, 1.f), _accAngle - pi * 0.5f, &quat); _sprite->setRotationQuat(quat); } UseCaseSprite3D::UseCaseSprite3D() - : _caseIdx(0) +: _caseIdx(0) { auto s = Director::getInstance()->getWinSize(); - + _useCaseTitles[0] = "transparent 3d sprite and 2d sprite"; _useCaseTitles[1] = "ui - 3d - ui"; @@ -2131,28 +2131,28 @@ UseCaseSprite3D::UseCaseSprite3D() _caseIdx++; if (_caseIdx >= (int)USECASE::MAX_CASE_NUM) _caseIdx = 0; - this->switchCase(); - }); - + this->switchCase(); + }); + auto menu = Menu::create(itemPrev, itemNext, nullptr); menu->alignItemsHorizontally(); menu->setScale(0.5); menu->setAnchorPoint(Vec2(0,0)); menu->setPosition(Vec2(s.width/2,70)); - + _label = Label::create(); _label->setPosition(s.width * 0.5f, s.height * 0.8f); addChild(_label); - + addChild(menu); - + //setup camera auto camera = Camera::createPerspective(40, s.width / s.height, 0.01f, 1000.f); camera->setCameraFlag(CameraFlag::USER1); camera->setPosition3D(Vec3(0.f, 30.f, 100.f)); camera->lookAt(Vec3(0.f, 0.f, 0.f)); addChild(camera); - + switchCase(); } @@ -2169,7 +2169,7 @@ std::string UseCaseSprite3D::subtitle() const void UseCaseSprite3D::switchCase() { removeChildByTag(101); - + auto s = Director::getInstance()->getWinSize(); _label->setString(_useCaseTitles[_caseIdx]); if (_caseIdx == 0) // use case 1, 3d transparent sprite + 2d sprite @@ -2181,33 +2181,33 @@ void UseCaseSprite3D::switchCase() if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } - + auto circleBack = Sprite3D::create(); auto circle = Sprite::create("Sprite3DTest/circle.png"); circleBack->setScale(0.5f); circleBack->addChild(circle); circle->runAction(RepeatForever::create(RotateBy::create(3, Vec3(0.f, 0.f, 360.f)))); - + circleBack->setRotation3D(Vec3(90, 0, 0)); - + auto pos = sprite->getPosition3D(); circleBack->setPosition3D(Vec3(pos.x, pos.y, pos.z - 1)); - + sprite->setOpacity(250); sprite->setCameraMask(2); circleBack->setCameraMask(2); sprite->setTag(3); circleBack->setTag(2); - + auto node = Node::create(); node->addChild(sprite); node->addChild(circleBack); node->setTag(101); addChild(node); - + scheduleUpdate(); update(0.f); } @@ -2217,7 +2217,7 @@ void UseCaseSprite3D::switchCase() layer->setPosition(s.width * 0.25f, s.height * 0.25f); layer->setGlobalZOrder(-1); addChild(layer); - + std::string filename = "Sprite3DTest/girl.c3b"; auto sprite = Sprite3D::create(filename); sprite->setScale(0.5f); @@ -2229,20 +2229,20 @@ void UseCaseSprite3D::switchCase() } sprite->setPosition(s.width * 0.25f, s.height * 0.125f); layer->addChild(sprite); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"Message"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Message"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); - + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); + item1->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height ) ); item2->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height * 2.f ) ); - + auto pMenu1 = CCMenu::create(item1, item2, nullptr); pMenu1->setPosition(Vec2(0,0)); layer->addChild(pMenu1); - + layer->setTag(101); } } @@ -2275,14 +2275,14 @@ void UseCaseSprite3D::update(float delta) { static float accAngle = 0.f; accAngle += delta * CC_DEGREES_TO_RADIANS(60); - + float radius = 30.f; float x = cosf(accAngle) * radius, z = sinf(accAngle) * radius; - + auto node = getChildByTag(101); auto sprite3d = node->getChildByTag(3); auto circle = node->getChildByTag(2); - + sprite3d->setPositionX(x); sprite3d->setPositionZ(z); circle->setPositionX(x); From 54472497a4690bbf97b0ed07f646a65d526c5c68 Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Wed, 25 Mar 2015 13:43:55 +0800 Subject: [PATCH 12/27] fix comments --- cocos/3d/CCSkybox.cpp | 56 ++++++++-------- .../Classes/Sprite3DTest/Sprite3DTest.cpp | 66 +++++++++---------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index d871a971e5..11f1b85ba5 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -1,25 +1,25 @@ /**************************************************************************** - Copyright (c) 2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ #include "CCSkybox.h" @@ -88,13 +88,13 @@ void Skybox::initBuffers() glBufferData(GL_ARRAY_BUFFER, sizeof(vexBuf), vexBuf, GL_STATIC_DRAW); // init index buffer object - unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, // font - 1, 5, 4, 1, 4, 0, // right - 4, 5, 6, 4, 6, 7, // back - 7, 6, 2, 7, 2, 3, // left - 2, 6, 5, 2, 5, 1, // up - 3, 0, 4, 3, 4, 7 // down - }; + const unsigned char idxBuf[] = { 2, 1, 0, 3, 2, 0, // font + 1, 5, 4, 1, 4, 0, // right + 4, 5, 6, 4, 6, 7, // back + 7, 6, 2, 7, 2, 3, // left + 2, 6, 5, 2, 5, 1, // up + 3, 0, 4, 3, 4, 7 // down + }; glGenBuffers(1, &_indexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 2aa3c7a972..3ac91f2251 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -1,27 +1,26 @@ /**************************************************************************** - Copyright (c) 2012 cocos2d-x.org - Copyright (c) 2013-2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ +Copyright (c) 2014 Chukong Technologies Inc. + +http://www.cocos2d-x.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ #include "Sprite3DTest.h" #include "base/CCAsyncTaskPool.h" @@ -1630,11 +1629,11 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto label1 = Label::createWithTTF(ttfConfig,"Hair"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Glasses"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label3 = Label::createWithTTF(ttfConfig,"Coat"); auto item3 = MenuItemLabel::create(label3,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label4 = Label::createWithTTF(ttfConfig,"Pants"); - auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label5 = Label::createWithTTF(ttfConfig,"Shoes"); auto item5 = MenuItemLabel::create(label5,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); item1->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*4 ) ); @@ -2234,7 +2233,7 @@ void UseCaseSprite3D::switchCase() auto label1 = Label::createWithTTF(ttfConfig,"Message"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Message"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); item1->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height ) ); item2->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height * 2.f ) ); @@ -2336,8 +2335,8 @@ void Sprite3DCubeMapTest::addNewSpriteWithCoords(Vec2 p) // create the second texture for cylinder _textureCube = TextureCube::create("Sprite3DTest/skybox/left.jpg", "Sprite3DTest/skybox/right.jpg", - "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", - "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); + "Sprite3DTest/skybox/top.jpg", "Sprite3DTest/skybox/bottom.jpg", + "Sprite3DTest/skybox/front.jpg", "Sprite3DTest/skybox/back.jpg"); _textureCube->retain(); @@ -2366,11 +2365,12 @@ void Sprite3DCubeMapTest::addNewSpriteWithCoords(Vec2 p) { auto meshattribute = _teapot->getMesh()->getMeshVertexAttribute(i); state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - _teapot->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + _teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); + offset += meshattribute.attribSizeBytes; } addChild(_teapot); From c1e5e47bdb2a296a19ac19c02c5aa634bd03baab Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Wed, 25 Mar 2015 13:46:30 +0800 Subject: [PATCH 13/27] fix code style issue --- .../Classes/Sprite3DTest/Sprite3DTest.h | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 8e1cbf20f3..5b852bc4e1 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -1,26 +1,26 @@ /**************************************************************************** - Copyright (c) 2013 cocos2d-x.org +Copyright (c) 2014 Chukong Technologies Inc. - http://www.cocos2d-x.org +http://www.cocos2d-x.org - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ #ifndef _SPRITE3D_TEST_H_ #define _SPRITE3D_TEST_H_ From aead9e5855bd2f4ea0aeb36577b326245d8942fc Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Thu, 26 Mar 2015 09:53:41 +0800 Subject: [PATCH 14/27] correct for code indent --- cocos/3d/CCSkybox.cpp | 42 +- .../Classes/Sprite3DTest/Sprite3DTest.cpp | 660 +++++++++--------- .../Classes/Sprite3DTest/Sprite3DTest.h | 184 ++--- 3 files changed, 449 insertions(+), 437 deletions(-) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index 11f1b85ba5..baab531046 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -1,25 +1,25 @@ /**************************************************************************** - Copyright (c) 2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ #include "CCSkybox.h" diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 3ac91f2251..97037e3dd1 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -1,26 +1,27 @@ /**************************************************************************** -Copyright (c) 2014 Chukong Technologies Inc. + Copyright (c) 2012 cocos2d-x.org + Copyright (c) 2013-2014 Chukong Technologies Inc. -http://www.cocos2d-x.org + http://www.cocos2d-x.org -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ #include "Sprite3DTest.h" #include "base/CCAsyncTaskPool.h" @@ -53,7 +54,7 @@ static std::function createFunctions[] = CL(Sprite3DHitTest), CL(AsyncLoadSprite3DTest), #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) - // 3DEffect use custom shader which is not supported on WP8/WinRT yet. + // 3DEffect use custom shader which is not supported on WP8/WinRT yet. CL(Sprite3DEffectTest), CL(Sprite3DUVAnimationTest), CL(Sprite3DFakeShadowTest), @@ -81,7 +82,7 @@ static Layer* nextSpriteTestAction() { sceneIdx++; sceneIdx = sceneIdx % MAX_LAYER; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -92,7 +93,7 @@ static Layer* backSpriteTestAction() int total = MAX_LAYER; if( sceneIdx < 0 ) sceneIdx += total; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -110,7 +111,7 @@ static Layer* restartSpriteTestAction() //------------------------------------------------------------------ Sprite3DTestDemo::Sprite3DTestDemo(void) -: BaseTest() + : BaseTest() { } @@ -137,7 +138,7 @@ void Sprite3DTestDemo::restartCallback(Ref* sender) { auto s = new (std::nothrow) Sprite3DTestScene(); s->addChild(restartSpriteTestAction()); - + Director::getInstance()->replaceScene(s); s->release(); } @@ -194,7 +195,7 @@ Sprite3DBasicTest::Sprite3DBasicTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DBasicTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -204,26 +205,26 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) //int idx = (int)(CCRANDOM_0_1() * 1400.0f / 100.0f); //int x = (idx%5) * 85; //int y = (idx/5) * 121; - -// //option 1: load a obj that contain the texture in it -// auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); - + + // //option 1: load a obj that contain the texture in it + // auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); + //option 2: load obj and assign the texture auto sprite = Sprite3D::create("Sprite3DTest/boss1.obj"); sprite->setScale(3.f); sprite->setTexture("Sprite3DTest/boss.png"); - + // //sprite->setEffect(cocos2d::EFFECT_OUTLINE); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -236,7 +237,7 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -245,7 +246,7 @@ void Sprite3DBasicTest::onTouchesEnded(const std::vector& touches, Event for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -290,14 +291,15 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() //pass mesh's attribute to shader long offset = 0; auto attributeCount = cylinder->getMesh()->getMeshVertexAttribCount(); - for (auto i = 0; i < attributeCount; i++) { + for (auto i = 0; i < attributeCount; i++) + { auto meshattribute = cylinder->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - cylinder->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + cylinder->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } @@ -308,13 +310,13 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() tRepeatParams.minFilter = GL_NEAREST; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; - shining_texture->setTexParameters(tRepeatParams); + shining_texture->setTexParameters(tRepeatParams); //pass the texture sampler to our custom shader _state->setUniformTexture("caustics",shining_texture); this->addChild(cylinder); - this->setCameraMask(2); + this->setCameraMask(2); this->addChild(camera); //adjust cylinder's position & rotation @@ -323,18 +325,18 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() //the callback function update cylinder's texcoord schedule(schedule_selector(Sprite3DUVAnimationTest::cylinderUpdate)); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -346,12 +348,12 @@ Sprite3DUVAnimationTest::~Sprite3DUVAnimationTest() #endif } -std::string Sprite3DUVAnimationTest::title() const +std::string Sprite3DUVAnimationTest::title() const { return "Testing UV Animation"; } -std::string Sprite3DUVAnimationTest::subtitle() const +std::string Sprite3DUVAnimationTest::subtitle() const { return ""; } @@ -386,13 +388,13 @@ void Sprite3DUVAnimationTest::cylinderUpdate(float dt) Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() { Size visibleSize = Director::getInstance()->getVisibleSize(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesBegan, this); listener->onTouchesMoved = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesMoved, this); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto layer = Layer::create(); addChild(layer,0); //create Camera @@ -411,18 +413,19 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() _plane->setGLProgramState(_state); //pass mesh's attribute to shader - long offset = 0; + long offset = 0; auto attributeCount = _plane->getMesh()->getMeshVertexAttribCount(); - for (auto i = 0; i < attributeCount; i++) { + for (auto i = 0; i < attributeCount; i++) + { auto meshattribute = _plane->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - _plane->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + _plane->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; - } + } _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); //create shadow texture @@ -432,9 +435,9 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); + shadowTexture->setTexParameters(tRepeatParams); _state->setUniformTexture("u_shadowTexture",shadowTexture); - layer->addChild(_plane); + layer->addChild(_plane); //create the orc _orc = Sprite3D::create("Sprite3DTest/orc.c3b"); @@ -448,30 +451,30 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() layer->setCameraMask(2); schedule(CC_SCHEDULE_SELECTOR(Sprite3DFakeShadowTest::updateCamera), 0.0f); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); - glProgram->link(); - glProgram->updateUniforms(); - - _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); - - //create shadow texture - auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); - Texture2D::TexParams tRepeatParams;//set texture parameters - tRepeatParams.magFilter = GL_LINEAR; - tRepeatParams.minFilter = GL_LINEAR; - tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; - tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); - _state->setUniformTexture("u_shadowTexture",shadowTexture); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); + + //create shadow texture + auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); + Texture2D::TexParams tRepeatParams;//set texture parameters + tRepeatParams.magFilter = GL_LINEAR; + tRepeatParams.minFilter = GL_LINEAR; + tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; + tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; + shadowTexture->setTexParameters(tRepeatParams); + _state->setUniformTexture("u_shadowTexture",shadowTexture); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -483,12 +486,12 @@ Sprite3DFakeShadowTest::~Sprite3DFakeShadowTest() #endif } -std::string Sprite3DFakeShadowTest::title() const +std::string Sprite3DFakeShadowTest::title() const { return "fake shadow effect"; } -std::string Sprite3DFakeShadowTest::subtitle() const +std::string Sprite3DFakeShadowTest::subtitle() const { return "touch the screen to move around"; } @@ -593,18 +596,18 @@ bool Sprite3DFakeShadowTest::isState(unsigned int state,unsigned int bit) const return (state & bit) == bit; } -void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event *event) +void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event* event) { } -void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event *event) +void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event* event) { } -void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event *event) +void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event* event) { - for ( auto &item: touches ) + for ( auto& item: touches ) { auto touch = item; auto location = touch->getLocationInView(); @@ -652,43 +655,44 @@ Sprite3DBasicToonShaderTest::Sprite3DBasicToonShaderTest() auto _camera = Camera::createPerspective(60, visibleSize.width/visibleSize.height, 0.1f, 200); _camera->setCameraFlag(CameraFlag::USER1); // create a teapot - auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); - //create and set our custom shader + auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + //create and set our custom shader auto shader =GLProgram::createWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); _state = GLProgramState::create(shader); teapot->setGLProgramState(_state); teapot->setPosition3D(Vec3(0,-5,-20)); - teapot->setRotation3D(Vec3(-90,180,0)); + teapot->setRotation3D(Vec3(-90,180,0)); auto rotate_action = RotateBy::create(1.5,Vec3(0,30,0)); - teapot->runAction(RepeatForever::create(rotate_action)); + teapot->runAction(RepeatForever::create(rotate_action)); //pass mesh's attribute to shader long offset = 0; auto attributeCount = teapot->getMesh()->getMeshVertexAttribCount(); - for (auto i = 0; i < attributeCount; i++) { + for (auto i = 0; i < attributeCount; i++) + { auto meshattribute = teapot->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - teapot->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } addChild(teapot); addChild(_camera); setCameraMask(2); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -700,19 +704,19 @@ Sprite3DBasicToonShaderTest::~Sprite3DBasicToonShaderTest() #endif } -std::string Sprite3DBasicToonShaderTest::title() const +std::string Sprite3DBasicToonShaderTest::title() const { return "basic toon shader test"; } -std::string Sprite3DBasicToonShaderTest::subtitle() const +std::string Sprite3DBasicToonShaderTest::subtitle() const { return " "; } //------------------------------------------------------------------ // -// Sprite3DLightMapTest +// Sprite3DLightMapTest // //------------------------------------------------------------------ Sprite3DLightMapTest::Sprite3DLightMapTest() @@ -724,16 +728,16 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() _camera->setCameraFlag(CameraFlag::USER1); _camera->setPosition3D(Vec3(0,25,15)); _camera->setRotation3D(Vec3(-35,0,0)); - auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); - LightMapScene->setScale(0.1f); + auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); + LightMapScene->setScale(0.1f); addChild(LightMapScene); - addChild(_camera); - setCameraMask(2); + addChild(_camera); + setCameraMask(2); //add a point light auto light = PointLight::create(Vec3(35,75,-20.5),Color3B(255,255,255),150); addChild(light); - //set the ambient light + //set the ambient light auto ambient = AmbientLight::create(Color3B(55,55,55)); addChild(ambient); @@ -744,14 +748,14 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() } Sprite3DLightMapTest::~Sprite3DLightMapTest() { - + } std::string Sprite3DLightMapTest::title() const { return "light map test"; } -std::string Sprite3DLightMapTest::subtitle() const +std::string Sprite3DLightMapTest::subtitle() const { return "drag the screen to move around"; } @@ -775,9 +779,9 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to cameraRightDir.normalize(); cameraRightDir.y=0; Vec3 cameraPos= _camera->getPosition3D(); - cameraPos+=cameraDir*newPos.y*delta; + cameraPos+=cameraDir*newPos.y*delta; cameraPos+=cameraRightDir*newPos.x*delta; - _camera->setPosition3D(cameraPos); + _camera->setPosition3D(cameraPos); } } @@ -789,37 +793,38 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to Sprite3DHitTest::Sprite3DHitTest() { auto s = Director::getInstance()->getWinSize(); - + auto sprite1 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite1->setScale(4.f); sprite1->setTexture("Sprite3DTest/boss.png"); sprite1->setPosition( Vec2(s.width/2, s.height/2) ); - + //add to scene addChild( sprite1 ); sprite1->runAction(RepeatForever::create(RotateBy::create(3, 360))); - + auto sprite2 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite2->setScale(4.f); sprite2->setTexture("Sprite3DTest/boss.png"); sprite2->setPosition( Vec2(s.width/2, s.height/2) ); sprite2->setAnchorPoint(Vec2(0.5, 0.5)); - + //add to scene addChild( sprite2 ); sprite2->runAction(RepeatForever::create(RotateBy::create(3, -360))); - - + + // Make sprite1 touchable auto listener1 = EventListenerTouchOneByOne::create(); listener1->setSwallowTouches(true); - - listener1->onTouchBegan = [](Touch* touch, Event* event){ + + listener1->onTouchBegan = [](Touch* touch, Event* event) + { auto target = static_cast(event->getCurrentTarget()); - - Rect rect = target->getBoundingBox(); + + Rect rect = target->getBoundingBox(); if (rect.containsPoint(touch->getLocation())) { log("sprite3d began... x = %f, y = %f", touch->getLocation().x, touch->getLocation().y); @@ -828,21 +833,23 @@ Sprite3DHitTest::Sprite3DHitTest() } return false; }; - - listener1->onTouchMoved = [](Touch* touch, Event* event){ + + listener1->onTouchMoved = [](Touch* touch, Event* event) + { auto target = static_cast(event->getCurrentTarget()); target->setPosition(target->getPosition() + touch->getDelta()); }; - - listener1->onTouchEnded = [=](Touch* touch, Event* event){ + + listener1->onTouchEnded = [=](Touch* touch, Event* event) + { auto target = static_cast(event->getCurrentTarget()); log("sprite3d onTouchesEnded.. "); target->setOpacity(255); }; - + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2); - + } std::string Sprite3DHitTest::title() const @@ -859,21 +866,21 @@ void Sprite3DTestScene::runThisTest() { auto layer = nextSpriteTestAction(); addChild(layer); - + Director::getInstance()->replaceScene(this); } Sprite3DTestScene::Sprite3DTestScene() { - + } -static int tuple_sort( const std::tuple &tuple1, const std::tuple &tuple2 ) +static int tuple_sort( const std::tuple& tuple1, const std::tuple& tuple2 ) { return std::get<0>(tuple1) < std::get<0>(tuple2); } -EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &objFilePath, const std::string &textureFilePath) +EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath) { auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(objFilePath)) @@ -887,11 +894,11 @@ EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &o return nullptr; } -EffectSprite3D* EffectSprite3D::create(const std::string &path) +EffectSprite3D* EffectSprite3D::create(const std::string& path) { if (path.length() < 4) CCASSERT(false, "improper name specified when creating Sprite3D"); - + auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(path)) { @@ -903,9 +910,9 @@ EffectSprite3D* EffectSprite3D::create(const std::string &path) } EffectSprite3D::EffectSprite3D() -: _defaultEffect(nullptr) + : _defaultEffect(nullptr) { - + } EffectSprite3D::~EffectSprite3D() @@ -917,7 +924,7 @@ EffectSprite3D::~EffectSprite3D() CC_SAFE_RELEASE(_defaultEffect); } -void EffectSprite3D::setEffect3D(Effect3D *effect) +void EffectSprite3D::setEffect3D(Effect3D* effect) { if(_defaultEffect == effect) return; CC_SAFE_RETAIN(effect); @@ -930,7 +937,7 @@ void EffectSprite3D::addEffect(Effect3DOutline* effect, ssize_t order) if(nullptr == effect) return; effect->retain(); effect->setTarget(this); - + _effects.push_back(std::make_tuple(order,effect,CustomCommand())); std::sort(std::begin(_effects), std::end(_effects), tuple_sort); @@ -985,26 +992,26 @@ Effect3DOutline* Effect3DOutline::create() bool Effect3DOutline::init() { - + return true; } Effect3DOutline::Effect3DOutline() -: _outlineWidth(1.0f) -, _outlineColor(1, 1, 1) -, _sprite(nullptr) + : _outlineWidth(1.0f) + , _outlineColor(1, 1, 1) + , _sprite(nullptr) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _glProgramState->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _glProgramState->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -1036,10 +1043,10 @@ void Effect3DOutline::setOutlineWidth(float width) } } -void Effect3DOutline::setTarget(EffectSprite3D *sprite) +void Effect3DOutline::setTarget(EffectSprite3D* sprite) { CCASSERT(nullptr != sprite && nullptr != sprite->getMesh(),"Error: Setting a null pointer or a null mesh EffectSprite3D to Effect3D"); - + if(sprite != _sprite) { GLProgram* glprogram; @@ -1053,16 +1060,16 @@ void Effect3DOutline::setTarget(EffectSprite3D *sprite) _glProgramState->retain(); _glProgramState->setUniformVec3("OutLineColor", _outlineColor); _glProgramState->setUniformFloat("OutlineWidth", _outlineWidth); - - + + _sprite = sprite; - + auto mesh = sprite->getMesh(); long offset = 0; for (auto i = 0; i < mesh->getMeshVertexAttribCount(); i++) { auto meshvertexattrib = mesh->getMeshVertexAttribute(i); - + _glProgramState->setVertexAttribPointer(s_attributeNames[meshvertexattrib.vertexAttrib], meshvertexattrib.size, meshvertexattrib.type, @@ -1071,12 +1078,12 @@ void Effect3DOutline::setTarget(EffectSprite3D *sprite) (void*)offset); offset += meshvertexattrib.attribSizeBytes; } - + Color4F color(_sprite->getDisplayedColor()); color.a = _sprite->getDisplayedOpacity() / 255.0f; _glProgramState->setUniformVec4("u_color", Vec4(color.r, color.g, color.b, color.a)); } - + } static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int paletteSize, const float* palette) @@ -1084,7 +1091,7 @@ static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int p glUniform4fv( uniform->location, (GLsizei)paletteSize, (const float*)palette ); } -void Effect3DOutline::draw(const Mat4 &transform) +void Effect3DOutline::draw(const Mat4& transform) { //draw Color4F color(_sprite->getDisplayedColor()); @@ -1095,10 +1102,10 @@ void Effect3DOutline::draw(const Mat4 &transform) glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glEnable(GL_DEPTH_TEST); - + auto mesh = _sprite->getMesh(); glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer()); - + auto skin = _sprite->getMesh()->getSkin(); if(_sprite && skin) { @@ -1106,14 +1113,14 @@ void Effect3DOutline::draw(const Mat4 &transform) skin->getMatrixPaletteSize(), (float*)skin->getMatrixPalette()); _glProgramState->setUniformCallback("u_matrixPalette", function); } - + if(_sprite) _glProgramState->apply(transform); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getIndexBuffer()); glDrawElements(mesh->getPrimitiveType(), (GLsizei)mesh->getIndexCount(), mesh->getIndexFormat(), 0); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, mesh->getIndexCount()); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_DEPTH_TEST); @@ -1122,18 +1129,18 @@ void Effect3DOutline::draw(const Mat4 &transform) } } -void EffectSprite3D::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) +void EffectSprite3D::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) { - for(auto &effect : _effects) + for(auto& effect : _effects) { if(std::get<0>(effect) >=0) break; - CustomCommand &cc = std::get<2>(effect); + CustomCommand& cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } - + if(!_defaultEffect) { Sprite3D::draw(renderer, transform, flags); @@ -1144,15 +1151,15 @@ void EffectSprite3D::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &tran _command.func = CC_CALLBACK_0(Effect3D::draw, _defaultEffect, transform); renderer->addCommand(&_command); } - - for(auto &effect : _effects) + + for(auto& effect : _effects) { if(std::get<0>(effect) <=0) continue; - CustomCommand &cc = std::get<2>(effect); + CustomCommand& cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } } @@ -1160,7 +1167,7 @@ Sprite3DEffectTest::Sprite3DEffectTest() { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DEffectTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1183,22 +1190,22 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) sprite->addEffect(effect, -1); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); - + Effect3DOutline* effect2 = Effect3DOutline::create(); sprite->addEffect(effect2, -2); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); //sprite->setEffect3D(effect); sprite->setScale(6.f); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -1211,7 +1218,7 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -1220,7 +1227,7 @@ void Sprite3DEffectTest::onTouchesEnded(const std::vector& touches, Even for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1232,22 +1239,22 @@ AsyncLoadSprite3DTest::AsyncLoadSprite3DTest() _paths.push_back("Sprite3DTest/orc.c3b"); _paths.push_back("Sprite3DTest/ReskinGirl.c3b"); _paths.push_back("Sprite3DTest/axe.c3b"); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"AsyncLoad Sprite3D"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite,this) ); - + auto s = Director::getInstance()->getWinSize(); item1->setPosition( s.width * .5f, s.height * .8f); - + auto pMenu1 = CCMenu::create(item1, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + auto node = Node::create(); node->setTag(101); this->addChild(node); - + menuCallback_asyncLoadSprite(nullptr); } @@ -1268,14 +1275,15 @@ void AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite(Ref* sender) { //Note that you must stop the tasks before leaving the scene. AsyncTaskPool::getInstance()->stopTasks(AsyncTaskPool::TaskType::TASK_IO); - + auto node = getChildByTag(101); node->removeAllChildren(); //remove all loaded sprite - + //remove cache data Sprite3DCache::getInstance()->removeAllSprite3DData(); long index = 0; - for (const auto& path : _paths) { + for (const auto& path : _paths) + { Sprite3D::createAsync(path, CC_CALLBACK_2(AsyncLoadSprite3DTest::asyncLoad_Callback, this), (void*)index++); } } @@ -1297,7 +1305,7 @@ Sprite3DWithSkinTest::Sprite3DWithSkinTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1346,7 +1354,7 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector& touches, Ev for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1356,7 +1364,7 @@ Sprite3DWithSkinOutlineTest::Sprite3DWithSkinOutlineTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinOutlineTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1371,33 +1379,33 @@ std::string Sprite3DWithSkinOutlineTest::subtitle() const void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) { - + std::string fileName = "Sprite3DTest/orc.c3b"; auto sprite = EffectSprite3D::create(fileName); - + Effect3DOutline* effect = Effect3DOutline::create(); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); sprite->addEffect(effect, -1); - + Effect3DOutline* effect2 = Effect3DOutline::create(); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); sprite->addEffect(effect2, -2); - + sprite->setScale(3); sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); bool inverse = (std::rand() % 3 == 0); - + int rand2 = std::rand(); float speed = 1.0f; if(rand2 % 3 == 1) @@ -1409,7 +1417,7 @@ void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) speed = animate->getSpeed() - 0.5 * CCRANDOM_0_1(); } animate->setSpeed(inverse ? -speed : speed); - + sprite->runAction(RepeatForever::create(animate)); } } @@ -1419,24 +1427,24 @@ void Sprite3DWithSkinOutlineTest::onTouchesEnded(const std::vector& touc for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } Animate3DTest::Animate3DTest() -: _hurt(nullptr) -, _swim(nullptr) -, _sprite(nullptr) -, _moveAction(nullptr) -, _elapseTransTime(0.f) + : _hurt(nullptr) + , _swim(nullptr) + , _sprite(nullptr) + , _moveAction(nullptr) + , _elapseTransTime(0.f) { addSprite3D(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Animate3DTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + scheduleUpdate(); } @@ -1462,7 +1470,7 @@ void Animate3DTest::update(float dt) if (_state == State::HURT_TO_SWIMMING) { _elapseTransTime += dt; - + if (_elapseTransTime >= Animate3D::getTransitionTime()) { _sprite->stopAction(_hurt); @@ -1495,13 +1503,13 @@ void Animate3DTest::addSprite3D() auto animate = Animate3D::create(animation, 0.f, 1.933f); _swim = RepeatForever::create(animate); sprite->runAction(_swim); - + _swim->retain(); _hurt = Animate3D::create(animation, 1.933f, 2.8f); _hurt->retain(); _state = State::SWIMMING; } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr); @@ -1535,7 +1543,7 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev for (auto touch: touches) { auto location = touch->getLocation(); - + if (_sprite) { float len = (_sprite->getPosition() - location).length(); @@ -1560,12 +1568,12 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev } AttachmentTest::AttachmentTest() -: _hasWeapon(false) -, _sprite(nullptr) + : _hasWeapon(false) + , _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(AttachmentTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1587,16 +1595,16 @@ void AttachmentTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; @@ -1617,11 +1625,11 @@ void AttachmentTest::onTouchesEnded(const std::vector& touches, Event* e _hasWeapon = !_hasWeapon; } Sprite3DReskinTest::Sprite3DReskinTest() -: _sprite(nullptr) + : _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DReskinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1649,7 +1657,7 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto pMenu1 = CCMenu::create(item1, item2, item3, item4, item5, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + } void Sprite3DReskinTest::menuCallback_reSkin(Ref* sender) { @@ -1682,41 +1690,41 @@ void Sprite3DReskinTest::addNewSpriteWithCoords(Vec2 p) if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; - + auto& body = _skins[(int)SkinType::UPPER_BODY]; body.push_back("Girl_UpperBody01"); body.push_back("Girl_UpperBody02"); - + auto& pants = _skins[(int)SkinType::PANTS]; pants.push_back("Girl_LowerBody01"); pants.push_back("Girl_LowerBody02"); - + auto& shoes = _skins[(int)SkinType::SHOES]; shoes.push_back("Girl_Shoes01"); shoes.push_back("Girl_Shoes02"); - + auto& hair = _skins[(int)SkinType::HAIR]; hair.push_back("Girl_Hair01"); hair.push_back("Girl_Hair02"); - + auto& face = _skins[(int)SkinType::FACE]; face.push_back("Girl_Face01"); face.push_back("Girl_Face02"); - + auto& hand = _skins[(int)SkinType::HAND]; hand.push_back("Girl_Hand01"); hand.push_back("Girl_Hand02"); - + auto& glasses = _skins[(int)SkinType::GLASSES]; glasses.push_back(""); glasses.push_back("Girl_Glasses01"); - + memset(_curSkin, 0, (int)SkinType::MAX_TYPE * sizeof(int)); - + applyCurSkin(); } @@ -1726,10 +1734,12 @@ void Sprite3DReskinTest::onTouchesEnded(const std::vector& touches, Even void Sprite3DReskinTest::applyCurSkin() { - for (ssize_t i = 0; i < _sprite->getMeshCount(); i++) { + for (ssize_t i = 0; i < _sprite->getMeshCount(); i++) + { auto mesh = _sprite->getMeshByIndex(static_cast(i)); bool isVisible = false; - for (int j = 0; j < (int)SkinType::MAX_TYPE; j++) { + for (int j = 0; j < (int)SkinType::MAX_TYPE; j++) + { if (mesh->getName() == _skins[j].at(_curSkin[j])) { isVisible = true; @@ -1749,7 +1759,7 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto s = Director::getInstance()->getWinSize(); initDrawBox(); - + addNewSpriteWithCoords(Vec2(s.width/2, s.height/2)); MenuItemFont::setFontName("fonts/arial.ttf"); MenuItemFont::setFontSize(65); @@ -1757,12 +1767,12 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() decrease->setColor(Color3B(0,200,20)); auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(Sprite3DWithOBBPerformanceTest::addOBBCallback, this)); increase->setColor(Color3B(0,200,20)); - + auto menu = Menu::create(decrease, increase, nullptr); menu->alignItemsHorizontally(); menu->setPosition(Vec2(s.width/2, s.height-65)); addChild(menu, 1); - + TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); _labelCubeCount = Label::createWithTTF(ttfCount,"0 cubes"); _labelCubeCount->setColor(Color3B(0,200,20)); @@ -1814,14 +1824,14 @@ void Sprite3DWithOBBPerformanceTest::onTouchesBegan(const std::vector& t void Sprite3DWithOBBPerformanceTest::onTouchesEnded(const std::vector& touches, Event* event) { - + } void Sprite3DWithOBBPerformanceTest::onTouchesMoved(const std::vector& touches, Event* event) { for (const auto& touch: touches) { - auto location = touch->getLocation(); + auto location = touch->getLocation(); auto obbSize = _obb.size(); for(decltype(obbSize) i = 0; i < obbSize; i++) @@ -1837,23 +1847,23 @@ void Sprite3DWithOBBPerformanceTest::update(float dt) char szText[16]; sprintf(szText,"%lu cubes",_obb.size()); _labelCubeCount->setString(szText); - + if (_drawDebug) { _drawDebug->clear(); - + Mat4 mat = _sprite->getNodeToWorldTransform(); mat.getRightVector(&_obbt._xAxis); _obbt._xAxis.normalize(); - + mat.getUpVector(&_obbt._yAxis); _obbt._yAxis.normalize(); - + mat.getForwardVector(&_obbt._zAxis); _obbt._zAxis.normalize(); - + _obbt._center = _sprite->getPosition3D(); - + Vec3 corners[8] = {}; _obbt.getCorners(corners); _drawDebug->drawCube(corners, Color4F(0,0,1,1)); @@ -1892,16 +1902,16 @@ void Sprite3DWithOBBPerformanceTest::addNewSpriteWithCoords(Vec2 p) auto animate = Animate3D::create(animation, 0.f, 1.933f); sprite->runAction(RepeatForever::create(animate)); } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Sprite3DWithOBBPerformanceTest::reachEndCallBack, this)), nullptr); seq->setTag(100); sprite->runAction(seq); - + AABB aabb = _sprite->getAABB(); _obbt = OBB(aabb); - + _drawDebug = DrawNode3D::create(); addChild(_drawDebug); } @@ -1955,23 +1965,23 @@ void Sprite3DWithOBBPerformanceTest::delOBBWithCount(float value) void Sprite3DWithOBBPerformanceTest::unproject(const Mat4& viewProjection, const Size* viewport, Vec3* src, Vec3* dst) { assert(dst); - + assert(viewport->width != 0.0f && viewport->height != 0.0f); Vec4 screen(src->x / viewport->width, ((viewport->height - src->y)) / viewport->height, src->z, 1.0f); - + screen.x = screen.x * 2.0f - 1.0f; screen.y = screen.y * 2.0f - 1.0f; screen.z = screen.z * 2.0f - 1.0f; - + viewProjection.getInversed().transformVector(screen, &screen); - + if (screen.w != 0.0f) { screen.x /= screen.w; screen.y /= screen.w; screen.z /= screen.w; } - + dst->set(screen.x, screen.y, screen.z); } @@ -1980,26 +1990,26 @@ void Sprite3DWithOBBPerformanceTest::calculateRayByLocationInView(Ray* ray, cons auto dir = Director::getInstance(); auto view = dir->getWinSize(); auto mat = dir->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - + Vec3 src = Vec3(location.x, location.y, -1); Vec3 nearPoint; unproject(mat, &view, &src, &nearPoint); - + src = Vec3(location.x, location.y, 1); Vec3 farPoint; unproject(mat, &view, &src, &farPoint); - + Vec3 direction; Vec3::subtract(farPoint, nearPoint, &direction); direction.normalize(); - + ray->_origin = nearPoint; ray->_direction = direction; } Sprite3DMirrorTest::Sprite3DMirrorTest() -: _sprite(nullptr) -, _mirrorSprite(nullptr) + : _sprite(nullptr) + , _mirrorSprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); @@ -2021,21 +2031,21 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x - 80, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; _hasWeapon = true; - + //create mirror Sprite3D sprite = Sprite3D::create(fileName); sprite->setScale(5); @@ -2044,25 +2054,25 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x + 80, p.y) ); - + //test attach sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _mirrorSprite = sprite; } QuaternionTest::QuaternionTest() -: _arcSpeed(CC_DEGREES_TO_RADIANS(90)) -, _radius(100.f) -, _accAngle(0.f) + : _arcSpeed(CC_DEGREES_TO_RADIANS(90)) + , _radius(100.f) + , _accAngle(0.f) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords(Vec2(s.width / 2.f, s.height / 2.f)); @@ -2100,58 +2110,60 @@ void QuaternionTest::update(float delta) const float pi = M_PI; if (_accAngle >= 2 * pi) _accAngle -= 2 * pi; - + auto s = Director::getInstance()->getWinSize(); _sprite->setPosition(Vec2(s.width / 2.f + _radius * cosf(_accAngle), s.height / 2.f + _radius * sinf(_accAngle))); - + Quaternion quat; Quaternion::createFromAxisAngle(Vec3(0.f, 0.f, 1.f), _accAngle - pi * 0.5f, &quat); _sprite->setRotationQuat(quat); } UseCaseSprite3D::UseCaseSprite3D() -: _caseIdx(0) + : _caseIdx(0) { auto s = Director::getInstance()->getWinSize(); - + _useCaseTitles[0] = "transparent 3d sprite and 2d sprite"; _useCaseTitles[1] = "ui - 3d - ui"; - + auto itemPrev = MenuItemImage::create("Images/b1.png", "Images/b2.png", - [&](Ref *sender) { - _caseIdx--; - if (_caseIdx < 0) - _caseIdx = (int)USECASE::MAX_CASE_NUM - 1; - this->switchCase(); - }); - + [&](Ref *sender) + { + _caseIdx--; + if (_caseIdx < 0) + _caseIdx = (int)USECASE::MAX_CASE_NUM - 1; + this->switchCase(); + }); + auto itemNext = MenuItemImage::create("Images/f1.png", "Images/f2.png", - [&](Ref *sender) { - _caseIdx++; - if (_caseIdx >= (int)USECASE::MAX_CASE_NUM) - _caseIdx = 0; - this->switchCase(); - }); - + [&](Ref *sender) + { + _caseIdx++; + if (_caseIdx >= (int)USECASE::MAX_CASE_NUM) + _caseIdx = 0; + this->switchCase(); + }); + auto menu = Menu::create(itemPrev, itemNext, nullptr); menu->alignItemsHorizontally(); menu->setScale(0.5); menu->setAnchorPoint(Vec2(0,0)); menu->setPosition(Vec2(s.width/2,70)); - + _label = Label::create(); _label->setPosition(s.width * 0.5f, s.height * 0.8f); addChild(_label); - + addChild(menu); - + //setup camera auto camera = Camera::createPerspective(40, s.width / s.height, 0.01f, 1000.f); camera->setCameraFlag(CameraFlag::USER1); camera->setPosition3D(Vec3(0.f, 30.f, 100.f)); camera->lookAt(Vec3(0.f, 0.f, 0.f)); addChild(camera); - + switchCase(); } @@ -2168,7 +2180,7 @@ std::string UseCaseSprite3D::subtitle() const void UseCaseSprite3D::switchCase() { removeChildByTag(101); - + auto s = Director::getInstance()->getWinSize(); _label->setString(_useCaseTitles[_caseIdx]); if (_caseIdx == 0) // use case 1, 3d transparent sprite + 2d sprite @@ -2180,33 +2192,33 @@ void UseCaseSprite3D::switchCase() if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } - + auto circleBack = Sprite3D::create(); auto circle = Sprite::create("Sprite3DTest/circle.png"); circleBack->setScale(0.5f); circleBack->addChild(circle); circle->runAction(RepeatForever::create(RotateBy::create(3, Vec3(0.f, 0.f, 360.f)))); - + circleBack->setRotation3D(Vec3(90, 0, 0)); - + auto pos = sprite->getPosition3D(); circleBack->setPosition3D(Vec3(pos.x, pos.y, pos.z - 1)); - + sprite->setOpacity(250); sprite->setCameraMask(2); circleBack->setCameraMask(2); sprite->setTag(3); circleBack->setTag(2); - + auto node = Node::create(); node->addChild(sprite); node->addChild(circleBack); node->setTag(101); addChild(node); - + scheduleUpdate(); update(0.f); } @@ -2216,7 +2228,7 @@ void UseCaseSprite3D::switchCase() layer->setPosition(s.width * 0.25f, s.height * 0.25f); layer->setGlobalZOrder(-1); addChild(layer); - + std::string filename = "Sprite3DTest/girl.c3b"; auto sprite = Sprite3D::create(filename); sprite->setScale(0.5f); @@ -2228,20 +2240,20 @@ void UseCaseSprite3D::switchCase() } sprite->setPosition(s.width * 0.25f, s.height * 0.125f); layer->addChild(sprite); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"Message"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Message"); auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); - + item1->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height ) ); item2->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height * 2.f ) ); - + auto pMenu1 = CCMenu::create(item1, item2, nullptr); pMenu1->setPosition(Vec2(0,0)); layer->addChild(pMenu1); - + layer->setTag(101); } } @@ -2274,14 +2286,14 @@ void UseCaseSprite3D::update(float delta) { static float accAngle = 0.f; accAngle += delta * CC_DEGREES_TO_RADIANS(60); - + float radius = 30.f; float x = cosf(accAngle) * radius, z = sinf(accAngle) * radius; - + auto node = getChildByTag(101); auto sprite3d = node->getChildByTag(3); auto circle = node->getChildByTag(2); - + sprite3d->setPositionX(x); sprite3d->setPositionZ(z); circle->setPositionX(x); diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 5b852bc4e1..5c49119afc 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -1,26 +1,26 @@ /**************************************************************************** -Copyright (c) 2014 Chukong Technologies Inc. - -http://www.cocos2d-x.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ + Copyright (c) 2013 cocos2d-x.org + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ #ifndef _SPRITE3D_TEST_H_ #define _SPRITE3D_TEST_H_ @@ -43,11 +43,11 @@ class Sprite3DTestDemo : public BaseTest public: Sprite3DTestDemo(void); virtual ~Sprite3DTestDemo(void); - + void restartCallback(Ref* sender); void nextCallback(Ref* sender); void backCallback(Ref* sender); - + // overrides virtual std::string title() const override; virtual std::string subtitle() const override; @@ -70,7 +70,7 @@ public: Sprite3DBasicTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -83,14 +83,14 @@ public: virtual ~Sprite3DUVAnimationTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + protected: void cylinderUpdate(float dt); - + float _cylinder_texture_offset; float _shining_duraion; - GLProgramState* _state; - + GLProgramState * _state; + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif @@ -116,17 +116,17 @@ public: void move3D(float elapsedTime); void updateState(float elapsedTime); bool isState(unsigned int state,unsigned int bit) const; - 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 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); private: - cocos2d::Camera* _camera; + cocos2d::Camera * _camera; Vec3 _targetPos; unsigned int _curState; - cocos2d::Sprite3D* _plane; - cocos2d::Sprite3D* _orc; - GLProgramState* _state; - + cocos2d::Sprite3D * _plane; + cocos2d::Sprite3D * _orc; + GLProgramState * _state; + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif @@ -142,7 +142,7 @@ public: virtual std::string subtitle() const override; void onTouchesMoved(const std::vector& touches, cocos2d::Event* event); private: - Camera* _camera; + Camera * _camera; }; class Sprite3DBasicToonShaderTest : public Sprite3DTestDemo @@ -153,10 +153,10 @@ public: virtual ~Sprite3DBasicToonShaderTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + protected: - GLProgramState* _state; - + GLProgramState * _state; + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif @@ -167,8 +167,8 @@ class EffectSprite3D; class Effect3D : public Ref { public: - virtual void draw(const Mat4& transform) = 0; - virtual void setTarget(EffectSprite3D* sprite) = 0; + virtual void draw(const Mat4 &transform) = 0; + virtual void setTarget(EffectSprite3D *sprite) = 0; protected: Effect3D() : _glProgramState(nullptr) {} virtual ~Effect3D() @@ -183,20 +183,20 @@ class Effect3DOutline: public Effect3D { public: static Effect3DOutline* create(); - + void setOutlineColor(const Vec3& color); - + void setOutlineWidth(float width); - - virtual void draw(const Mat4& transform) override; - virtual void setTarget(EffectSprite3D* sprite) override; + + virtual void draw(const Mat4 &transform) override; + virtual void setTarget(EffectSprite3D *sprite) override; protected: - + Effect3DOutline(); virtual ~Effect3DOutline(); - + bool init(); - + Vec3 _outlineColor; float _outlineWidth; //weak reference @@ -204,16 +204,16 @@ protected: #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) EventListenerCustom* _backToForegroundListener; #endif - + protected: static const std::string _vertShaderFile; static const std::string _fragShaderFile; static const std::string _keyInGLProgramCache; - + static const std::string _vertSkinnedShaderFile; static const std::string _fragSkinnedShaderFile; static const std::string _keySkinnedInGLProgramCache; - + static GLProgram* getOrCreateProgram(bool isSkinned = false); }; @@ -231,14 +231,14 @@ class EffectSprite3D : public Sprite3D public: static EffectSprite3D* createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath); static EffectSprite3D* create(const std::string& path); - + void setEffect3D(Effect3D* effect); void addEffect(Effect3DOutline* effect, ssize_t order); - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override; protected: EffectSprite3D(); virtual ~EffectSprite3D(); - + std::vector> _effects; Effect3D* _defaultEffect; CustomCommand _command; @@ -251,9 +251,9 @@ public: Sprite3DEffectTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -265,11 +265,11 @@ public: virtual ~AsyncLoadSprite3DTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void menuCallback_asyncLoadSprite(Ref* sender); - + void asyncLoad_Callback(Sprite3D* sprite, void* param); - + protected: std::vector _paths; //model paths to be loaded }; @@ -281,9 +281,9 @@ public: Sprite3DWithSkinTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -294,9 +294,9 @@ public: Sprite3DWithSkinOutlineTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + void onTouchesEnded(const std::vector& touches, Event* event); }; @@ -308,14 +308,14 @@ public: ~Animate3DTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void onTouchesEnded(const std::vector& touches, Event* event); - + virtual void update(float dt) override; - + protected: void addSprite3D(); - + enum class State { SWIMMING, @@ -323,20 +323,20 @@ protected: HURT, HURT_TO_SWIMMING, }; - + void reachEndCallBack(); - + void renewCallBack(); - + cocos2d::Sprite3D* _sprite; - + cocos2d::Action* _swim; cocos2d::Animate3D* _hurt; float _elapseTransTime; - + State _state; - + MoveTo* _moveAction; }; @@ -347,11 +347,11 @@ public: AttachmentTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void onTouchesEnded(const std::vector& touches, Event* event); - + void addNewSpriteWithCoords(Vec2 p); - + protected: bool _hasWeapon; cocos2d::Sprite3D* _sprite; @@ -366,11 +366,11 @@ public: virtual std::string subtitle() const override; void onTouchesEnded(const std::vector& touches, Event* event); void addNewSpriteWithCoords(Vec2 p); - + void menuCallback_reSkin(Ref* sender); protected: void applyCurSkin(); - + enum class SkinType { UPPER_BODY = 0, @@ -382,7 +382,7 @@ protected: GLASSES, MAX_TYPE, }; - + std::vector _skins[(int)SkinType::MAX_TYPE]; //all skins int _curSkin[(int)SkinType::MAX_TYPE]; //current skin index cocos2d::Sprite3D* _sprite; @@ -416,7 +416,7 @@ protected: std::set _intersetList; void initDrawBox(); void reachEndCallBack(); - + void unproject(const Mat4& viewProjection, const Size* viewport, Vec3* src, Vec3* dst); void calculateRayByLocationInView(Ray* ray, const Vec2& location); }; @@ -428,9 +428,9 @@ public: Sprite3DMirrorTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); - + protected: bool _hasWeapon; cocos2d::Sprite3D* _sprite; @@ -444,10 +444,10 @@ public: QuaternionTest(); virtual std::string title() const override; virtual std::string subtitle() const override; - + void addNewSpriteWithCoords(Vec2 p); virtual void update(float delta) override; - + protected: cocos2d::Sprite3D* _sprite; float _arcSpeed; @@ -463,15 +463,15 @@ public: UseCaseSprite3D(); virtual std::string title() const override; virtual std::string subtitle() const override; - + virtual void update(float delta) override; - + void menuCallback_Message(Ref* sender); - + protected: - + void switchCase(); - + enum class USECASE{ _3D_WITH_2D, _UI_3D_UI, From 572ede87f2f21d573ea7088b775b796c208aabfa Mon Sep 17 00:00:00 2001 From: zhukaixy Date: Thu, 26 Mar 2015 10:05:43 +0800 Subject: [PATCH 15/27] correct for code indent --- .../Classes/Sprite3DTest/Sprite3DTest.cpp | 673 +++++++++--------- 1 file changed, 331 insertions(+), 342 deletions(-) diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 97037e3dd1..05e47b9ec8 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -1,26 +1,26 @@ /**************************************************************************** - Copyright (c) 2012 cocos2d-x.org - Copyright (c) 2013-2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2012 cocos2d-x.org + Copyright (c) 2013-2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ #include "Sprite3DTest.h" @@ -54,7 +54,7 @@ static std::function createFunctions[] = CL(Sprite3DHitTest), CL(AsyncLoadSprite3DTest), #if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8) - // 3DEffect use custom shader which is not supported on WP8/WinRT yet. + // 3DEffect use custom shader which is not supported on WP8/WinRT yet. CL(Sprite3DEffectTest), CL(Sprite3DUVAnimationTest), CL(Sprite3DFakeShadowTest), @@ -82,7 +82,7 @@ static Layer* nextSpriteTestAction() { sceneIdx++; sceneIdx = sceneIdx % MAX_LAYER; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -93,7 +93,7 @@ static Layer* backSpriteTestAction() int total = MAX_LAYER; if( sceneIdx < 0 ) sceneIdx += total; - + auto layer = (createFunctions[sceneIdx])(); return layer; } @@ -111,7 +111,7 @@ static Layer* restartSpriteTestAction() //------------------------------------------------------------------ Sprite3DTestDemo::Sprite3DTestDemo(void) - : BaseTest() +: BaseTest() { } @@ -138,7 +138,7 @@ void Sprite3DTestDemo::restartCallback(Ref* sender) { auto s = new (std::nothrow) Sprite3DTestScene(); s->addChild(restartSpriteTestAction()); - + Director::getInstance()->replaceScene(s); s->release(); } @@ -195,7 +195,7 @@ Sprite3DBasicTest::Sprite3DBasicTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DBasicTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -205,26 +205,26 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) //int idx = (int)(CCRANDOM_0_1() * 1400.0f / 100.0f); //int x = (idx%5) * 85; //int y = (idx/5) * 121; - - // //option 1: load a obj that contain the texture in it - // auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); - + +// //option 1: load a obj that contain the texture in it +// auto sprite = Sprite3D::create("sprite3dTest/scene01.obj"); + //option 2: load obj and assign the texture auto sprite = Sprite3D::create("Sprite3DTest/boss1.obj"); sprite->setScale(3.f); sprite->setTexture("Sprite3DTest/boss.png"); - + // //sprite->setEffect(cocos2d::EFFECT_OUTLINE); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -237,7 +237,7 @@ void Sprite3DBasicTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -246,7 +246,7 @@ void Sprite3DBasicTest::onTouchesEnded(const std::vector& touches, Event for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -291,15 +291,14 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() //pass mesh's attribute to shader long offset = 0; auto attributeCount = cylinder->getMesh()->getMeshVertexAttribCount(); - for (auto i = 0; i < attributeCount; i++) - { + for (auto i = 0; i < attributeCount; i++) { auto meshattribute = cylinder->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - cylinder->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + cylinder->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } @@ -310,13 +309,13 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() tRepeatParams.minFilter = GL_NEAREST; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; - shining_texture->setTexParameters(tRepeatParams); + shining_texture->setTexParameters(tRepeatParams); //pass the texture sampler to our custom shader _state->setUniformTexture("caustics",shining_texture); this->addChild(cylinder); - this->setCameraMask(2); + this->setCameraMask(2); this->addChild(camera); //adjust cylinder's position & rotation @@ -325,18 +324,18 @@ Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() //the callback function update cylinder's texcoord schedule(schedule_selector(Sprite3DUVAnimationTest::cylinderUpdate)); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -348,12 +347,12 @@ Sprite3DUVAnimationTest::~Sprite3DUVAnimationTest() #endif } -std::string Sprite3DUVAnimationTest::title() const +std::string Sprite3DUVAnimationTest::title() const { return "Testing UV Animation"; } -std::string Sprite3DUVAnimationTest::subtitle() const +std::string Sprite3DUVAnimationTest::subtitle() const { return ""; } @@ -388,13 +387,13 @@ void Sprite3DUVAnimationTest::cylinderUpdate(float dt) Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() { Size visibleSize = Director::getInstance()->getVisibleSize(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesBegan, this); listener->onTouchesMoved = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesMoved, this); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DFakeShadowTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto layer = Layer::create(); addChild(layer,0); //create Camera @@ -413,19 +412,18 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() _plane->setGLProgramState(_state); //pass mesh's attribute to shader - long offset = 0; + long offset = 0; auto attributeCount = _plane->getMesh()->getMeshVertexAttribCount(); - for (auto i = 0; i < attributeCount; i++) - { + for (auto i = 0; i < attributeCount; i++) { auto meshattribute = _plane->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - _plane->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + _plane->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; - } + } _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); //create shadow texture @@ -435,9 +433,9 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); + shadowTexture->setTexParameters(tRepeatParams); _state->setUniformTexture("u_shadowTexture",shadowTexture); - layer->addChild(_plane); + layer->addChild(_plane); //create the orc _orc = Sprite3D::create("Sprite3DTest/orc.c3b"); @@ -451,30 +449,30 @@ Sprite3DFakeShadowTest::Sprite3DFakeShadowTest() layer->setCameraMask(2); schedule(CC_SCHEDULE_SELECTOR(Sprite3DFakeShadowTest::updateCamera), 0.0f); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); - glProgram->link(); - glProgram->updateUniforms(); - - _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); - - //create shadow texture - auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); - Texture2D::TexParams tRepeatParams;//set texture parameters - tRepeatParams.magFilter = GL_LINEAR; - tRepeatParams.minFilter = GL_LINEAR; - tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; - tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; - shadowTexture->setTexParameters(tRepeatParams); - _state->setUniformTexture("u_shadowTexture",shadowTexture); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/simple_shadow.vert","Sprite3DTest/simple_shadow.frag"); + glProgram->link(); + glProgram->updateUniforms(); + + _state->setUniformMat4("u_model_matrix",_plane->getNodeToWorldTransform()); + + //create shadow texture + auto shadowTexture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/shadowCircle.png"); + Texture2D::TexParams tRepeatParams;//set texture parameters + tRepeatParams.magFilter = GL_LINEAR; + tRepeatParams.minFilter = GL_LINEAR; + tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; + tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; + shadowTexture->setTexParameters(tRepeatParams); + _state->setUniformTexture("u_shadowTexture",shadowTexture); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -486,12 +484,12 @@ Sprite3DFakeShadowTest::~Sprite3DFakeShadowTest() #endif } -std::string Sprite3DFakeShadowTest::title() const +std::string Sprite3DFakeShadowTest::title() const { return "fake shadow effect"; } -std::string Sprite3DFakeShadowTest::subtitle() const +std::string Sprite3DFakeShadowTest::subtitle() const { return "touch the screen to move around"; } @@ -596,18 +594,18 @@ bool Sprite3DFakeShadowTest::isState(unsigned int state,unsigned int bit) const return (state & bit) == bit; } -void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event* event) +void Sprite3DFakeShadowTest::onTouchesBegan(const std::vector& touches, cocos2d::Event *event) { } -void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event* event) +void Sprite3DFakeShadowTest::onTouchesMoved(const std::vector& touches, cocos2d::Event *event) { } -void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event* event) +void Sprite3DFakeShadowTest::onTouchesEnded(const std::vector& touches, cocos2d::Event *event) { - for ( auto& item: touches ) + for ( auto &item: touches ) { auto touch = item; auto location = touch->getLocationInView(); @@ -655,44 +653,43 @@ Sprite3DBasicToonShaderTest::Sprite3DBasicToonShaderTest() auto _camera = Camera::createPerspective(60, visibleSize.width/visibleSize.height, 0.1f, 200); _camera->setCameraFlag(CameraFlag::USER1); // create a teapot - auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); - //create and set our custom shader + auto teapot = Sprite3D::create("Sprite3DTest/teapot.c3b"); + //create and set our custom shader auto shader =GLProgram::createWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); _state = GLProgramState::create(shader); teapot->setGLProgramState(_state); teapot->setPosition3D(Vec3(0,-5,-20)); - teapot->setRotation3D(Vec3(-90,180,0)); + teapot->setRotation3D(Vec3(-90,180,0)); auto rotate_action = RotateBy::create(1.5,Vec3(0,30,0)); - teapot->runAction(RepeatForever::create(rotate_action)); + teapot->runAction(RepeatForever::create(rotate_action)); //pass mesh's attribute to shader long offset = 0; auto attributeCount = teapot->getMesh()->getMeshVertexAttribCount(); - for (auto i = 0; i < attributeCount; i++) - { + for (auto i = 0; i < attributeCount; i++) { auto meshattribute = teapot->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], - meshattribute.size, - meshattribute.type, - GL_FALSE, - teapot->getMesh()->getVertexSizeInBytes(), - (GLvoid*)offset); + meshattribute.size, + meshattribute.type, + GL_FALSE, + teapot->getMesh()->getVertexSizeInBytes(), + (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } addChild(teapot); addChild(_camera); setCameraMask(2); - + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _state->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _state->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames("Sprite3DTest/toon.vert","Sprite3DTest/toon.frag"); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -704,19 +701,19 @@ Sprite3DBasicToonShaderTest::~Sprite3DBasicToonShaderTest() #endif } -std::string Sprite3DBasicToonShaderTest::title() const +std::string Sprite3DBasicToonShaderTest::title() const { return "basic toon shader test"; } -std::string Sprite3DBasicToonShaderTest::subtitle() const +std::string Sprite3DBasicToonShaderTest::subtitle() const { return " "; } //------------------------------------------------------------------ // -// Sprite3DLightMapTest +// Sprite3DLightMapTest // //------------------------------------------------------------------ Sprite3DLightMapTest::Sprite3DLightMapTest() @@ -728,16 +725,16 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() _camera->setCameraFlag(CameraFlag::USER1); _camera->setPosition3D(Vec3(0,25,15)); _camera->setRotation3D(Vec3(-35,0,0)); - auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); - LightMapScene->setScale(0.1f); + auto LightMapScene = Sprite3D::create("Sprite3DTest/LightMapScene.c3b"); + LightMapScene->setScale(0.1f); addChild(LightMapScene); - addChild(_camera); - setCameraMask(2); + addChild(_camera); + setCameraMask(2); //add a point light auto light = PointLight::create(Vec3(35,75,-20.5),Color3B(255,255,255),150); addChild(light); - //set the ambient light + //set the ambient light auto ambient = AmbientLight::create(Color3B(55,55,55)); addChild(ambient); @@ -748,14 +745,14 @@ Sprite3DLightMapTest::Sprite3DLightMapTest() } Sprite3DLightMapTest::~Sprite3DLightMapTest() { - + } std::string Sprite3DLightMapTest::title() const { return "light map test"; } -std::string Sprite3DLightMapTest::subtitle() const +std::string Sprite3DLightMapTest::subtitle() const { return "drag the screen to move around"; } @@ -779,9 +776,9 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to cameraRightDir.normalize(); cameraRightDir.y=0; Vec3 cameraPos= _camera->getPosition3D(); - cameraPos+=cameraDir*newPos.y*delta; + cameraPos+=cameraDir*newPos.y*delta; cameraPos+=cameraRightDir*newPos.x*delta; - _camera->setPosition3D(cameraPos); + _camera->setPosition3D(cameraPos); } } @@ -793,38 +790,37 @@ void Sprite3DLightMapTest::onTouchesMoved(const std::vector& to Sprite3DHitTest::Sprite3DHitTest() { auto s = Director::getInstance()->getWinSize(); - + auto sprite1 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite1->setScale(4.f); sprite1->setTexture("Sprite3DTest/boss.png"); sprite1->setPosition( Vec2(s.width/2, s.height/2) ); - + //add to scene addChild( sprite1 ); sprite1->runAction(RepeatForever::create(RotateBy::create(3, 360))); - + auto sprite2 = Sprite3D::create("Sprite3DTest/boss1.obj"); - + sprite2->setScale(4.f); sprite2->setTexture("Sprite3DTest/boss.png"); sprite2->setPosition( Vec2(s.width/2, s.height/2) ); sprite2->setAnchorPoint(Vec2(0.5, 0.5)); - + //add to scene addChild( sprite2 ); sprite2->runAction(RepeatForever::create(RotateBy::create(3, -360))); - - + + // Make sprite1 touchable auto listener1 = EventListenerTouchOneByOne::create(); listener1->setSwallowTouches(true); - - listener1->onTouchBegan = [](Touch* touch, Event* event) - { + + listener1->onTouchBegan = [](Touch* touch, Event* event){ auto target = static_cast(event->getCurrentTarget()); - - Rect rect = target->getBoundingBox(); + + Rect rect = target->getBoundingBox(); if (rect.containsPoint(touch->getLocation())) { log("sprite3d began... x = %f, y = %f", touch->getLocation().x, touch->getLocation().y); @@ -833,23 +829,21 @@ Sprite3DHitTest::Sprite3DHitTest() } return false; }; - - listener1->onTouchMoved = [](Touch* touch, Event* event) - { + + listener1->onTouchMoved = [](Touch* touch, Event* event){ auto target = static_cast(event->getCurrentTarget()); target->setPosition(target->getPosition() + touch->getDelta()); }; - - listener1->onTouchEnded = [=](Touch* touch, Event* event) - { + + listener1->onTouchEnded = [=](Touch* touch, Event* event){ auto target = static_cast(event->getCurrentTarget()); log("sprite3d onTouchesEnded.. "); target->setOpacity(255); }; - + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1->clone(), sprite2); - + } std::string Sprite3DHitTest::title() const @@ -866,21 +860,21 @@ void Sprite3DTestScene::runThisTest() { auto layer = nextSpriteTestAction(); addChild(layer); - + Director::getInstance()->replaceScene(this); } Sprite3DTestScene::Sprite3DTestScene() { - + } -static int tuple_sort( const std::tuple& tuple1, const std::tuple& tuple2 ) +static int tuple_sort( const std::tuple &tuple1, const std::tuple &tuple2 ) { return std::get<0>(tuple1) < std::get<0>(tuple2); } -EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string& objFilePath, const std::string& textureFilePath) +EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string &objFilePath, const std::string &textureFilePath) { auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(objFilePath)) @@ -894,11 +888,11 @@ EffectSprite3D* EffectSprite3D::createFromObjFileAndTexture(const std::string& o return nullptr; } -EffectSprite3D* EffectSprite3D::create(const std::string& path) +EffectSprite3D* EffectSprite3D::create(const std::string &path) { if (path.length() < 4) CCASSERT(false, "improper name specified when creating Sprite3D"); - + auto sprite = new (std::nothrow) EffectSprite3D(); if (sprite && sprite->initWithFile(path)) { @@ -910,9 +904,9 @@ EffectSprite3D* EffectSprite3D::create(const std::string& path) } EffectSprite3D::EffectSprite3D() - : _defaultEffect(nullptr) +: _defaultEffect(nullptr) { - + } EffectSprite3D::~EffectSprite3D() @@ -924,7 +918,7 @@ EffectSprite3D::~EffectSprite3D() CC_SAFE_RELEASE(_defaultEffect); } -void EffectSprite3D::setEffect3D(Effect3D* effect) +void EffectSprite3D::setEffect3D(Effect3D *effect) { if(_defaultEffect == effect) return; CC_SAFE_RETAIN(effect); @@ -937,7 +931,7 @@ void EffectSprite3D::addEffect(Effect3DOutline* effect, ssize_t order) if(nullptr == effect) return; effect->retain(); effect->setTarget(this); - + _effects.push_back(std::make_tuple(order,effect,CustomCommand())); std::sort(std::begin(_effects), std::end(_effects), tuple_sort); @@ -992,26 +986,26 @@ Effect3DOutline* Effect3DOutline::create() bool Effect3DOutline::init() { - + return true; } Effect3DOutline::Effect3DOutline() - : _outlineWidth(1.0f) - , _outlineColor(1, 1, 1) - , _sprite(nullptr) +: _outlineWidth(1.0f) +, _outlineColor(1, 1, 1) +, _sprite(nullptr) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, - [this](EventCustom*) - { - auto glProgram = _glProgramState->getGLProgram(); - glProgram->reset(); - glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); - glProgram->link(); - glProgram->updateUniforms(); - } - ); + [this](EventCustom*) + { + auto glProgram = _glProgramState->getGLProgram(); + glProgram->reset(); + glProgram->initWithFilenames(_vertShaderFile, _fragShaderFile); + glProgram->link(); + glProgram->updateUniforms(); + } + ); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif } @@ -1043,10 +1037,10 @@ void Effect3DOutline::setOutlineWidth(float width) } } -void Effect3DOutline::setTarget(EffectSprite3D* sprite) +void Effect3DOutline::setTarget(EffectSprite3D *sprite) { CCASSERT(nullptr != sprite && nullptr != sprite->getMesh(),"Error: Setting a null pointer or a null mesh EffectSprite3D to Effect3D"); - + if(sprite != _sprite) { GLProgram* glprogram; @@ -1060,16 +1054,16 @@ void Effect3DOutline::setTarget(EffectSprite3D* sprite) _glProgramState->retain(); _glProgramState->setUniformVec3("OutLineColor", _outlineColor); _glProgramState->setUniformFloat("OutlineWidth", _outlineWidth); - - + + _sprite = sprite; - + auto mesh = sprite->getMesh(); long offset = 0; for (auto i = 0; i < mesh->getMeshVertexAttribCount(); i++) { auto meshvertexattrib = mesh->getMeshVertexAttribute(i); - + _glProgramState->setVertexAttribPointer(s_attributeNames[meshvertexattrib.vertexAttrib], meshvertexattrib.size, meshvertexattrib.type, @@ -1078,12 +1072,12 @@ void Effect3DOutline::setTarget(EffectSprite3D* sprite) (void*)offset); offset += meshvertexattrib.attribSizeBytes; } - + Color4F color(_sprite->getDisplayedColor()); color.a = _sprite->getDisplayedOpacity() / 255.0f; _glProgramState->setUniformVec4("u_color", Vec4(color.r, color.g, color.b, color.a)); } - + } static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int paletteSize, const float* palette) @@ -1091,7 +1085,7 @@ static void MatrixPalleteCallBack( GLProgram* glProgram, Uniform* uniform, int p glUniform4fv( uniform->location, (GLsizei)paletteSize, (const float*)palette ); } -void Effect3DOutline::draw(const Mat4& transform) +void Effect3DOutline::draw(const Mat4 &transform) { //draw Color4F color(_sprite->getDisplayedColor()); @@ -1102,10 +1096,10 @@ void Effect3DOutline::draw(const Mat4& transform) glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glEnable(GL_DEPTH_TEST); - + auto mesh = _sprite->getMesh(); glBindBuffer(GL_ARRAY_BUFFER, mesh->getVertexBuffer()); - + auto skin = _sprite->getMesh()->getSkin(); if(_sprite && skin) { @@ -1113,14 +1107,14 @@ void Effect3DOutline::draw(const Mat4& transform) skin->getMatrixPaletteSize(), (float*)skin->getMatrixPalette()); _glProgramState->setUniformCallback("u_matrixPalette", function); } - + if(_sprite) _glProgramState->apply(transform); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->getIndexBuffer()); glDrawElements(mesh->getPrimitiveType(), (GLsizei)mesh->getIndexCount(), mesh->getIndexFormat(), 0); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, mesh->getIndexCount()); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_DEPTH_TEST); @@ -1129,18 +1123,18 @@ void Effect3DOutline::draw(const Mat4& transform) } } -void EffectSprite3D::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& transform, uint32_t flags) +void EffectSprite3D::draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) { - for(auto& effect : _effects) + for(auto &effect : _effects) { if(std::get<0>(effect) >=0) break; - CustomCommand& cc = std::get<2>(effect); + CustomCommand &cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } - + if(!_defaultEffect) { Sprite3D::draw(renderer, transform, flags); @@ -1151,15 +1145,15 @@ void EffectSprite3D::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& tran _command.func = CC_CALLBACK_0(Effect3D::draw, _defaultEffect, transform); renderer->addCommand(&_command); } - - for(auto& effect : _effects) + + for(auto &effect : _effects) { if(std::get<0>(effect) <=0) continue; - CustomCommand& cc = std::get<2>(effect); + CustomCommand &cc = std::get<2>(effect); cc.func = CC_CALLBACK_0(Effect3D::draw,std::get<1>(effect),transform); renderer->addCommand(&cc); - + } } @@ -1167,7 +1161,7 @@ Sprite3DEffectTest::Sprite3DEffectTest() { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DEffectTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1190,22 +1184,22 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) sprite->addEffect(effect, -1); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); - + Effect3DOutline* effect2 = Effect3DOutline::create(); sprite->addEffect(effect2, -2); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); //sprite->setEffect3D(effect); sprite->setScale(6.f); - + //add to scene addChild( sprite ); - + sprite->setPosition( Vec2( p.x, p.y) ); - + ActionInterval* action; float random = CCRANDOM_0_1(); - + if( random < 0.20 ) action = ScaleBy::create(3, 2); else if(random < 0.40) @@ -1218,7 +1212,7 @@ void Sprite3DEffectTest::addNewSpriteWithCoords(Vec2 p) action = FadeOut::create(2); auto action_back = action->reverse(); auto seq = Sequence::create( action, action_back, nullptr ); - + sprite->runAction( RepeatForever::create(seq) ); } @@ -1227,7 +1221,7 @@ void Sprite3DEffectTest::onTouchesEnded(const std::vector& touches, Even for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1239,22 +1233,22 @@ AsyncLoadSprite3DTest::AsyncLoadSprite3DTest() _paths.push_back("Sprite3DTest/orc.c3b"); _paths.push_back("Sprite3DTest/ReskinGirl.c3b"); _paths.push_back("Sprite3DTest/axe.c3b"); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"AsyncLoad Sprite3D"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite,this) ); - + auto s = Director::getInstance()->getWinSize(); item1->setPosition( s.width * .5f, s.height * .8f); - + auto pMenu1 = CCMenu::create(item1, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + auto node = Node::create(); node->setTag(101); this->addChild(node); - + menuCallback_asyncLoadSprite(nullptr); } @@ -1275,15 +1269,14 @@ void AsyncLoadSprite3DTest::menuCallback_asyncLoadSprite(Ref* sender) { //Note that you must stop the tasks before leaving the scene. AsyncTaskPool::getInstance()->stopTasks(AsyncTaskPool::TaskType::TASK_IO); - + auto node = getChildByTag(101); node->removeAllChildren(); //remove all loaded sprite - + //remove cache data Sprite3DCache::getInstance()->removeAllSprite3DData(); long index = 0; - for (const auto& path : _paths) - { + for (const auto& path : _paths) { Sprite3D::createAsync(path, CC_CALLBACK_2(AsyncLoadSprite3DTest::asyncLoad_Callback, this), (void*)index++); } } @@ -1305,7 +1298,7 @@ Sprite3DWithSkinTest::Sprite3DWithSkinTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1354,7 +1347,7 @@ void Sprite3DWithSkinTest::onTouchesEnded(const std::vector& touches, Ev for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } @@ -1364,7 +1357,7 @@ Sprite3DWithSkinOutlineTest::Sprite3DWithSkinOutlineTest() auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DWithSkinOutlineTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); } @@ -1379,33 +1372,33 @@ std::string Sprite3DWithSkinOutlineTest::subtitle() const void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) { - + std::string fileName = "Sprite3DTest/orc.c3b"; auto sprite = EffectSprite3D::create(fileName); - + Effect3DOutline* effect = Effect3DOutline::create(); effect->setOutlineColor(Vec3(1,0,0)); effect->setOutlineWidth(0.01f); sprite->addEffect(effect, -1); - + Effect3DOutline* effect2 = Effect3DOutline::create(); effect2->setOutlineWidth(0.02f); effect2->setOutlineColor(Vec3(1,1,0)); sprite->addEffect(effect2, -2); - + sprite->setScale(3); sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); bool inverse = (std::rand() % 3 == 0); - + int rand2 = std::rand(); float speed = 1.0f; if(rand2 % 3 == 1) @@ -1417,7 +1410,7 @@ void Sprite3DWithSkinOutlineTest::addNewSpriteWithCoords(Vec2 p) speed = animate->getSpeed() - 0.5 * CCRANDOM_0_1(); } animate->setSpeed(inverse ? -speed : speed); - + sprite->runAction(RepeatForever::create(animate)); } } @@ -1427,24 +1420,24 @@ void Sprite3DWithSkinOutlineTest::onTouchesEnded(const std::vector& touc for (auto touch: touches) { auto location = touch->getLocation(); - + addNewSpriteWithCoords( location ); } } Animate3DTest::Animate3DTest() - : _hurt(nullptr) - , _swim(nullptr) - , _sprite(nullptr) - , _moveAction(nullptr) - , _elapseTransTime(0.f) +: _hurt(nullptr) +, _swim(nullptr) +, _sprite(nullptr) +, _moveAction(nullptr) +, _elapseTransTime(0.f) { addSprite3D(); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Animate3DTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - + scheduleUpdate(); } @@ -1470,7 +1463,7 @@ void Animate3DTest::update(float dt) if (_state == State::HURT_TO_SWIMMING) { _elapseTransTime += dt; - + if (_elapseTransTime >= Animate3D::getTransitionTime()) { _sprite->stopAction(_hurt); @@ -1503,13 +1496,13 @@ void Animate3DTest::addSprite3D() auto animate = Animate3D::create(animation, 0.f, 1.933f); _swim = RepeatForever::create(animate); sprite->runAction(_swim); - + _swim->retain(); _hurt = Animate3D::create(animation, 1.933f, 2.8f); _hurt->retain(); _state = State::SWIMMING; } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Animate3DTest::reachEndCallBack, this)), nullptr); @@ -1543,7 +1536,7 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev for (auto touch: touches) { auto location = touch->getLocation(); - + if (_sprite) { float len = (_sprite->getPosition() - location).length(); @@ -1568,12 +1561,12 @@ void Animate3DTest::onTouchesEnded(const std::vector& touches, Event* ev } AttachmentTest::AttachmentTest() - : _hasWeapon(false) - , _sprite(nullptr) +: _hasWeapon(false) +, _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(AttachmentTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1595,16 +1588,16 @@ void AttachmentTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; @@ -1625,11 +1618,11 @@ void AttachmentTest::onTouchesEnded(const std::vector& touches, Event* e _hasWeapon = !_hasWeapon; } Sprite3DReskinTest::Sprite3DReskinTest() - : _sprite(nullptr) +: _sprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); - + auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesEnded = CC_CALLBACK_2(Sprite3DReskinTest::onTouchesEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); @@ -1637,11 +1630,11 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto label1 = Label::createWithTTF(ttfConfig,"Hair"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Glasses"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label3 = Label::createWithTTF(ttfConfig,"Coat"); auto item3 = MenuItemLabel::create(label3,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label4 = Label::createWithTTF(ttfConfig,"Pants"); - auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); + auto item4 = MenuItemLabel::create(label4, CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); auto label5 = Label::createWithTTF(ttfConfig,"Shoes"); auto item5 = MenuItemLabel::create(label5,CC_CALLBACK_1(Sprite3DReskinTest::menuCallback_reSkin,this) ); item1->setPosition( Vec2(VisibleRect::left().x+50, VisibleRect::bottom().y+item1->getContentSize().height*4 ) ); @@ -1657,7 +1650,7 @@ Sprite3DReskinTest::Sprite3DReskinTest() auto pMenu1 = CCMenu::create(item1, item2, item3, item4, item5, nullptr); pMenu1->setPosition(Vec2(0,0)); this->addChild(pMenu1, 10); - + } void Sprite3DReskinTest::menuCallback_reSkin(Ref* sender) { @@ -1690,41 +1683,41 @@ void Sprite3DReskinTest::addNewSpriteWithCoords(Vec2 p) if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; - + auto& body = _skins[(int)SkinType::UPPER_BODY]; body.push_back("Girl_UpperBody01"); body.push_back("Girl_UpperBody02"); - + auto& pants = _skins[(int)SkinType::PANTS]; pants.push_back("Girl_LowerBody01"); pants.push_back("Girl_LowerBody02"); - + auto& shoes = _skins[(int)SkinType::SHOES]; shoes.push_back("Girl_Shoes01"); shoes.push_back("Girl_Shoes02"); - + auto& hair = _skins[(int)SkinType::HAIR]; hair.push_back("Girl_Hair01"); hair.push_back("Girl_Hair02"); - + auto& face = _skins[(int)SkinType::FACE]; face.push_back("Girl_Face01"); face.push_back("Girl_Face02"); - + auto& hand = _skins[(int)SkinType::HAND]; hand.push_back("Girl_Hand01"); hand.push_back("Girl_Hand02"); - + auto& glasses = _skins[(int)SkinType::GLASSES]; glasses.push_back(""); glasses.push_back("Girl_Glasses01"); - + memset(_curSkin, 0, (int)SkinType::MAX_TYPE * sizeof(int)); - + applyCurSkin(); } @@ -1734,12 +1727,10 @@ void Sprite3DReskinTest::onTouchesEnded(const std::vector& touches, Even void Sprite3DReskinTest::applyCurSkin() { - for (ssize_t i = 0; i < _sprite->getMeshCount(); i++) - { + for (ssize_t i = 0; i < _sprite->getMeshCount(); i++) { auto mesh = _sprite->getMeshByIndex(static_cast(i)); bool isVisible = false; - for (int j = 0; j < (int)SkinType::MAX_TYPE; j++) - { + for (int j = 0; j < (int)SkinType::MAX_TYPE; j++) { if (mesh->getName() == _skins[j].at(_curSkin[j])) { isVisible = true; @@ -1759,7 +1750,7 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto s = Director::getInstance()->getWinSize(); initDrawBox(); - + addNewSpriteWithCoords(Vec2(s.width/2, s.height/2)); MenuItemFont::setFontName("fonts/arial.ttf"); MenuItemFont::setFontSize(65); @@ -1767,12 +1758,12 @@ Sprite3DWithOBBPerformanceTest::Sprite3DWithOBBPerformanceTest() decrease->setColor(Color3B(0,200,20)); auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(Sprite3DWithOBBPerformanceTest::addOBBCallback, this)); increase->setColor(Color3B(0,200,20)); - + auto menu = Menu::create(decrease, increase, nullptr); menu->alignItemsHorizontally(); menu->setPosition(Vec2(s.width/2, s.height-65)); addChild(menu, 1); - + TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); _labelCubeCount = Label::createWithTTF(ttfCount,"0 cubes"); _labelCubeCount->setColor(Color3B(0,200,20)); @@ -1824,14 +1815,14 @@ void Sprite3DWithOBBPerformanceTest::onTouchesBegan(const std::vector& t void Sprite3DWithOBBPerformanceTest::onTouchesEnded(const std::vector& touches, Event* event) { - + } void Sprite3DWithOBBPerformanceTest::onTouchesMoved(const std::vector& touches, Event* event) { for (const auto& touch: touches) { - auto location = touch->getLocation(); + auto location = touch->getLocation(); auto obbSize = _obb.size(); for(decltype(obbSize) i = 0; i < obbSize; i++) @@ -1847,23 +1838,23 @@ void Sprite3DWithOBBPerformanceTest::update(float dt) char szText[16]; sprintf(szText,"%lu cubes",_obb.size()); _labelCubeCount->setString(szText); - + if (_drawDebug) { _drawDebug->clear(); - + Mat4 mat = _sprite->getNodeToWorldTransform(); mat.getRightVector(&_obbt._xAxis); _obbt._xAxis.normalize(); - + mat.getUpVector(&_obbt._yAxis); _obbt._yAxis.normalize(); - + mat.getForwardVector(&_obbt._zAxis); _obbt._zAxis.normalize(); - + _obbt._center = _sprite->getPosition3D(); - + Vec3 corners[8] = {}; _obbt.getCorners(corners); _drawDebug->drawCube(corners, Color4F(0,0,1,1)); @@ -1902,16 +1893,16 @@ void Sprite3DWithOBBPerformanceTest::addNewSpriteWithCoords(Vec2 p) auto animate = Animate3D::create(animation, 0.f, 1.933f); sprite->runAction(RepeatForever::create(animate)); } - + _moveAction = MoveTo::create(4.f, Vec2(s.width / 5.f, s.height / 2.f)); _moveAction->retain(); auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(Sprite3DWithOBBPerformanceTest::reachEndCallBack, this)), nullptr); seq->setTag(100); sprite->runAction(seq); - + AABB aabb = _sprite->getAABB(); _obbt = OBB(aabb); - + _drawDebug = DrawNode3D::create(); addChild(_drawDebug); } @@ -1965,23 +1956,23 @@ void Sprite3DWithOBBPerformanceTest::delOBBWithCount(float value) void Sprite3DWithOBBPerformanceTest::unproject(const Mat4& viewProjection, const Size* viewport, Vec3* src, Vec3* dst) { assert(dst); - + assert(viewport->width != 0.0f && viewport->height != 0.0f); Vec4 screen(src->x / viewport->width, ((viewport->height - src->y)) / viewport->height, src->z, 1.0f); - + screen.x = screen.x * 2.0f - 1.0f; screen.y = screen.y * 2.0f - 1.0f; screen.z = screen.z * 2.0f - 1.0f; - + viewProjection.getInversed().transformVector(screen, &screen); - + if (screen.w != 0.0f) { screen.x /= screen.w; screen.y /= screen.w; screen.z /= screen.w; } - + dst->set(screen.x, screen.y, screen.z); } @@ -1990,26 +1981,26 @@ void Sprite3DWithOBBPerformanceTest::calculateRayByLocationInView(Ray* ray, cons auto dir = Director::getInstance(); auto view = dir->getWinSize(); auto mat = dir->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - + Vec3 src = Vec3(location.x, location.y, -1); Vec3 nearPoint; unproject(mat, &view, &src, &nearPoint); - + src = Vec3(location.x, location.y, 1); Vec3 farPoint; unproject(mat, &view, &src, &farPoint); - + Vec3 direction; Vec3::subtract(farPoint, nearPoint, &direction); direction.normalize(); - + ray->_origin = nearPoint; ray->_direction = direction; } Sprite3DMirrorTest::Sprite3DMirrorTest() - : _sprite(nullptr) - , _mirrorSprite(nullptr) +: _sprite(nullptr) +, _mirrorSprite(nullptr) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords( Vec2(s.width/2, s.height/2) ); @@ -2031,21 +2022,21 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x - 80, p.y) ); - + //test attach auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _sprite = sprite; _hasWeapon = true; - + //create mirror Sprite3D sprite = Sprite3D::create(fileName); sprite->setScale(5); @@ -2054,25 +2045,25 @@ void Sprite3DMirrorTest::addNewSpriteWithCoords(Vec2 p) sprite->setRotation3D(Vec3(0,180,0)); addChild(sprite); sprite->setPosition( Vec2( p.x + 80, p.y) ); - + //test attach sp = Sprite3D::create("Sprite3DTest/axe.c3b"); sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - + animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } _mirrorSprite = sprite; } QuaternionTest::QuaternionTest() - : _arcSpeed(CC_DEGREES_TO_RADIANS(90)) - , _radius(100.f) - , _accAngle(0.f) +: _arcSpeed(CC_DEGREES_TO_RADIANS(90)) +, _radius(100.f) +, _accAngle(0.f) { auto s = Director::getInstance()->getWinSize(); addNewSpriteWithCoords(Vec2(s.width / 2.f, s.height / 2.f)); @@ -2110,60 +2101,58 @@ void QuaternionTest::update(float delta) const float pi = M_PI; if (_accAngle >= 2 * pi) _accAngle -= 2 * pi; - + auto s = Director::getInstance()->getWinSize(); _sprite->setPosition(Vec2(s.width / 2.f + _radius * cosf(_accAngle), s.height / 2.f + _radius * sinf(_accAngle))); - + Quaternion quat; Quaternion::createFromAxisAngle(Vec3(0.f, 0.f, 1.f), _accAngle - pi * 0.5f, &quat); _sprite->setRotationQuat(quat); } UseCaseSprite3D::UseCaseSprite3D() - : _caseIdx(0) +: _caseIdx(0) { auto s = Director::getInstance()->getWinSize(); - + _useCaseTitles[0] = "transparent 3d sprite and 2d sprite"; _useCaseTitles[1] = "ui - 3d - ui"; - + auto itemPrev = MenuItemImage::create("Images/b1.png", "Images/b2.png", - [&](Ref *sender) - { - _caseIdx--; - if (_caseIdx < 0) - _caseIdx = (int)USECASE::MAX_CASE_NUM - 1; - this->switchCase(); - }); - + [&](Ref *sender) { + _caseIdx--; + if (_caseIdx < 0) + _caseIdx = (int)USECASE::MAX_CASE_NUM - 1; + this->switchCase(); + }); + auto itemNext = MenuItemImage::create("Images/f1.png", "Images/f2.png", - [&](Ref *sender) - { - _caseIdx++; - if (_caseIdx >= (int)USECASE::MAX_CASE_NUM) - _caseIdx = 0; - this->switchCase(); - }); - + [&](Ref *sender) { + _caseIdx++; + if (_caseIdx >= (int)USECASE::MAX_CASE_NUM) + _caseIdx = 0; + this->switchCase(); + }); + auto menu = Menu::create(itemPrev, itemNext, nullptr); menu->alignItemsHorizontally(); menu->setScale(0.5); menu->setAnchorPoint(Vec2(0,0)); menu->setPosition(Vec2(s.width/2,70)); - + _label = Label::create(); _label->setPosition(s.width * 0.5f, s.height * 0.8f); addChild(_label); - + addChild(menu); - + //setup camera auto camera = Camera::createPerspective(40, s.width / s.height, 0.01f, 1000.f); camera->setCameraFlag(CameraFlag::USER1); camera->setPosition3D(Vec3(0.f, 30.f, 100.f)); camera->lookAt(Vec3(0.f, 0.f, 0.f)); addChild(camera); - + switchCase(); } @@ -2180,7 +2169,7 @@ std::string UseCaseSprite3D::subtitle() const void UseCaseSprite3D::switchCase() { removeChildByTag(101); - + auto s = Director::getInstance()->getWinSize(); _label->setString(_useCaseTitles[_caseIdx]); if (_caseIdx == 0) // use case 1, 3d transparent sprite + 2d sprite @@ -2192,33 +2181,33 @@ void UseCaseSprite3D::switchCase() if (animation) { auto animate = Animate3D::create(animation); - + sprite->runAction(RepeatForever::create(animate)); } - + auto circleBack = Sprite3D::create(); auto circle = Sprite::create("Sprite3DTest/circle.png"); circleBack->setScale(0.5f); circleBack->addChild(circle); circle->runAction(RepeatForever::create(RotateBy::create(3, Vec3(0.f, 0.f, 360.f)))); - + circleBack->setRotation3D(Vec3(90, 0, 0)); - + auto pos = sprite->getPosition3D(); circleBack->setPosition3D(Vec3(pos.x, pos.y, pos.z - 1)); - + sprite->setOpacity(250); sprite->setCameraMask(2); circleBack->setCameraMask(2); sprite->setTag(3); circleBack->setTag(2); - + auto node = Node::create(); node->addChild(sprite); node->addChild(circleBack); node->setTag(101); addChild(node); - + scheduleUpdate(); update(0.f); } @@ -2228,7 +2217,7 @@ void UseCaseSprite3D::switchCase() layer->setPosition(s.width * 0.25f, s.height * 0.25f); layer->setGlobalZOrder(-1); addChild(layer); - + std::string filename = "Sprite3DTest/girl.c3b"; auto sprite = Sprite3D::create(filename); sprite->setScale(0.5f); @@ -2240,20 +2229,20 @@ void UseCaseSprite3D::switchCase() } sprite->setPosition(s.width * 0.25f, s.height * 0.125f); layer->addChild(sprite); - + TTFConfig ttfConfig("fonts/arial.ttf", 15); auto label1 = Label::createWithTTF(ttfConfig,"Message"); auto item1 = MenuItemLabel::create(label1,CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); auto label2 = Label::createWithTTF(ttfConfig,"Message"); - auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); - + auto item2 = MenuItemLabel::create(label2, CC_CALLBACK_1(UseCaseSprite3D::menuCallback_Message,this) ); + item1->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height ) ); item2->setPosition( Vec2(s.width * 0.5f - item1->getContentSize().width * 0.5f, s.height * 0.5f - item1->getContentSize().height * 2.f ) ); - + auto pMenu1 = CCMenu::create(item1, item2, nullptr); pMenu1->setPosition(Vec2(0,0)); layer->addChild(pMenu1); - + layer->setTag(101); } } @@ -2286,14 +2275,14 @@ void UseCaseSprite3D::update(float delta) { static float accAngle = 0.f; accAngle += delta * CC_DEGREES_TO_RADIANS(60); - + float radius = 30.f; float x = cosf(accAngle) * radius, z = sinf(accAngle) * radius; - + auto node = getChildByTag(101); auto sprite3d = node->getChildByTag(3); auto circle = node->getChildByTag(2); - + sprite3d->setPositionX(x); sprite3d->setPositionZ(z); circle->setPositionX(x); From 7af9957e1c13281643533570fda20ab8f91a6ebb Mon Sep 17 00:00:00 2001 From: yangxiao Date: Thu, 26 Mar 2015 12:56:38 +0800 Subject: [PATCH 16/27] reset submodule --- plugin | 2 +- tests/cpp-tests/Resources/ccs-res | 2 +- tools/cocos2d-console | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin b/plugin index dc25546289..3a71e881f1 160000 --- a/plugin +++ b/plugin @@ -1 +1 @@ -Subproject commit dc25546289ab18dd273199124dada948638eb5e1 +Subproject commit 3a71e881f1b39b5b23ffcf32322e4139bf9350f7 diff --git a/tests/cpp-tests/Resources/ccs-res b/tests/cpp-tests/Resources/ccs-res index ce5606d4e5..7b3f21b5ad 160000 --- a/tests/cpp-tests/Resources/ccs-res +++ b/tests/cpp-tests/Resources/ccs-res @@ -1 +1 @@ -Subproject commit ce5606d4e520d2671a678b0ba3d5a0b84fdb5ab9 +Subproject commit 7b3f21b5ad03445b907e0b713804fdc35f3c0959 diff --git a/tools/cocos2d-console b/tools/cocos2d-console index 53130d3397..41a1468b22 160000 --- a/tools/cocos2d-console +++ b/tools/cocos2d-console @@ -1 +1 @@ -Subproject commit 53130d33970b5d9b15a8f0e4c2632e352a6ade9f +Subproject commit 41a1468b229eb1d93e382e54c70457940129cdc0 From c23746fbcd87946828899c081f3b675d0416c879 Mon Sep 17 00:00:00 2001 From: yangxiao Date: Thu, 26 Mar 2015 13:05:42 +0800 Subject: [PATCH 17/27] modify --- cocos/3d/CCSkybox.cpp | 46 +++++++++---------- cocos/3d/CCSkybox.h | 42 ++++++++--------- cocos/3d/CCTextureCube.cpp | 44 +++++++++--------- cocos/3d/CCTextureCube.h | 44 +++++++++--------- .../Classes/Sprite3DTest/Sprite3DTest.cpp | 2 +- .../Classes/Sprite3DTest/Sprite3DTest.h | 12 ++--- 6 files changed, 95 insertions(+), 95 deletions(-) diff --git a/cocos/3d/CCSkybox.cpp b/cocos/3d/CCSkybox.cpp index 173ed2c6ca..c9eb9705dc 100644 --- a/cocos/3d/CCSkybox.cpp +++ b/cocos/3d/CCSkybox.cpp @@ -1,29 +1,29 @@ /**************************************************************************** - Copyright (c) 2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2015 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ -#include "CCSkybox.h" -#include "CCTextureCube.h" +#include "3d/CCSkybox.h" +#include "3d/CCTextureCube.h" NS_CC_BEGIN diff --git a/cocos/3d/CCSkybox.h b/cocos/3d/CCSkybox.h index 55954e42c4..720c8d4442 100644 --- a/cocos/3d/CCSkybox.h +++ b/cocos/3d/CCSkybox.h @@ -1,25 +1,25 @@ /**************************************************************************** - Copyright (c) 2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + Copyright (c) 2015 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. ****************************************************************************/ #ifndef __SKYBOX_H__ diff --git a/cocos/3d/CCTextureCube.cpp b/cocos/3d/CCTextureCube.cpp index 5cd5e80322..f11c306040 100644 --- a/cocos/3d/CCTextureCube.cpp +++ b/cocos/3d/CCTextureCube.cpp @@ -1,26 +1,26 @@ /**************************************************************************** - Copyright (c) 2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -****************************************************************************/ + Copyright (c) 2015 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ #include "3d/CCTextureCube.h" #include "platform/CCImage.h" diff --git a/cocos/3d/CCTextureCube.h b/cocos/3d/CCTextureCube.h index 460b4c6f0a..f8c25902b4 100644 --- a/cocos/3d/CCTextureCube.h +++ b/cocos/3d/CCTextureCube.h @@ -1,26 +1,26 @@ /**************************************************************************** - Copyright (c) 2014 Chukong Technologies Inc. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -****************************************************************************/ + Copyright (c) 2015 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ #ifndef __CCTEXTURECUBE_H__ #define __CCTEXTURECUBE_H__ diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp index 5443232589..9feda1cc5c 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.cpp @@ -2362,7 +2362,7 @@ Sprite3DCubeMapTest::~Sprite3DCubeMapTest() std::string Sprite3DCubeMapTest::title() const { - return "CubeMap && Skybox Test"; + return "CubeMap & Skybox Test"; } std::string Sprite3DCubeMapTest::subtitle() const diff --git a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h index 41ff971f12..3df3b5826b 100644 --- a/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h +++ b/tests/cpp-tests/Classes/Sprite3DTest/Sprite3DTest.h @@ -30,12 +30,12 @@ #include namespace cocos2d { -class Animate3D; -class Sprite3D; -class Delay; -class Ray; -class DrawNode3D; -class GLProgramState; + class Animate3D; + class Sprite3D; + class Delay; + class Ray; + class DrawNode3D; + class GLProgramState; } class Sprite3DTestDemo : public BaseTest From 7d3154e2e9c369124ba9efb89f12d03d2d34d30e Mon Sep 17 00:00:00 2001 From: yangxiao Date: Thu, 26 Mar 2015 14:34:11 +0800 Subject: [PATCH 18/27] add to linux --- cocos/3d/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cocos/3d/CMakeLists.txt b/cocos/3d/CMakeLists.txt index 3acd5a5254..682655a154 100644 --- a/cocos/3d/CMakeLists.txt +++ b/cocos/3d/CMakeLists.txt @@ -23,5 +23,7 @@ set(COCOS_3D_SRC 3d/CCSprite3D.cpp 3d/CCSprite3DMaterial.cpp 3d/CCBillBoard.cpp + 3d/CCSkybox.cpp + 3d/CCTextureCube.cpp ) From 6cd1697240ac24099e5ed056b56540cd36535bce Mon Sep 17 00:00:00 2001 From: yangxiao Date: Thu, 26 Mar 2015 18:10:42 +0800 Subject: [PATCH 19/27] config wp8 and add comment --- cocos/2d/libcocos2d_wp8.vcxproj | 4 ++++ cocos/2d/libcocos2d_wp8.vcxproj.filters | 12 ++++++++++ cocos/3d/CCSkybox.h | 25 +++++++++++++++++--- cocos/3d/CCTextureCube.h | 31 ++++++++++++++++++------- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/cocos/2d/libcocos2d_wp8.vcxproj b/cocos/2d/libcocos2d_wp8.vcxproj index 2bd3354056..6b862f370e 100644 --- a/cocos/2d/libcocos2d_wp8.vcxproj +++ b/cocos/2d/libcocos2d_wp8.vcxproj @@ -386,8 +386,10 @@ + + @@ -990,8 +992,10 @@ + + diff --git a/cocos/2d/libcocos2d_wp8.vcxproj.filters b/cocos/2d/libcocos2d_wp8.vcxproj.filters index 93d1161219..9e6d9e7b74 100644 --- a/cocos/2d/libcocos2d_wp8.vcxproj.filters +++ b/cocos/2d/libcocos2d_wp8.vcxproj.filters @@ -1809,6 +1809,12 @@ cocostudio\json + + 3d + + + 3d + @@ -3516,6 +3522,12 @@ cocostudio\json + + 3d + + + 3d + diff --git a/cocos/3d/CCSkybox.h b/cocos/3d/CCSkybox.h index 720c8d4442..266e0eca86 100644 --- a/cocos/3d/CCSkybox.h +++ b/cocos/3d/CCSkybox.h @@ -31,29 +31,48 @@ NS_CC_BEGIN class TextureCube; +/** +* Sky box technology usually used to simulate infinity sky, mountains and other phenomena. +*/ class CC_DLL Skybox : public Node { public: CREATE_FUNC(Skybox); + /**texture getter and setter*/ void setTexture(TextureCube*); - void onDraw(const Mat4& transform, uint32_t flags); - - // Overrides + /** draw Skybox object */ virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + /** reload sky box after GLESContext reconstructed.*/ void reload(); CC_CONSTRUCTOR_ACCESS: + /** + * Constructor. + */ Skybox(); + + /** + * Destructor. + */ virtual ~Skybox(); + + /** + * init Skybox. + */ virtual bool init(); protected: + /** + * init internal buffers for Skybox. + */ void initBuffers(); + void onDraw(const Mat4& transform, uint32_t flags); + GLuint _vao; GLuint _vertexBuffer; GLuint _indexBuffer; diff --git a/cocos/3d/CCTextureCube.h b/cocos/3d/CCTextureCube.h index f8c25902b4..011c847191 100644 --- a/cocos/3d/CCTextureCube.h +++ b/cocos/3d/CCTextureCube.h @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** Copyright (c) 2015 Chukong Technologies Inc. http://www.cocos2d-x.org @@ -34,28 +34,41 @@ NS_CC_BEGIN /** - texture cube map. - It wraps the cocos2d::Texture2D + TextureCube is a collection of six separate square textures that are put + onto the faces of an imaginary cube. */ class CC_DLL TextureCube: public Texture2D { public: - /** - create cube texture from 6 textures. - - @param path The image resource path. - @create cube texture from 6 textures. + /** create cube texture from 6 textures. + @param positive_x texture for the right side of the texture cube face. + @param negative_x texture for the up side of the texture cube face. + @param positive_y texture for the top side of the texture cube face + @param negative_y texture for the bottom side of the texture cube face + @param positive_z texture for the forward side of the texture cube face. + @param negative_z texture for the rear side of the texture cube face. + @return A new texture cube inited with given parameters. */ static TextureCube* create(const std::string& positive_x, const std::string& negative_x, const std::string& positive_y, const std::string& negative_y, const std::string& positive_z, const std::string& negative_z); + /** Sets the min filter, mag filter, wrap s and wrap t texture parameters. + If the texture size is NPOT (non power of 2), then in can only use GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}. + */ void setTexParameters(const TexParams&); + /** reload texture cube after GLESContext reconstructed.*/ bool reloadTexture(); CC_CONSTRUCTOR_ACCESS: + /** + * Constructor. + */ TextureCube(); - TextureCube(const TextureCube&); + + /** + * Destructor. + */ virtual ~TextureCube(); protected: From c73602a5238db3fd03f867d72f63d057614bff58 Mon Sep 17 00:00:00 2001 From: CocosRobot Date: Fri, 27 Mar 2015 02:26:35 +0000 Subject: [PATCH 20/27] [AUTO]: updating luabinding automatically --- .../scripting/lua-bindings/auto/api/ClippingRectangleNode.lua | 4 ++-- cocos/scripting/lua-bindings/auto/api/Lens3D.lua | 2 +- cocos/scripting/lua-bindings/auto/api/Shaky3D.lua | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos/scripting/lua-bindings/auto/api/ClippingRectangleNode.lua b/cocos/scripting/lua-bindings/auto/api/ClippingRectangleNode.lua index 7242da6b3b..f73fe5eee6 100644 --- a/cocos/scripting/lua-bindings/auto/api/ClippingRectangleNode.lua +++ b/cocos/scripting/lua-bindings/auto/api/ClippingRectangleNode.lua @@ -13,7 +13,7 @@ -------------------------------- -- brief Enable/Disable the clipping.
--- param Pass true to enable clipping. Pass false to disable clipping. +-- param enabled Pass true to enable clipping. Pass false to disable clipping. -- @function [parent=#ClippingRectangleNode] setClippingEnabled -- @param self -- @param #bool enabled @@ -28,7 +28,7 @@ -------------------------------- -- brief Set the clipping rectangle.
--- param Specify the clipping rectangle. +-- param clippingRegion Specify the clipping rectangle. -- @function [parent=#ClippingRectangleNode] setClippingRegion -- @param self -- @param #rect_table clippingRegion diff --git a/cocos/scripting/lua-bindings/auto/api/Lens3D.lua b/cocos/scripting/lua-bindings/auto/api/Lens3D.lua index 2f3c93be70..004787619d 100644 --- a/cocos/scripting/lua-bindings/auto/api/Lens3D.lua +++ b/cocos/scripting/lua-bindings/auto/api/Lens3D.lua @@ -6,7 +6,7 @@ -------------------------------- -- brief Set the center position of lens effect.
--- param The center position will be set. +-- param position The center position will be set. -- @function [parent=#Lens3D] setPosition -- @param self -- @param #vec2_table position diff --git a/cocos/scripting/lua-bindings/auto/api/Shaky3D.lua b/cocos/scripting/lua-bindings/auto/api/Shaky3D.lua index eb21f4c48b..4f3a07d944 100644 --- a/cocos/scripting/lua-bindings/auto/api/Shaky3D.lua +++ b/cocos/scripting/lua-bindings/auto/api/Shaky3D.lua @@ -6,7 +6,7 @@ -------------------------------- -- brief Create the action with a range, shake Z vertices, a grid and duration.
--- param duration Specify the duration of the Shaky3D action. It's a value in seconds.
+-- param initWithDuration Specify the duration of the Shaky3D action. It's a value in seconds.
-- param gridSize Specify the size of the grid.
-- param range Specify the range of the shaky effect.
-- param shakeZ Specify whether shake on the z axis.
From 0af4f9f1edeebaeda671bfa41cfa17b63dcc9aa3 Mon Sep 17 00:00:00 2001 From: calfjohn Date: Fri, 27 Mar 2015 10:34:01 +0800 Subject: [PATCH 21/27] fixed doxygen warning for physics and texture2d --- cocos/physics/CCPhysicsBody.h | 2 +- cocos/physics/CCPhysicsShape.h | 8 ++++---- cocos/renderer/CCTexture2D.h | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cocos/physics/CCPhysicsBody.h b/cocos/physics/CCPhysicsBody.h index 48fdfd66cf..ed0ca49715 100644 --- a/cocos/physics/CCPhysicsBody.h +++ b/cocos/physics/CCPhysicsBody.h @@ -399,7 +399,7 @@ public: /** * @brief Set the body mass. * - * @attension If you need add/subtract mass to body, don't use setMass(getMass() +/- mass), because the mass of body may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMass() instead. + * @attention If you need add/subtract mass to body, don't use setMass(getMass() +/- mass), because the mass of body may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMass() instead. */ void setMass(float mass); diff --git a/cocos/physics/CCPhysicsShape.h b/cocos/physics/CCPhysicsShape.h index 5df64f7718..ac535e8e7a 100644 --- a/cocos/physics/CCPhysicsShape.h +++ b/cocos/physics/CCPhysicsShape.h @@ -486,7 +486,7 @@ public: /** * Get this polygon's points array count. * - * @preturn An interger number. + * @return An interger number. */ int getPointsCount() const; @@ -523,7 +523,7 @@ public: /** * Get this box's width and height. * - * @preturn An Size object. + * @return An Size object. */ Size getSize() const; @@ -621,7 +621,7 @@ public: /** * Get this polygon's points array count. * - * @preturn An interger number. + * @return An interger number. */ int getPointsCount() const; @@ -700,7 +700,7 @@ public: /** * Get this chain's points array count. * - * @preturn An interger number. + * @return An interger number. */ int getPointsCount() const; diff --git a/cocos/renderer/CCTexture2D.h b/cocos/renderer/CCTexture2D.h index 4c2295a197..46e0d18ebe 100644 --- a/cocos/renderer/CCTexture2D.h +++ b/cocos/renderer/CCTexture2D.h @@ -282,6 +282,7 @@ public: @param text A null terminated string. @param fontName The font name. + @param fontSize The font size. @param dimensions The font dimension. @param hAlignment The font horizontal text alignment type. @param vAlignment The font vertical text alignment type. From fdffad3956b4a35c70913a30bc46f2977039b50c Mon Sep 17 00:00:00 2001 From: Wenhai Lin Date: Fri, 27 Mar 2015 10:52:59 +0800 Subject: [PATCH 22/27] [ci skip]Fixed warnings when generating docs by doxygen. --- cocos/2d/CCNode.h | 6 +++--- cocos/audio/include/AudioEngine.h | 5 +++-- cocos/base/CCMap.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cocos/2d/CCNode.h b/cocos/2d/CCNode.h index 0a0e070ac8..bc4d446a02 100644 --- a/cocos/2d/CCNode.h +++ b/cocos/2d/CCNode.h @@ -739,9 +739,9 @@ public: * * If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. * - * @param child A child node. - * @param zOrder Z order for drawing priority. Please refer to `setLocalZOrder(int)`. - * @param tag An integer to identify the node easily. Please refer to `setTag(int)`. + * @param child A child node. + * @param localZOrder Z order for drawing priority. Please refer to `setLocalZOrder(int)`. + * @param tag An integer to identify the node easily. Please refer to `setTag(int)`. * * Please use `addChild(Node* child, int localZOrder, const std::string &name)` instead. */ diff --git a/cocos/audio/include/AudioEngine.h b/cocos/audio/include/AudioEngine.h index 9ab5ac13f9..078075c91b 100644 --- a/cocos/audio/include/AudioEngine.h +++ b/cocos/audio/include/AudioEngine.h @@ -194,10 +194,11 @@ public: /** * Sets the current playback position of an audio instance. * - * @param audioID An audioID returned by the play2d function. + * @param audioID An audioID returned by the play2d function. + * @param sec The offset in seconds from the start to seek to. * @return */ - static bool setCurrentTime(int audioID, float time); + static bool setCurrentTime(int audioID, float sec); /** * Gets the current playback position of an audio instance. diff --git a/cocos/base/CCMap.h b/cocos/base/CCMap.h index edecf4074e..0f2ff5e2a1 100644 --- a/cocos/base/CCMap.h +++ b/cocos/base/CCMap.h @@ -47,7 +47,7 @@ NS_CC_BEGIN /** * Similar to std::unordered_map, but it will manage reference count automatically internally. * Which means it will invoke Ref::retain() when adding an element, and invoke Ref::release() when removing an element. - * @warn The element should be `Ref` or its sub-class. + * @warning The element should be `Ref` or its sub-class. * @lua NA */ template From 0cab686c007ef376bb7634667b8d6d1de2cce0ec Mon Sep 17 00:00:00 2001 From: minggo Date: Fri, 27 Mar 2015 11:08:01 +0800 Subject: [PATCH 23/27] [ci skip]update CHANGELOG --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index cf72ff5d3f..31049729eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,6 @@ cocos2d-x-3.6beta Apr.14 2015 + [NEW] 3D: added texturecub supported + [FIX] Sprite3D: memory leak cocos2d-x-3.5 Mar.23 2015 From a1b054911c68693e5a5b2846b2f34ca4c5d6616d Mon Sep 17 00:00:00 2001 From: samuele3hu Date: Fri, 27 Mar 2015 11:13:28 +0800 Subject: [PATCH 24/27] Update comments of some header files --- cocos/network/SocketIO.h | 2 +- .../lua-bindings/manual/CCLuaStack.h | 6 ++--- .../lua-bindings/manual/LuaBasicConversions.h | 26 +++++++++---------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cocos/network/SocketIO.h b/cocos/network/SocketIO.h index d65d89d188..57e5d89d6e 100644 --- a/cocos/network/SocketIO.h +++ b/cocos/network/SocketIO.h @@ -252,7 +252,7 @@ public: /** * Used to register a socket.io event callback. * Event argument should be passed using CC_CALLBACK2(&Base::function, this). - * @param eventName. + * @param eventName the name of event. * @param e the callback function. */ void on(const std::string& eventName, SIOEvent e); diff --git a/cocos/scripting/lua-bindings/manual/CCLuaStack.h b/cocos/scripting/lua-bindings/manual/CCLuaStack.h index 8938413cb2..04c71183d9 100644 --- a/cocos/scripting/lua-bindings/manual/CCLuaStack.h +++ b/cocos/scripting/lua-bindings/manual/CCLuaStack.h @@ -321,7 +321,7 @@ public: * By calling this function, the number of return value is numResults(may be > 1). * All the return values are stored in the resultArray. * - * @param nHandler the index count corresponding to the lua function. + * @param handler the index count corresponding to the lua function. * @param numArgs the number of variables. * @param numResults the number of return value. * @param resultArray a array used to store the return value. @@ -381,7 +381,7 @@ public: * * @param L the current lua_State. * @param chunk the buffer pointer. - * @param chunSize the size of buffer. + * @param chunkSize the size of buffer. * @param chunkName the name of chunk pointer. * @return 0, LUA_ERRSYNTAX or LUA_ERRMEM:. * @lua NA @@ -402,7 +402,7 @@ public: /** * Load the Lua chunks from current lua_State. * - * @param l the current lua_State. + * @param L the current lua_State. * @return 1 if load sucessfully otherwise 0. * @lua NA * @js NA diff --git a/cocos/scripting/lua-bindings/manual/LuaBasicConversions.h b/cocos/scripting/lua-bindings/manual/LuaBasicConversions.h index 3d3d1913ad..6a6d3dbe95 100644 --- a/cocos/scripting/lua-bindings/manual/LuaBasicConversions.h +++ b/cocos/scripting/lua-bindings/manual/LuaBasicConversions.h @@ -58,7 +58,7 @@ cocos2d::log(__VA_ARGS__); \ * @param L the current lua_State. * @param lo the given accpetable index of stack. * @param type the typename used to judge. - * @int def whether has default value. + * @param def whether has default value. * @return Return true if the typename of userdata at the given accepteable index of stack is equal to type, otherwise return false. * @lua NA * @js NA @@ -849,9 +849,9 @@ extern bool luaval_to_std_vector_ushort(lua_State* L, int lo, std::vector& inValue) * The object in the cocos2d::Map which would be pushed into the table should be Ref type. * * @param L the current lua_State. - * @param verAttrib a cocos2d::Map object. + * @param v a cocos2d::Map object. * @lua NA * @js NA */ @@ -1190,7 +1190,7 @@ void ccmap_string_key_to_luaval(lua_State* L, const cocos2d::Map * Value::Type::INT_KEY_MAP -> push a hash table into the Lua stack. * * @param L the current lua_State. - * @param verAttrib a cocos2d::Value object. + * @param inValue a cocos2d::Value object. * @lua NA * @js NA */ @@ -1201,7 +1201,7 @@ void ccvalue_to_luaval(lua_State* L,const cocos2d::Value& inValue); * The type of value of the key/value pair would be boolean,number, integer, string, array table, hash table. * * @param L the current lua_State. - * @param verAttrib a cocos2d::ValueMap object. + * @param inValue a cocos2d::ValueMap object. * @lua NA * @js NA */ @@ -1212,7 +1212,7 @@ void ccvaluemap_to_luaval(lua_State* L,const cocos2d::ValueMap& inValue); * The type of value of the key/value pair would be boolean,number, integer, string, array table, hash table. * * @param L the current lua_State. - * @param verAttrib a cocos2d::Map object. + * @param inValue a cocos2d::ValueMapIntKey object. * @lua NA * @js NA */ @@ -1223,7 +1223,7 @@ void ccvaluemapintkey_to_luaval(lua_State* L, const cocos2d::ValueMapIntKey& inV * The type of value of the key/value pair would be boolean,number, integer, string, array table, hash table. * * @param L the current lua_State. - * @param verAttrib a cocos2d::ValueVector object. + * @param inValue a cocos2d::ValueVector object. * @lua NA * @js NA */ @@ -1235,7 +1235,7 @@ void ccvaluevector_to_luaval(lua_State* L, const cocos2d::ValueVector& inValue); * Get the real typename for the specified typename. * Because all override functions wouldn't be bound,so we must use `typeid` to get the real class name. * - * @param T the pointer points to a object. + * @param ret the pointer points to a type T object. * @param type the string pointer points to specified typename. * @return return the pointer points to the real typename, or nullptr. */ From 72f378db712401a3a02d8058238f4d1a05cb1060 Mon Sep 17 00:00:00 2001 From: minggo Date: Fri, 27 Mar 2015 11:15:10 +0800 Subject: [PATCH 25/27] [ci skip]update CHANGELOG --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 31049729eb..8077d9b366 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -cocos2d-x-3.6beta Apr.14 2015 +cocos2d-x-3.6beta0 Apr.14 2015 [NEW] 3D: added texturecub supported [FIX] Sprite3D: memory leak From 43c030205b6de22a1104298ceda9b865b9c69ff5 Mon Sep 17 00:00:00 2001 From: CocosRobot Date: Fri, 27 Mar 2015 03:16:06 +0000 Subject: [PATCH 26/27] [AUTO][ci skip]: updating cocos2dx_files.json --- templates/cocos2dx_files.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/templates/cocos2dx_files.json b/templates/cocos2dx_files.json index c5b67912d4..6e33851a89 100644 --- a/templates/cocos2dx_files.json +++ b/templates/cocos2dx_files.json @@ -275,10 +275,14 @@ "cocos/3d/CCRay.h", "cocos/3d/CCSkeleton3D.cpp", "cocos/3d/CCSkeleton3D.h", + "cocos/3d/CCSkybox.cpp", + "cocos/3d/CCSkybox.h", "cocos/3d/CCSprite3D.cpp", "cocos/3d/CCSprite3D.h", "cocos/3d/CCSprite3DMaterial.cpp", "cocos/3d/CCSprite3DMaterial.h", + "cocos/3d/CCTextureCube.cpp", + "cocos/3d/CCTextureCube.h", "cocos/3d/CMakeLists.txt", "cocos/3d/cocos3d.h", "cocos/Android.mk", @@ -1117,6 +1121,8 @@ "cocos/renderer/ccShader_3D_Particle.vert", "cocos/renderer/ccShader_3D_PositionNormalTex.vert", "cocos/renderer/ccShader_3D_PositionTex.vert", + "cocos/renderer/ccShader_3D_Skybox.frag", + "cocos/renderer/ccShader_3D_Skybox.vert", "cocos/renderer/ccShader_Label.vert", "cocos/renderer/ccShader_Label_df.frag", "cocos/renderer/ccShader_Label_df_glow.frag", From 17bd26e9d49cf7ff373536a510f788fac5565efe Mon Sep 17 00:00:00 2001 From: SuYaohui <365886954@qq.com> Date: Fri, 27 Mar 2015 11:39:31 +0800 Subject: [PATCH 27/27] Add comments --- cocos/2d/CCAction.h | 2 +- cocos/2d/CCActionCamera.h | 4 ++-- cocos/2d/CCActionCatmullRom.h | 4 ++-- cocos/2d/CCAnimation.h | 6 +++--- cocos/2d/CCRenderTexture.h | 7 ++++--- cocos/2d/CCSprite.h | 16 ++++++++-------- cocos/2d/CCTMXLayer.h | 2 +- cocos/2d/CCTMXObjectGroup.h | 2 +- cocos/2d/CCTMXTiledMap.h | 2 +- cocos/base/CCNS.h | 6 +++--- cocos/base/ccConfig.h | 4 ++-- cocos/platform/CCGLView.h | 5 ++++- 12 files changed, 32 insertions(+), 28 deletions(-) diff --git a/cocos/2d/CCAction.h b/cocos/2d/CCAction.h index 83ba9e2a86..d98f90971d 100644 --- a/cocos/2d/CCAction.h +++ b/cocos/2d/CCAction.h @@ -109,7 +109,7 @@ public: * @param time A value between 0 and 1. */ virtual void update(float time); - /** Return certain target.. + /** Return certain target. * * @return A certain target. */ diff --git a/cocos/2d/CCActionCamera.h b/cocos/2d/CCActionCamera.h index 51c0d107b3..18ca96af41 100644 --- a/cocos/2d/CCActionCamera.h +++ b/cocos/2d/CCActionCamera.h @@ -124,9 +124,9 @@ public: * @param t Duration in seconds. * @param radius The start radius. * @param deltaRadius The delta radius. - * @param angelZ The start Angel in Z. + * @param angleZ The start Angel in Z. * @param deltaAngleZ The delta angle in Z. - * @param angelX The start Angel in X. + * @param angleX The start Angel in X. * @param deltaAngleX The delta angle in X. * @return An OrbitCamera. */ diff --git a/cocos/2d/CCActionCatmullRom.h b/cocos/2d/CCActionCatmullRom.h index 1c6c3d9ae8..22ccd2b27c 100644 --- a/cocos/2d/CCActionCatmullRom.h +++ b/cocos/2d/CCActionCatmullRom.h @@ -168,7 +168,7 @@ public: /** Creates an action with a Cardinal Spline array of points and tension. * @param duration In seconds. - * @param point An PointArray. + * @param points An PointArray. * @param tension Goodness of fit. * @code * When this function bound to js or lua,the input params are changed. @@ -192,7 +192,7 @@ public: * Initializes the action with a duration and an array of points. * * @param duration In seconds. - * @param point An PointArray. + * @param points An PointArray. * @param tension Goodness of fit. */ bool initWithDuration(float duration, PointArray* points, float tension); diff --git a/cocos/2d/CCAnimation.h b/cocos/2d/CCAnimation.h index c44cbc5628..72e089c0ab 100644 --- a/cocos/2d/CCAnimation.h +++ b/cocos/2d/CCAnimation.h @@ -45,10 +45,10 @@ class SpriteFrame; * @{ */ -/** AnimationFrame +/** @class AnimationFrame * * A frame of the animation. It contains information like: - * - sprite frame name. + * - sprite frame name. * - # of delay units. * - offset @@ -222,7 +222,7 @@ public: /** Sets the delay in seconds of the "delay unit". * - * @param setDelayPerUnit The delay in seconds of the "delay unit". + * @param delayPerUnit The delay in seconds of the "delay unit". */ void setDelayPerUnit(float delayPerUnit) { _delayPerUnit = delayPerUnit; }; diff --git a/cocos/2d/CCRenderTexture.h b/cocos/2d/CCRenderTexture.h index 33f64b3b75..373f003e6b 100644 --- a/cocos/2d/CCRenderTexture.h +++ b/cocos/2d/CCRenderTexture.h @@ -97,6 +97,7 @@ public: * @param g Green. * @param b Blue. * @param a Alpha. + * @param depthValue The depth Value. */ virtual void beginWithClear(float r, float g, float b, float a, float depthValue); @@ -129,13 +130,13 @@ public: /** Clears the texture with a specified depth value. * - * @param A specified depth value. + * @param depthValue A specified depth value. */ virtual void clearDepth(float depthValue); /** Clears the texture with a specified stencil value. * - * @param A specified stencil value. + * @param stencilValue A specified stencil value. */ virtual void clearStencil(int stencilValue); @@ -256,7 +257,7 @@ public: /** Sets the Sprite being used. * - * @param A Sprite. + * @param sprite A Sprite. */ inline void setSprite(Sprite* sprite) { CC_SAFE_RETAIN(sprite); diff --git a/cocos/2d/CCSprite.h b/cocos/2d/CCSprite.h index 855580f1d6..e07ec02b49 100644 --- a/cocos/2d/CCSprite.h +++ b/cocos/2d/CCSprite.h @@ -443,7 +443,7 @@ CC_CONSTRUCTOR_ACCESS: * * @param texture A pointer to an existing Texture2D object. * You can use a Texture2D object for many sprites. - * @return true if the sprite is initialized properly, false otherwise. + * @return True if the sprite is initialized properly, false otherwise. */ virtual bool initWithTexture(Texture2D *texture); @@ -455,7 +455,7 @@ CC_CONSTRUCTOR_ACCESS: * @param texture A pointer to an exisiting Texture2D object. * You can use a Texture2D object for many sprites. * @param rect Only the contents inside rect of this texture will be applied for this sprite. - * @return true if the sprite is initialized properly, false otherwise. + * @return True if the sprite is initialized properly, false otherwise. */ virtual bool initWithTexture(Texture2D *texture, const Rect& rect); @@ -468,15 +468,15 @@ CC_CONSTRUCTOR_ACCESS: * @param texture A Texture2D object whose texture will be applied to this sprite. * @param rect A rectangle assigned the contents of texture. * @param rotated Whether or not the texture rectangle is rotated. - * @return true if the sprite is initialized properly, false otherwise. + * @return True if the sprite is initialized properly, false otherwise. */ virtual bool initWithTexture(Texture2D *texture, const Rect& rect, bool rotated); /** * Initializes a sprite with an SpriteFrame. The texture and rect in SpriteFrame will be applied on this sprite. * - * @param pSpriteFrame A SpriteFrame object. It should includes a valid texture and a rect. - * @return true if the sprite is initialized properly, false otherwise. + * @param spriteFrame A SpriteFrame object. It should includes a valid texture and a rect. + * @return True if the sprite is initialized properly, false otherwise. */ virtual bool initWithSpriteFrame(SpriteFrame *spriteFrame); @@ -487,7 +487,7 @@ CC_CONSTRUCTOR_ACCESS: * If the SpriteFrame doesn't exist it will raise an exception. * * @param spriteFrameName A key string that can fected a volid SpriteFrame from SpriteFrameCache. - * @return true if the sprite is initialized properly, false otherwise. + * @return True if the sprite is initialized properly, false otherwise. */ virtual bool initWithSpriteFrameName(const std::string& spriteFrameName); @@ -499,7 +499,7 @@ CC_CONSTRUCTOR_ACCESS: * After initialization, the rect used will be the size of the image. The offset will be (0,0). * * @param filename The path to an image file in local file system. - * @return true if the sprite is initialized properly, false otherwise. + * @return True if the sprite is initialized properly, false otherwise. * @js init * @lua init */ @@ -514,7 +514,7 @@ CC_CONSTRUCTOR_ACCESS: * * @param filename The path to an image file in local file system. * @param rect The rectangle assigned the content area from texture. - * @return true if the sprite is initialized properly, false otherwise. + * @return True if the sprite is initialized properly, false otherwise. * @js init * @lua init */ diff --git a/cocos/2d/CCTMXLayer.h b/cocos/2d/CCTMXLayer.h index 32a7b3a7b4..2ed28ab51c 100644 --- a/cocos/2d/CCTMXLayer.h +++ b/cocos/2d/CCTMXLayer.h @@ -226,7 +226,7 @@ public: /** Set tileset information for the layer. * - * @param The tileset information for the layer. + * @param info The tileset information for the layer. */ inline void setTileSet(TMXTilesetInfo* info) { CC_SAFE_RETAIN(info); diff --git a/cocos/2d/CCTMXObjectGroup.h b/cocos/2d/CCTMXObjectGroup.h index b77580b85c..5e5fa3e102 100644 --- a/cocos/2d/CCTMXObjectGroup.h +++ b/cocos/2d/CCTMXObjectGroup.h @@ -63,7 +63,7 @@ public: /** Set the group name. * - * @param groupname A string,it is used to set the group name. + * @param groupName A string,it is used to set the group name. */ inline void setGroupName(const std::string& groupName){ _groupName = groupName; } diff --git a/cocos/2d/CCTMXTiledMap.h b/cocos/2d/CCTMXTiledMap.h index 8bb8d858fb..92ba1828de 100644 --- a/cocos/2d/CCTMXTiledMap.h +++ b/cocos/2d/CCTMXTiledMap.h @@ -201,7 +201,7 @@ public: /** Set the tiles's size property measured in pixels. * - * @param The tiles's size property measured in pixels. + * @param tileSize The tiles's size property measured in pixels. */ inline void setTileSize(const Size& tileSize) { _tileSize = tileSize; }; diff --git a/cocos/base/CCNS.h b/cocos/base/CCNS.h index 8272ddb481..cacd940f65 100644 --- a/cocos/base/CCNS.h +++ b/cocos/base/CCNS.h @@ -37,7 +37,7 @@ NS_CC_BEGIN /** * @brief Returns a Core Graphics rectangle structure corresponding to the data in a given string. - * @param pszContent A string object whose contents are of the form "{{x,y},{w, h}}", + * @param str A string object whose contents are of the form "{{x,y},{w, h}}", * where x is the x coordinate, y is the y coordinate, w is the width, and h is the height. * These components can represent integer or float values. * An example of a valid string is "{{3,2},{4,5}}". @@ -49,7 +49,7 @@ Rect CC_DLL RectFromString(const std::string& str); /** * @brief Returns a Core Graphics point structure corresponding to the data in a given string. - * @param pszContent A string object whose contents are of the form "{x,y}", + * @param str A string object whose contents are of the form "{x,y}", * where x is the x coordinate and y is the y coordinate. * The x and y values can represent integer or float values. * An example of a valid string is "{3.0,2.5}". @@ -61,7 +61,7 @@ Vec2 CC_DLL PointFromString(const std::string& str); /** * @brief Returns a Core Graphics size structure corresponding to the data in a given string. - * @param pszContent A string object whose contents are of the form "{w, h}", + * @param str A string object whose contents are of the form "{w, h}", * where w is the width and h is the height. * The w and h values can be integer or float values. * An example of a valid string is "{3.0,2.5}". diff --git a/cocos/base/ccConfig.h b/cocos/base/ccConfig.h index 88082b823c..292fdcff92 100644 --- a/cocos/base/ccConfig.h +++ b/cocos/base/ccConfig.h @@ -90,7 +90,7 @@ THE SOFTWARE. #define CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL 0 #endif -/** @def CC_DIRECTOR_FPS_INTERVAL +/** @def CC_DIRECTOR_STATS_INTERVAL * Seconds between FPS updates. * 0.5 seconds, means that the FPS number will be updated every 0.5 seconds. * Having a bigger number means a more reliable FPS. @@ -284,7 +284,7 @@ THE SOFTWARE. /** @def CC_CONSTRUCTOR_ACCESS * Indicate the init functions access modifier. If value equals to protected, then these functions are protected. - * If value equals to public, these functions are public + * If value equals to public, these functions are public, * protected by default. */ #ifndef CC_CONSTRUCTOR_ACCESS diff --git a/cocos/platform/CCGLView.h b/cocos/platform/CCGLView.h index 480a9cbb40..826a04740a 100644 --- a/cocos/platform/CCGLView.h +++ b/cocos/platform/CCGLView.h @@ -70,7 +70,10 @@ enum class ResolutionPolicy UNKNOWN, }; -/** @struct GLContextAttrs Have six opengl Context Attrs. */ +/** @struct GLContextAttrs + * + * There are six opengl Context Attrs. + */ struct GLContextAttrs { int redBits;