diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj b/build/cocos2d_libs.xcodeproj/project.pbxproj index 592a58106b..8216151edb 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj @@ -1749,6 +1749,14 @@ 50ED2BE519BEAF7900A0AB90 /* UIEditBoxImpl-win32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50ED2BDE19BEAF7900A0AB90 /* UIEditBoxImpl-win32.cpp */; }; 50ED2BE619BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50ED2BDF19BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp */; }; 50ED2BE719BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 50ED2BDF19BEAF7900A0AB90 /* UIEditBoxImpl-wp8.cpp */; }; + 5E9F61261A3FFE3D0038DE01 /* CCFrustum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */; }; + 5E9F61271A3FFE3D0038DE01 /* CCFrustum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */; }; + 5E9F61281A3FFE3D0038DE01 /* CCFrustum.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */; }; + 5E9F61291A3FFE3D0038DE01 /* CCFrustum.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */; }; + 5E9F612A1A3FFE3D0038DE01 /* CCPlane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E9F61241A3FFE3D0038DE01 /* CCPlane.cpp */; }; + 5E9F612B1A3FFE3D0038DE01 /* CCPlane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E9F61241A3FFE3D0038DE01 /* CCPlane.cpp */; }; + 5E9F612C1A3FFE3D0038DE01 /* CCPlane.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E9F61251A3FFE3D0038DE01 /* CCPlane.h */; }; + 5E9F612D1A3FFE3D0038DE01 /* CCPlane.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E9F61251A3FFE3D0038DE01 /* CCPlane.h */; }; A07A4CAF1783777C0073F6A7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1551A342158F2AB200E66CFE /* Foundation.framework */; }; B2165EEA19921124000BE3E6 /* CCPrimitiveCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B257B45E198A353E00D9A687 /* CCPrimitiveCommand.cpp */; }; B217703C1977ECB4009EE11B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B217703B1977ECB4009EE11B /* IOKit.framework */; }; @@ -2921,6 +2929,10 @@ 50FCEB9018C72017004AD434 /* WidgetReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WidgetReader.cpp; sourceTree = ""; }; 50FCEB9118C72017004AD434 /* WidgetReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WidgetReader.h; sourceTree = ""; }; 50FCEB9218C72017004AD434 /* WidgetReaderProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WidgetReaderProtocol.h; sourceTree = ""; }; + 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCFrustum.cpp; sourceTree = ""; }; + 5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFrustum.h; sourceTree = ""; }; + 5E9F61241A3FFE3D0038DE01 /* CCPlane.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CCPlane.cpp; sourceTree = ""; }; + 5E9F61251A3FFE3D0038DE01 /* CCPlane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCPlane.h; sourceTree = ""; }; A07A4D641783777C0073F6A7 /* libcocos2d iOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libcocos2d iOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B217703B1977ECB4009EE11B /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; B217703D1977ECC1009EE11B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; @@ -5160,6 +5172,10 @@ B29594B81926D61F003EEF37 /* 3d */ = { isa = PBXGroup; children = ( + 5E9F61221A3FFE3D0038DE01 /* CCFrustum.cpp */, + 5E9F61231A3FFE3D0038DE01 /* CCFrustum.h */, + 5E9F61241A3FFE3D0038DE01 /* CCPlane.cpp */, + 5E9F61251A3FFE3D0038DE01 /* CCPlane.h */, B60C5BD219AC68B10056FBDE /* CCBillBoard.cpp */, B60C5BD319AC68B10056FBDE /* CCBillBoard.h */, 15AE17E419AAD2F700C27E9E /* CCAABB.cpp */, @@ -5392,6 +5408,7 @@ 5034CA47191D591100CE6051 /* ccShader_Label_normal.frag in Headers */, 15AE182219AAD2F700C27E9E /* CCBundleReader.h in Headers */, 15AE18A519AAD33D00C27E9E /* CCScale9SpriteLoader.h in Headers */, + 5E9F61281A3FFE3D0038DE01 /* CCFrustum.h in Headers */, 50ED2BE019BEAF7900A0AB90 /* UIEditBoxImpl-win32.h in Headers */, 15AE197119AAD35700C27E9E /* CCFrame.h in Headers */, 15AE1A6519AAD40300C27E9E /* b2TimeStep.h in Headers */, @@ -5676,6 +5693,7 @@ 50ABBFFD1926664800A911A9 /* CCFileUtils-apple.h in Headers */, 15B3708219EE414C00ABE682 /* CCEventListenerAssetsManagerEx.h in Headers */, 15B3708619EE414C00ABE682 /* Downloader.h in Headers */, + 5E9F612C1A3FFE3D0038DE01 /* CCPlane.h in Headers */, 5034CA41191D591100CE6051 /* ccShader_Position_uColor.frag in Headers */, 50ABBE7F1925AB6F00A911A9 /* CCEventTouch.h in Headers */, 50ABBE5B1925AB6F00A911A9 /* CCEventKeyboard.h in Headers */, @@ -5974,6 +5992,7 @@ 15AE182F19AAD2F700C27E9E /* CCMeshVertexIndexData.h in Headers */, 15AE1BAA19AADFDF00C27E9E /* UIVBox.h in Headers */, 3EACC9A719F5014D00EB3C5E /* CCLight.h in Headers */, + 5E9F61291A3FFE3D0038DE01 /* CCFrustum.h in Headers */, 15AE194E19AAD35100C27E9E /* CCDataReaderHelper.h in Headers */, 15AE1ADB19AAD41000C27E9E /* b2Rope.h in Headers */, D0FD03561A3B51AA00825BB5 /* CCAllocatorMacros.h in Headers */, @@ -6258,6 +6277,7 @@ 15AE19AD19AAD39700C27E9E /* LoadingBarReader.h in Headers */, 50ABBE5C1925AB6F00A911A9 /* CCEventKeyboard.h in Headers */, B375107D1823ACA100B3BA6A /* CCPhysicsBodyInfo_chipmunk.h in Headers */, + 5E9F612D1A3FFE3D0038DE01 /* CCPlane.h in Headers */, 50ABC01C1926664800A911A9 /* CCSAXParser.h in Headers */, 503DD8F11926736A00CD74DD /* OpenGL_Internal-ios.h in Headers */, 38ACD1FF1A27111900C3093D /* WidgetCallBackHandlerProtocol.h in Headers */, @@ -6396,6 +6416,7 @@ 15AE189819AAD33D00C27E9E /* CCMenuItemLoader.cpp in Sources */, 15AE1A5719AAD40300C27E9E /* b2Settings.cpp in Sources */, 50ABBE271925AB6F00A911A9 /* CCAutoreleasePool.cpp in Sources */, + 5E9F612A1A3FFE3D0038DE01 /* CCPlane.cpp in Sources */, 15AE197419AAD35700C27E9E /* CCTimeLine.cpp in Sources */, 15AE188E19AAD33D00C27E9E /* CCLabelTTFLoader.cpp in Sources */, 15AE1A3019AAD3D500C27E9E /* b2ChainShape.cpp in Sources */, @@ -6668,6 +6689,7 @@ 15AE196E19AAD35700C27E9E /* CCActionTimelineCache.cpp in Sources */, 50ABBEB31925AB6F00A911A9 /* CCUserDefault-apple.mm in Sources */, 50ABBEB51925AB6F00A911A9 /* CCUserDefault-android.cpp in Sources */, + 5E9F61261A3FFE3D0038DE01 /* CCFrustum.cpp in Sources */, 29394CF619B01DBA00D2DE1A /* UIWebViewImpl-ios.mm in Sources */, 382383FC1A258FA7002C4610 /* idl_gen_text.cpp in Sources */, 50ABBE831925AB6F00A911A9 /* ccFPSImages.c in Sources */, @@ -6968,6 +6990,7 @@ B29A7E0019EE1B7700872B35 /* Json.c in Sources */, 1A570120180BC90D0088DEC7 /* CCGrid.cpp in Sources */, 15AE181119AAD2F700C27E9E /* CCAnimation3D.cpp in Sources */, + 5E9F612B1A3FFE3D0038DE01 /* CCPlane.cpp in Sources */, 1A57019E180BCB590088DEC7 /* CCFont.cpp in Sources */, 15AE1ACC19AAD40300C27E9E /* b2PrismaticJoint.cpp in Sources */, 15AE195F19AAD35100C27E9E /* CCSpriteFrameCacheHelper.cpp in Sources */, @@ -7138,6 +7161,7 @@ 1A57030D180BCF190088DEC7 /* CCComponent.cpp in Sources */, 15AE1B8F19AADA9A00C27E9E /* UIDeprecated.cpp in Sources */, 464AD6E6197EBB1400E502D8 /* pvr.cpp in Sources */, + 5E9F61271A3FFE3D0038DE01 /* CCFrustum.cpp in Sources */, 15AE1B7619AADA9A00C27E9E /* UIPageView.cpp in Sources */, 1A570311180BCF190088DEC7 /* CCComponentContainer.cpp in Sources */, 50ABBE2C1925AB6F00A911A9 /* ccCArray.cpp in Sources */, diff --git a/cocos/2d/CCCamera.cpp b/cocos/2d/CCCamera.cpp index 9bdbc33edc..89baefd956 100644 --- a/cocos/2d/CCCamera.cpp +++ b/cocos/2d/CCCamera.cpp @@ -69,6 +69,8 @@ Camera::Camera() : _scene(nullptr) , _viewProjectionDirty(true) , _cameraFlag(1) +, _frustumDirty(true) +, _enableFrustumCulling(true) { } @@ -96,6 +98,7 @@ const Mat4& Camera::getViewMatrix() const if (memcmp(viewInv.m, _viewInv.m, count) != 0) { _viewProjectionDirty = true; + _frustumDirty = true; _viewInv = viewInv; _view = viewInv.getInversed(); } @@ -205,6 +208,7 @@ bool Camera::initPerspective(float fieldOfView, float aspectRatio, float nearPla } #endif _viewProjectionDirty = true; + _frustumDirty = true; return true; } @@ -225,6 +229,7 @@ bool Camera::initOrthographic(float zoomX, float zoomY, float nearPlane, float f } #endif _viewProjectionDirty = true; + _frustumDirty = true; return true; } @@ -248,6 +253,26 @@ void Camera::unproject(const Size& viewport, Vec3* src, Vec3* dst) const dst->set(screen.x, screen.y, screen.z); } +void Camera::enableFrustumCulling(bool enalbe, bool clipZ) +{ + _enableFrustumCulling = enalbe; + _frustum.setClipZ(clipZ); +} + +bool Camera::isVisibleInFrustum(const AABB* aabb) const +{ + if (_enableFrustumCulling) + { + if (_frustumDirty) + { + _frustum.initFrustum(this); + _frustumDirty = false; + } + return !_frustum.isOutOfFrustum(*aabb); + } + return true; +} + void Camera::onEnter() { if (_scene == nullptr) diff --git a/cocos/2d/CCCamera.h b/cocos/2d/CCCamera.h index c1178cd96b..bd4e73fb15 100644 --- a/cocos/2d/CCCamera.h +++ b/cocos/2d/CCCamera.h @@ -25,6 +25,7 @@ THE SOFTWARE. #define _CCCAMERA_H__ #include "2d/CCNode.h" +#include "3d/CCFrustum.h" NS_CC_BEGIN @@ -135,6 +136,16 @@ public: */ void unproject(const Size& viewport, Vec3* src, Vec3* dst) const; + /** + * Enable frustum culling + */ + void enableFrustumCulling(bool enalbe, bool clipZ); + + /** + * Is this aabb visible in frustum + */ + bool isVisibleInFrustum(const AABB* aabb)const; + //override virtual void onEnter() override; virtual void onExit() override; @@ -171,7 +182,9 @@ protected: float _farPlane; mutable bool _viewProjectionDirty; unsigned short _cameraFlag; // camera flag - + mutable Frustum _frustum; // camera frustum + mutable bool _frustumDirty; + bool _enableFrustumCulling; static Camera* _visitingCamera; friend class Director; diff --git a/cocos/2d/libcocos2d.vcxproj b/cocos/2d/libcocos2d.vcxproj index 395dbfdcf1..5898629f82 100644 --- a/cocos/2d/libcocos2d.vcxproj +++ b/cocos/2d/libcocos2d.vcxproj @@ -228,11 +228,13 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + + @@ -600,11 +602,13 @@ xcopy /Y /Q "$(ProjectDir)..\..\external\chipmunk\prebuilt\win32\release-lib\*.* + + diff --git a/cocos/3d/CCAttachNode.cpp b/cocos/3d/CCAttachNode.cpp index ee53d03d9d..0cb16fca26 100644 --- a/cocos/3d/CCAttachNode.cpp +++ b/cocos/3d/CCAttachNode.cpp @@ -62,6 +62,21 @@ Mat4 AttachNode::getWorldToNodeTransform() const return mat; } +Mat4 AttachNode::getNodeToWorldTransform() const +{ + Mat4 mat; + auto parent = getParent(); + if (parent) + { + mat = parent->getNodeToWorldTransform() * _attachBone->getWorldMat(); + } + else + { + mat = _attachBone->getWorldMat(); + } + return mat; +} + void AttachNode::visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) { Node::visit(renderer, parentTransform * _attachBone->getWorldMat(), Node::FLAGS_DIRTY_MASK); diff --git a/cocos/3d/CCAttachNode.h b/cocos/3d/CCAttachNode.h index f312b6cc7c..6cba23ae8b 100644 --- a/cocos/3d/CCAttachNode.h +++ b/cocos/3d/CCAttachNode.h @@ -49,6 +49,7 @@ public: static AttachNode* create(Bone3D* attachBone); virtual Mat4 getWorldToNodeTransform() const override; + virtual Mat4 getNodeToWorldTransform() const override; virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) override; CC_CONSTRUCTOR_ACCESS: diff --git a/cocos/3d/CCBundle3D.cpp b/cocos/3d/CCBundle3D.cpp index bde5b47a92..4b6f50292b 100644 --- a/cocos/3d/CCBundle3D.cpp +++ b/cocos/3d/CCBundle3D.cpp @@ -260,7 +260,6 @@ bool Bundle3D::loadObj(MeshDatas& meshdatas, MaterialDatas& materialdatas, NodeD } meshdatas.meshDatas.push_back(meshdata); - NMaterialData materialdata; int i = 0; char str[20]; std::string dir = ""; @@ -270,6 +269,8 @@ bool Bundle3D::loadObj(MeshDatas& meshdatas, MaterialDatas& materialdatas, NodeD for (const auto& it : shapes.shapes) { + NMaterialData materialdata; + NTextureData tex; tex.filename = it.material.diffuse_texname.empty() ? it.material.diffuse_texname : dir + it.material.diffuse_texname; tex.type = NTextureData::Usage::Diffuse; diff --git a/cocos/3d/CCFrustum.cpp b/cocos/3d/CCFrustum.cpp new file mode 100755 index 0000000000..ace97e6098 --- /dev/null +++ b/cocos/3d/CCFrustum.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** + 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/CCFrustum.h" +#include "2d/CCCamera.h" + +NS_CC_BEGIN + +bool Frustum::initFrustum(const Camera* camera) +{ + _initialized = true; + createPlane(camera); + return true; +} +bool Frustum::isOutOfFrustum(const AABB& aabb) const +{ + if (_initialized) + { + Vec3 point; + + int plane = _clipZ ? 6 : 4; + for (int i = 0; i < plane; i++) + { + const Vec3& normal = _plane[i].getNormal(); + point.x = normal.x < 0 ? aabb._max.x : aabb._min.x; + point.y = normal.y < 0 ? aabb._max.y : aabb._min.y; + point.z = normal.z < 0 ? aabb._max.z : aabb._min.z; + + if (_plane[i].getSide(point) == PointSide::FRONT_PLANE ) + return true; + } + } + return false; +} + +bool Frustum::isOutOfFrustum(const OBB& obb) const +{ + if (_initialized) + { + Vec3 point; + int plane = _clipZ ? 6 : 4; + Vec3 obbExtentX = obb._xAxis * obb._extents.x; + Vec3 obbExtentY = obb._yAxis * obb._extents.y; + Vec3 obbExtentZ = obb._zAxis * obb._extents.z; + + for (int i = 0; i < plane; i++) + { + const Vec3& normal = _plane[i].getNormal(); + point = obb._center; + point = normal.dot(obb._xAxis) > 0 ? point - obbExtentX : point + obbExtentX; + point = normal.dot(obb._yAxis) > 0 ? point - obbExtentY : point + obbExtentY; + point = normal.dot(obb._zAxis) > 0 ? point - obbExtentZ : point + obbExtentZ; + + if (_plane[i].getSide(point) == PointSide::FRONT_PLANE) + return true; + } + } + return false; +} + +void Frustum::createPlane(const Camera* camera) +{ + const Mat4& mat = camera->getViewProjectionMatrix(); + //ref http://www.lighthouse3d.com/tutorials/view-frustum-culling/clip-space-approach-extracting-the-planes/ + //extract frustum plane + _plane[0].initPlane(-Vec3(mat.m[3] + mat.m[0], mat.m[7] + mat.m[4], mat.m[11] + mat.m[8]), (mat.m[15] + mat.m[12]));//left + _plane[1].initPlane(-Vec3(mat.m[3] - mat.m[0], mat.m[7] - mat.m[4], mat.m[11] - mat.m[8]), (mat.m[15] - mat.m[12]));//right + _plane[2].initPlane(-Vec3(mat.m[3] + mat.m[1], mat.m[7] + mat.m[5], mat.m[11] + mat.m[9]), (mat.m[15] + mat.m[13]));//bottom + _plane[3].initPlane(-Vec3(mat.m[3] - mat.m[1], mat.m[7] - mat.m[5], mat.m[11] - mat.m[9]), (mat.m[15] - mat.m[13]));//top + _plane[4].initPlane(-Vec3(mat.m[3] + mat.m[2], mat.m[7] + mat.m[6], mat.m[11] + mat.m[10]), (mat.m[15] + mat.m[14]));//near + _plane[5].initPlane(-Vec3(mat.m[3] - mat.m[2], mat.m[7] - mat.m[6], mat.m[11] - mat.m[10]), (mat.m[15] - mat.m[14]));//far +} + +NS_CC_END diff --git a/cocos/3d/CCFrustum.h b/cocos/3d/CCFrustum.h new file mode 100755 index 0000000000..86638342b1 --- /dev/null +++ b/cocos/3d/CCFrustum.h @@ -0,0 +1,80 @@ +/**************************************************************************** + 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 __CC_FRUSTUM_H_ +#define __CC_FRUSTUM_H_ + +#include "base/ccMacros.h" +#include "math/CCMath.h" +#include "3d/CCAABB.h" +#include "3d/CCOBB.h" +#include "3d/CCPlane.h" + +NS_CC_BEGIN + +class Camera; +class CC_DLL Frustum +{ + friend class Camera; +public: + /** + * Constructor & Destructor. + */ + Frustum(): _initialized(false), _clipZ(true){} + ~Frustum(){} + + /** + * init frustum from camera. + */ + bool initFrustum(const Camera* camera); + + /** + * is aabb out of frustum. + */ + bool isOutOfFrustum(const AABB& aabb) const; + /** + * is obb out of frustum + */ + bool isOutOfFrustum(const OBB& obb) const; + + /** + * get & set z clip. if bclipZ == true use near and far plane + */ + void setClipZ(bool clipZ) { _clipZ = clipZ; } + bool isClipZ() { return _clipZ; } + +protected: + /** + * create clip plane + */ + void createPlane(const Camera* camera); + + Plane _plane[6]; // clip plane, left, right, top, bottom, near, far + bool _clipZ; // use near and far clip plane + bool _initialized; +}; + +NS_CC_END + +#endif//__CC_FRUSTUM_H_ diff --git a/cocos/3d/CCOBB.cpp b/cocos/3d/CCOBB.cpp index 582898657b..826e40d2bf 100755 --- a/cocos/3d/CCOBB.cpp +++ b/cocos/3d/CCOBB.cpp @@ -215,6 +215,8 @@ OBB::OBB(const AABB& aabb) _extents = aabb._max - aabb._min; _extents.scale(0.5f); + + computeExtAxis(); } OBB::OBB(const Vec3* verts, int num) @@ -259,6 +261,8 @@ OBB::OBB(const Vec3* verts, int num) _zAxis.normalize(); _extents = 0.5f * (vecMax - vecMin); + + computeExtAxis(); } bool OBB::containPoint(const Vec3& point) const @@ -296,19 +300,15 @@ void OBB::reset() void OBB::getCorners(Vec3* verts) const { - Vec3 extX = _xAxis * _extents.x; - Vec3 extY = _yAxis * _extents.y; - Vec3 extZ = _zAxis * _extents.z; + verts[0] = _center - _extentX + _extentY + _extentZ; // left top front + verts[1] = _center - _extentX - _extentY + _extentZ; // left bottom front + verts[2] = _center + _extentX - _extentY + _extentZ; // right bottom front + verts[3] = _center + _extentX + _extentY + _extentZ; // right top front - verts[0] = _center - extX + extY + extZ; // left top front - verts[1] = _center - extX - extY + extZ; // left bottom front - verts[2] = _center + extX - extY + extZ; // right bottom front - verts[3] = _center + extX + extY + extZ; // right top front - - verts[4] = _center + extX + extY - extZ; // right top back - verts[5] = _center + extX - extY - extZ; // right bottom back - verts[6] = _center - extX - extY - extZ; // left bottom back - verts[7] = _center - extX + extY - extZ; // left top back + verts[4] = _center + _extentX + _extentY - _extentZ; // right top back + verts[5] = _center + _extentX - _extentY - _extentZ; // right bottom back + verts[6] = _center - _extentX - _extentY - _extentZ; // left bottom back + verts[7] = _center - _extentX + _extentY - _extentZ; // left top back } float OBB::projectPoint(const Vec3& point, const Vec3& axis)const @@ -447,6 +447,8 @@ void OBB::transform(const Mat4& mat) _extents.x *= scale.x; _extents.y *= scale.y; _extents.z *= scale.z; + + computeExtAxis(); } NS_CC_END diff --git a/cocos/3d/CCOBB.h b/cocos/3d/CCOBB.h index 0fd8c1eea1..2065035060 100644 --- a/cocos/3d/CCOBB.h +++ b/cocos/3d/CCOBB.h @@ -84,6 +84,16 @@ public: void transform(const Mat4& mat); protected: + /* + * compute extX, extY, extZ + */ + void computeExtAxis() + { + _extentX = _xAxis * _extents.x; + _extentY = _yAxis * _extents.y; + _extentZ = _zAxis * _extents.z; + } + /* * Project point to the target axis */ @@ -109,6 +119,9 @@ public: Vec3 _xAxis; // x axis of obb, unit vector Vec3 _yAxis; // y axis of obb, unit vecotr Vec3 _zAxis; // z axis of obb, unit vector + Vec3 _extentX; // _xAxis * _extents.x + Vec3 _extentY; // _yAxis * _extents.y + Vec3 _extentZ; // _zAxis * _extents.z Vec3 _extents; // obb length along each axis }; diff --git a/cocos/3d/CCPlane.cpp b/cocos/3d/CCPlane.cpp new file mode 100755 index 0000000000..722ed2e91d --- /dev/null +++ b/cocos/3d/CCPlane.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** + 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 "CCPlane.h" + +NS_CC_BEGIN + +Plane::Plane() +: +_normal(0.f, 0.f, 1.f), +_dist(0.f) +{ + +} + +// create plane from tree point +Plane::Plane(const Vec3& p1, const Vec3& p2, const Vec3& p3) +{ + initPlane(p1, p2, p3); +} + +// create plane from normal and dist +Plane::Plane(const Vec3& normal, float dist) +{ + initPlane(normal, dist); +} + +// create plane from normal and a point on plane +Plane::Plane(const Vec3& normal, const Vec3& point) +{ + initPlane(normal, point); +} + +void Plane::initPlane(const Vec3& p1, const Vec3& p2, const Vec3& p3) +{ + Vec3 p21 = p2 - p1; + Vec3 p32 = p3 - p2; + Vec3::cross(p21, p32, &_normal); + _normal.normalize(); + _dist = _normal.dot(p1); +} + +void Plane::initPlane(const Vec3& normal, float dist) +{ + float oneOverLength = 1 / normal.length(); + _normal = normal * oneOverLength; + _dist = dist * oneOverLength; +} + +void Plane::initPlane(const Vec3& normal, const Vec3& point) +{ + _normal = normal; + _normal.normalize(); + _dist = _normal.dot(point); +} + +float Plane::dist2Plane(const Vec3& p) const +{ + return _normal.dot(p) - _dist; +} + + +PointSide Plane::getSide(const Vec3& point) const +{ + float dist = dist2Plane(point); + if (dist > 0) + return PointSide::FRONT_PLANE; + else if (dist < 0) + return PointSide::BEHIND_PLANE; + else + return PointSide::IN_PLANE; +} + +NS_CC_END diff --git a/cocos/3d/CCPlane.h b/cocos/3d/CCPlane.h new file mode 100755 index 0000000000..ad77ec5bb0 --- /dev/null +++ b/cocos/3d/CCPlane.h @@ -0,0 +1,101 @@ +/**************************************************************************** + 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 __CC_PLANE_H_ +#define __CC_PLANE_H_ + +#include "base/ccMacros.h" +#include "math/CCMath.h" + +NS_CC_BEGIN + +enum class PointSide +{ + IN_PLANE, + FRONT_PLANE, + BEHIND_PLANE, +}; + +class CC_DLL Plane +{ +public: + /** + * create plane from tree point. + */ + Plane(const Vec3& p1, const Vec3& p2, const Vec3& p3); + + /** + * create plane from normal and dist. + */ + Plane(const Vec3& normal, float dist); + + /** + * create plane from normal and a point on plane. + */ + Plane(const Vec3& normal, const Vec3& point); + Plane(); + + /** + * init plane from tree point. + */ + void initPlane(const Vec3& p1, const Vec3& p2, const Vec3& p3); + + /** + * init plane from normal and dist. + */ + void initPlane(const Vec3& normal, float dist); + + /** + * init plane from normal and a point on plane. + */ + void initPlane(const Vec3& normal, const Vec3& point); + + /** + * dist to plane, > 0 normal direction + */ + float dist2Plane(const Vec3& p) const; + + /** + * Gets the plane's normal. + */ + const Vec3& getNormal() const { return _normal; } + + /** + * Gets the plane's distance to the origin along its normal. + */ + float getDist() const { return _dist; } + + /** + * Return the side where the point is. + */ + PointSide getSide(const Vec3& point) const; + +protected: + Vec3 _normal; + float _dist; +}; + +NS_CC_END + +#endif diff --git a/cocos/3d/CCRay.cpp b/cocos/3d/CCRay.cpp index 94189183d1..046901e8ef 100755 --- a/cocos/3d/CCRay.cpp +++ b/cocos/3d/CCRay.cpp @@ -140,10 +140,26 @@ bool Ray::intersects(const OBB& obb) const return ray.intersects(aabb); } +float Ray::dist(const Plane& plane) const +{ + float ndd = Vec3::dot(plane.getNormal(), _direction); + if(ndd == 0) + return 0.0f; + float ndo = Vec3::dot(plane.getNormal(), _origin); + return (plane.getDist() - ndo) / ndd; +} + +Vec3 Ray::intersects(const Plane& plane) const +{ + float dis = this->dist(plane); + return _origin + dis * _direction; +} + void Ray::set(const Vec3& origin, const Vec3& direction) { _origin = origin; _direction = direction; + _direction.normalize(); } void Ray::transform(const Mat4& matrix) diff --git a/cocos/3d/CCRay.h b/cocos/3d/CCRay.h index 417147d56d..150c734071 100644 --- a/cocos/3d/CCRay.h +++ b/cocos/3d/CCRay.h @@ -28,6 +28,7 @@ #include "math/CCMath.h" #include "3d/CCAABB.h" #include "3d/CCOBB.h" +#include "3d/CCPlane.h" NS_CC_BEGIN @@ -67,6 +68,9 @@ public: */ bool intersects(const OBB& obb) const; + float dist(const Plane& plane) const; + Vec3 intersects(const Plane& plane) const; + /** * Sets this ray to the specified values. * diff --git a/cocos/3d/CCSprite3D.cpp b/cocos/3d/CCSprite3D.cpp index 0bb423bfc0..d98ee8e258 100644 --- a/cocos/3d/CCSprite3D.cpp +++ b/cocos/3d/CCSprite3D.cpp @@ -601,6 +601,10 @@ static Texture2D * getDummyTexture() void Sprite3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) { + // camera clipping + if(!Camera::getVisitingCamera()->isVisibleInFrustum(&this->getAABB())) + return; + if (_skeleton) _skeleton->updateBoneMatrix(); diff --git a/cocos/3d/CMakeLists.txt b/cocos/3d/CMakeLists.txt index 0e35a5a63e..3acd5a5254 100644 --- a/cocos/3d/CMakeLists.txt +++ b/cocos/3d/CMakeLists.txt @@ -11,11 +11,13 @@ set(COCOS_3D_SRC 3d/CCAttachNode.cpp 3d/CCBundle3D.cpp 3d/CCBundleReader.cpp + 3d/CCFrustum.cpp 3d/CCMesh.cpp 3d/CCMeshSkin.cpp 3d/CCMeshVertexIndexData.cpp 3d/CCOBB.cpp 3d/CCObjLoader.cpp + 3d/CCPlane.cpp 3d/CCRay.cpp 3d/CCSkeleton3D.cpp 3d/CCSprite3D.cpp diff --git a/cocos/Android.mk b/cocos/Android.mk index f94950c4ca..2cd641e5d6 100644 --- a/cocos/Android.mk +++ b/cocos/Android.mk @@ -77,6 +77,8 @@ cocos2d.cpp \ 2d/CCTransitionPageTurn.cpp \ 2d/CCTransitionProgress.cpp \ 2d/CCTweenFunction.cpp \ +3d/CCFrustum.cpp \ +3d/CCPlane.cpp \ platform/CCGLView.cpp \ platform/CCFileUtils.cpp \ platform/CCSAXParser.cpp \ diff --git a/cocos/cocos2d.h b/cocos/cocos2d.h index bdfabeb043..a8d613c27f 100644 --- a/cocos/cocos2d.h +++ b/cocos/cocos2d.h @@ -283,6 +283,8 @@ THE SOFTWARE. #include "3d/CCMeshVertexIndexData.h" #include "3d/CCSkeleton3D.h" #include "3d/CCBillBoard.h" +#include "3d/CCFrustum.h" +#include "3d/CCPlane.h" // Deprecated include #include "deprecated/CCDictionary.h" diff --git a/cocos/scripting/lua-bindings/auto/api/AttachNode.lua b/cocos/scripting/lua-bindings/auto/api/AttachNode.lua index e61a0d0d48..9ae15250db 100644 --- a/cocos/scripting/lua-bindings/auto/api/AttachNode.lua +++ b/cocos/scripting/lua-bindings/auto/api/AttachNode.lua @@ -12,12 +12,6 @@ -- @param #cc.Bone3D attachBone -- @return AttachNode#AttachNode ret (return value: cc.AttachNode) --------------------------------- --- --- @function [parent=#AttachNode] getWorldToNodeTransform --- @param self --- @return mat4_table#mat4_table ret (return value: mat4_table) - -------------------------------- -- -- @function [parent=#AttachNode] visit @@ -26,4 +20,16 @@ -- @param #mat4_table parentTransform -- @param #unsigned int parentFlags +-------------------------------- +-- +-- @function [parent=#AttachNode] getWorldToNodeTransform +-- @param self +-- @return mat4_table#mat4_table ret (return value: mat4_table) + +-------------------------------- +-- +-- @function [parent=#AttachNode] getNodeToWorldTransform +-- @param self +-- @return mat4_table#mat4_table ret (return value: mat4_table) + return nil diff --git a/cocos/scripting/lua-bindings/auto/api/Camera.lua b/cocos/scripting/lua-bindings/auto/api/Camera.lua index a070acd17e..0826a03728 100644 --- a/cocos/scripting/lua-bindings/auto/api/Camera.lua +++ b/cocos/scripting/lua-bindings/auto/api/Camera.lua @@ -37,6 +37,13 @@ -- @param self -- @return int#int ret (return value: int) +-------------------------------- +-- Enable frustum culling +-- @function [parent=#Camera] enableFrustumCulling +-- @param self +-- @param #bool enalbe +-- @param #bool clipZ + -------------------------------- -- Creates a view matrix based on the specified input parameters.
-- param eyePosition The eye position.
@@ -48,6 +55,13 @@ -- @param #vec3_table target -- @param #vec3_table up +-------------------------------- +-- Is this aabb visible in frustum +-- @function [parent=#Camera] isVisibleInFrustum +-- @param self +-- @param #cc.AABB aabb +-- @return bool#bool ret (return value: bool) + -------------------------------- -- -- @function [parent=#Camera] setCameraFlag diff --git a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp index 0a4f31b5bb..444a4d0f13 100644 --- a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp +++ b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp @@ -27,107 +27,6 @@ THE SOFTWARE. #include #include "../testResource.h" -////////////DrawLine///////////////////// - -class DrawLine3D: public Node -{ -public: - /** creates and initialize a node */ - static DrawLine3D* create(); - - /** - * Draw 3D Line - */ - void drawLine(const Vec3 &from, const Vec3 &to, const Color4F &color); - - /** Clear the geometry in the node's buffer. */ - void clear() - { - _buffer.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: - DrawLine3D() - { - - } - virtual ~DrawLine3D() - { - - } - virtual bool init(); - -protected: - struct V3F_C4B - { - Vec3 vertices; - Color4B colors; - }; - - std::vector _buffer; - - CustomCommand _customCommand; - -private: - CC_DISALLOW_COPY_AND_ASSIGN(DrawLine3D); -}; - -DrawLine3D* DrawLine3D::create() -{ - auto ret = new (std::nothrow) DrawLine3D(); - if (ret && ret->init()) - return ret; - CC_SAFE_DELETE(ret); - return nullptr; -} - -bool DrawLine3D::init() -{ - setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_COLOR)); - return true; -} - -void DrawLine3D::drawLine(const Vec3 &from, const Vec3 &to, const Color4F &color) -{ - Color4B col = Color4B(color); - DrawLine3D::V3F_C4B vertex; - vertex.vertices = from; - vertex.colors = col; - _buffer.push_back(vertex); - vertex.vertices = to; - _buffer.push_back(vertex); -} - -void DrawLine3D::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) -{ - _customCommand.init(_globalZOrder); - _customCommand.func = CC_CALLBACK_0(DrawLine3D::onDraw, this, transform, flags); - renderer->addCommand(&_customCommand); -} - -void DrawLine3D::onDraw(const Mat4 &transform, uint32_t flags) -{ - auto glProgram = getGLProgram(); - glProgram->use(); - glProgram->setUniformsForBuiltins(transform); - glEnable(GL_DEPTH_TEST); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_POSITION); - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(V3F_C4B), &(_buffer[0].vertices)); - - glEnableVertexAttribArray(GLProgram::VERTEX_ATTRIB_COLOR); - glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(V3F_C4B), &(_buffer[0].colors)); - glDrawArrays(GL_LINES, 0, static_cast(_buffer.size())); - glDisable(GL_DEPTH_TEST); -} - -//////////////////////////////////////////////////////////////////////////////// - enum { IDC_NEXT = 100, @@ -140,6 +39,7 @@ static int sceneIdx = -1; static std::function createFunctions[] = { CL(Camera3DTestDemo), + CL(CameraClippingDemo) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) @@ -354,7 +254,7 @@ void Camera3DTestDemo::onEnter() _layer3D->addChild(_camera); } SwitchViewCallback(this,CameraType::ThirdCamera); - DrawLine3D* line =DrawLine3D::create(); + DrawNode3D* line =DrawNode3D::create(); //draw x for( int j =-20; j<=20 ;j++) { @@ -755,6 +655,314 @@ void Camera3DTestDemo::onTouchesRotateRightEnd(Touch* touch, Event* event) { _bRotateRight = false; } + +//////////////////////////////////////////////////////////// +// CameraClippingDemo +CameraClippingDemo::CameraClippingDemo(void) +: BaseTest() +, _layer3D(nullptr) +, _cameraType(CameraType::FirstCamera) +, _cameraFirst(nullptr) +, _cameraThird(nullptr) +, _moveAction(nullptr) +, _drawAABB(nullptr) +, _drawFrustum(nullptr) +, _row(3) +{ +} +CameraClippingDemo::~CameraClippingDemo(void) +{ +} + +std::string CameraClippingDemo::title() const +{ + return "Camera Frustum Clipping"; +} + +void CameraClippingDemo::restartCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild(restartSpriteTestAction()); + + Director::getInstance()->replaceScene(s); + s->release(); +} + +void CameraClippingDemo::nextCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild( nextSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); +} + +void CameraClippingDemo::backCallback(Ref* sender) +{ + auto s = new (std::nothrow) Camera3DTestScene(); + s->addChild( backSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); +} + +void CameraClippingDemo::onEnter() +{ + BaseTest::onEnter(); + schedule(schedule_selector(CameraClippingDemo::update), 0.0f); + + auto s = Director::getInstance()->getWinSize(); + auto listener = EventListenerTouchAllAtOnce::create(); + listener->onTouchesBegan = CC_CALLBACK_2(CameraClippingDemo::onTouchesBegan, this); + listener->onTouchesMoved = CC_CALLBACK_2(CameraClippingDemo::onTouchesMoved, this); + listener->onTouchesEnded = CC_CALLBACK_2(CameraClippingDemo::onTouchesEnded, this); + _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); + auto layer3D=Layer::create(); + addChild(layer3D,0); + _layer3D=layer3D; + + // swich camera + MenuItemFont::setFontName("fonts/arial.ttf"); + MenuItemFont::setFontSize(20); + + auto menuItem1 = MenuItemFont::create("Switch Camera", CC_CALLBACK_1(CameraClippingDemo::switchViewCallback,this)); + menuItem1->setColor(Color3B(0,200,20)); + auto menu = Menu::create(menuItem1,NULL); + menu->setPosition(Vec2::ZERO); + menuItem1->setPosition(VisibleRect::left().x + 80, VisibleRect::top().y -70); + addChild(menu, 1); + + // + - + MenuItemFont::setFontSize(40); + auto decrease = MenuItemFont::create(" - ", CC_CALLBACK_1(CameraClippingDemo::delSpriteCallback, this)); + decrease->setColor(Color3B(0,200,20)); + auto increase = MenuItemFont::create(" + ", CC_CALLBACK_1(CameraClippingDemo::addSpriteCallback, this)); + increase->setColor(Color3B(0,200,20)); + + menu = Menu::create(decrease, increase, nullptr); + menu->alignItemsHorizontally(); + menu->setPosition(Vec2(s.width - 60, VisibleRect::top().y -70)); + addChild(menu, 1); + + TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); + _labelSprite3DCount = Label::createWithTTF(ttfCount,"0 sprits"); + _labelSprite3DCount->setColor(Color3B(0,200,20)); + _labelSprite3DCount->setPosition(Vec2(s.width/2, VisibleRect::top().y -70)); + addChild(_labelSprite3DCount); + + // aabb drawNode3D + _drawAABB = DrawNode3D::create(); + _drawAABB->setCameraMask((unsigned short) CameraFlag::USER1); + addChild(_drawAABB); + + // frustum drawNode3D + _drawFrustum = DrawNode3D::create(); + _drawFrustum->setCameraMask((unsigned short) CameraFlag::USER1); + addChild(_drawFrustum); + + // set camera + switchViewCallback(this); + + // add sprite + addSpriteCallback(nullptr); +} + +void CameraClippingDemo::onExit() +{ + BaseTest::onExit(); + if (_cameraFirst) + { + _cameraFirst = nullptr; + } + if (_cameraThird) + { + _cameraThird = nullptr; + } +} + +void CameraClippingDemo::update(float dt) +{ + _drawAABB->clear(); + + if(_cameraType == CameraType::ThirdCamera) + drawCameraFrustum(); + + Vector& children = _layer3D->getChildren(); + Vec3 corners[8]; + + for (const auto& iter: children) + { + const AABB& aabb = static_cast(iter)->getAABB(); + if (_cameraFirst->isVisibleInFrustum(&aabb)) + { + aabb.getCorners(corners); + _drawAABB->drawCube(corners, Color4F(0, 1, 0, 1)); + } + } +} + +void CameraClippingDemo::reachEndCallBack() +{ + _cameraFirst->stopActionByTag(100); + auto inverse = (MoveTo*)_moveAction->reverse(); + inverse->retain(); + _moveAction->release(); + _moveAction = inverse; + auto rot = RotateBy::create(1.f, Vec3(0.f, 180.f, 0.f)); + auto seq = Sequence::create(rot, _moveAction, CallFunc::create(CC_CALLBACK_0(CameraClippingDemo::reachEndCallBack, this)), nullptr); + seq->setTag(100); + _cameraFirst->runAction(seq); +} + +void CameraClippingDemo::switchViewCallback(Ref* sender) +{ + auto s = Director::getInstance()->getWinSize(); + + if (_cameraFirst == nullptr) + { + _cameraFirst = Camera::createPerspective(30, (GLfloat)s.width/s.height, 10, 200); + _cameraFirst->setCameraFlag(CameraFlag::USER8); + _cameraFirst->setPosition3D(Vec3(-100,0,0)); + _cameraFirst->lookAt(Vec3(1000,0,0), Vec3(0, 1, 0)); + _moveAction = MoveTo::create(4.f, Vec2(100, 0)); + _moveAction->retain(); + auto seq = Sequence::create(_moveAction, CallFunc::create(CC_CALLBACK_0(CameraClippingDemo::reachEndCallBack, this)), nullptr); + seq->setTag(100); + _cameraFirst->runAction(seq); + addChild(_cameraFirst); + } + + if (_cameraThird == nullptr) + { + _cameraThird = Camera::createPerspective(60, (GLfloat)s.width/s.height, 1, 1000); + _cameraThird->setCameraFlag(CameraFlag::USER8); + _cameraThird->setPosition3D(Vec3(0, 130, 130)); + _cameraThird->lookAt(Vec3(0,0,0), Vec3(0, 1, 0)); + addChild(_cameraThird); + } + + if(_cameraType == CameraType::FirstCamera) + { + _cameraType = CameraType::ThirdCamera; + _cameraThird->setCameraFlag(CameraFlag::USER1); + _cameraThird->enableFrustumCulling(false, false); + _cameraFirst->setCameraFlag(CameraFlag::USER8); + } + else if(_cameraType == CameraType::ThirdCamera) + { + _cameraType = CameraType::FirstCamera; + _cameraFirst->setCameraFlag(CameraFlag::USER1); + _cameraFirst->enableFrustumCulling(true, true); + _cameraThird->setCameraFlag(CameraFlag::USER8); + _drawFrustum->clear(); + } +} + +void CameraClippingDemo::addSpriteCallback(Ref* sender) +{ + _layer3D->removeAllChildren(); + _objects.clear(); + _drawAABB->clear(); + + ++_row; + for (int x = -_row; x < _row; x++) + { + for (int z = -_row; z < _row; z++) + { + auto sprite = Sprite3D::create("Sprite3DTest/orc.c3b"); + sprite->setPosition3D(Vec3(x * 30, 0, z * 30)); + sprite->setRotation3D(Vec3(0,180,0)); + _objects.push_back(sprite); + _layer3D->addChild(sprite); + } + } + + // set layer mask. + _layer3D->setCameraMask( (unsigned short) CameraFlag::USER1); + + // update sprite number + char szText[16]; + sprintf(szText,"%ld sprits",_layer3D->getChildrenCount()); + _labelSprite3DCount->setString(szText); +} + +void CameraClippingDemo::delSpriteCallback(Ref* sender) +{ + if (_row == 0) return; + + _layer3D->removeAllChildren(); + _objects.clear(); + + --_row; + for (int x = -_row; x < _row; x++) + { + for (int z = -_row; z < _row; z++) + { + auto sprite = Sprite3D::create("Sprite3DTest/orc.c3b"); + sprite->setPosition3D(Vec3(x * 30, 0, z * 30)); + _objects.push_back(sprite); + _layer3D->addChild(sprite); + } + } + + // set layer mask. + _layer3D->setCameraMask((unsigned short) CameraFlag::USER1); + + // update sprite number + char szText[16]; + sprintf(szText,"%ld sprits",_layer3D->getChildrenCount()); + _labelSprite3DCount->setString(szText); +} + +void CameraClippingDemo::drawCameraFrustum() +{ + _drawFrustum->clear(); + auto size = Director::getInstance()->getWinSize(); + + Color4F color(1.f, 1.f, 0.f, 1); + + // top-left + Vec3 tl_0,tl_1; + Vec3 src(0,0,0); + _cameraFirst->unproject(size, &src, &tl_0); + src = Vec3(0,0,1); + _cameraFirst->unproject(size, &src, &tl_1); + + // top-right + Vec3 tr_0,tr_1; + src = Vec3(size.width,0,0); + _cameraFirst->unproject(size, &src, &tr_0); + src = Vec3(size.width,0,1); + _cameraFirst->unproject(size, &src, &tr_1); + + // bottom-left + Vec3 bl_0,bl_1; + src = Vec3(0,size.height,0); + _cameraFirst->unproject(size, &src, &bl_0); + src = Vec3(0,size.height,1); + _cameraFirst->unproject(size, &src, &bl_1); + + // bottom-right + Vec3 br_0,br_1; + src = Vec3(size.width,size.height,0); + _cameraFirst->unproject(size, &src, &br_0); + src = Vec3(size.width,size.height,1); + _cameraFirst->unproject(size, &src, &br_1); + + _drawFrustum->drawLine(tl_0, tl_1, color); + _drawFrustum->drawLine(tr_0, tr_1, color); + _drawFrustum->drawLine(bl_0, bl_1, color); + _drawFrustum->drawLine(br_0, br_1, color); + + _drawFrustum->drawLine(tl_0, tr_0, color); + _drawFrustum->drawLine(tr_0, br_0, color); + _drawFrustum->drawLine(br_0, bl_0, color); + _drawFrustum->drawLine(bl_0, tl_0, color); + + _drawFrustum->drawLine(tl_1, tr_1, color); + _drawFrustum->drawLine(tr_1, br_1, color); + _drawFrustum->drawLine(br_1, bl_1, color); + _drawFrustum->drawLine(bl_1, tl_1, color); +} + void Camera3DTestScene::runThisTest() { auto layer = nextSpriteTestAction(); diff --git a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h index 9d24a0fdb7..21eb61a872 100644 --- a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h +++ b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.h @@ -27,11 +27,14 @@ THE SOFTWARE. #include "../testBasic.h" #include "../BaseTest.h" +#include "../Sprite3DTest/DrawNode3D.h" #include + namespace cocos2d { class Sprite3D; class Delay; } + enum State { State_None = 0, @@ -106,6 +109,45 @@ protected: Label* _ZoomInlabel; Label* _ZoomOutlabel; }; + +class CameraClippingDemo : public BaseTest +{ +public: + CREATE_FUNC(CameraClippingDemo); + CameraClippingDemo(void); + virtual ~CameraClippingDemo(void); + + void restartCallback(Ref* sender); + void nextCallback(Ref* sender); + void backCallback(Ref* sender); + + virtual void onEnter() override; + virtual void onExit() override; + + virtual void update(float dt) override; + + // overrides + virtual std::string title() const override; + void reachEndCallBack(); + void switchViewCallback(Ref* sender); + void addSpriteCallback(Ref* sender); + void delSpriteCallback(Ref* sender); + + void drawCameraFrustum(); + +protected: + Label* _labelSprite3DCount; + Layer* _layer3D; + std::vector _objects; + CameraType _cameraType; + Camera* _cameraFirst; + Camera* _cameraThird; + MoveBy* _moveAction; + DrawNode3D* _drawAABB; + DrawNode3D* _drawFrustum; + int _row; +}; + class Camera3DTestScene : public TestScene { public: