diff --git a/KREngine/KREngine.xcodeproj/project.pbxproj b/KREngine/KREngine.xcodeproj/project.pbxproj index d1c7fa2..f32a9a1 100644 --- a/KREngine/KREngine.xcodeproj/project.pbxproj +++ b/KREngine/KREngine.xcodeproj/project.pbxproj @@ -96,6 +96,10 @@ E491019D13C99BDC0098455B /* KRTextureManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E491018513C99BDC0098455B /* KRTextureManager.h */; settings = {ATTRIBUTES = (); }; }; E491019E13C99BDC0098455B /* KRTexture.h in Headers */ = {isa = PBXBuildFile; fileRef = E491018613C99BDC0098455B /* KRTexture.h */; settings = {ATTRIBUTES = (); }; }; E49101A013C99BF50098455B /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E491019F13C99BF50098455B /* OpenGLES.framework */; }; + E4924C2615EE95E800B965C6 /* KROctree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4924C2415EE95E700B965C6 /* KROctree.cpp */; }; + E4924C2715EE95E800B965C6 /* KROctree.h in Headers */ = {isa = PBXBuildFile; fileRef = E4924C2515EE95E800B965C6 /* KROctree.h */; }; + E4924C2B15EE96AB00B965C6 /* KROctreeNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4924C2915EE96AA00B965C6 /* KROctreeNode.cpp */; }; + E4924C2C15EE96AB00B965C6 /* KROctreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = E4924C2A15EE96AA00B965C6 /* KROctreeNode.h */; }; E497B946151BA99500D3DC67 /* KRVector2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E497B945151BA99400D3DC67 /* KRVector2.cpp */; }; E497B947151BA99500D3DC67 /* KRVector2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E497B945151BA99400D3DC67 /* KRVector2.cpp */; }; E497B948151BB89D00D3DC67 /* KRVector2.h in Headers */ = {isa = PBXBuildFile; fileRef = E497B943151BA93400D3DC67 /* KRVector2.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -234,6 +238,10 @@ E491018513C99BDC0098455B /* KRTextureManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRTextureManager.h; path = Classes/KRTextureManager.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; E491018613C99BDC0098455B /* KRTexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRTexture.h; path = Classes/KRTexture.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; E491019F13C99BF50098455B /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + E4924C2415EE95E700B965C6 /* KROctree.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KROctree.cpp; path = Classes/KROctree.cpp; sourceTree = ""; }; + E4924C2515EE95E800B965C6 /* KROctree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KROctree.h; path = Classes/KROctree.h; sourceTree = ""; }; + E4924C2915EE96AA00B965C6 /* KROctreeNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KROctreeNode.cpp; path = Classes/KROctreeNode.cpp; sourceTree = ""; }; + E4924C2A15EE96AA00B965C6 /* KROctreeNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KROctreeNode.h; path = Classes/KROctreeNode.h; sourceTree = ""; }; E497B943151BA93400D3DC67 /* KRVector2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = KRVector2.h; path = Classes/KRVector2.h; sourceTree = ""; }; E497B945151BA99400D3DC67 /* KRVector2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRVector2.cpp; path = Classes/KRVector2.cpp; sourceTree = ""; }; E497B949151BCEE900D3DC67 /* KRResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRResource.h; path = Classes/KRResource.h; sourceTree = ""; }; @@ -437,6 +445,10 @@ E45772E313C99F160037BEEA /* Shaders */, E491016E13C99BAE0098455B /* Classes */, E491016713C99B9E0098455B /* Supporting Files */, + E4924C2415EE95E700B965C6 /* KROctree.cpp */, + E4924C2515EE95E800B965C6 /* KROctree.h */, + E4924C2915EE96AA00B965C6 /* KROctreeNode.cpp */, + E4924C2A15EE96AA00B965C6 /* KROctreeNode.h */, ); path = KREngine; sourceTree = ""; @@ -568,6 +580,8 @@ E42CB1EC158446940066E0D8 /* KRQuaternion.h in Headers */, E43B0ACB15DDBB8500A5CB9F /* KRNotified.h in Headers */, E43B0AD815DDCA0F00A5CB9F /* KRContextObject.h in Headers */, + E4924C2715EE95E800B965C6 /* KROctree.h in Headers */, + E4924C2C15EE96AB00B965C6 /* KROctreeNode.h in Headers */, 1000469E15E6EF550053B072 /* KRSkyBox.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -727,6 +741,8 @@ E42CB1F0158446AB0066E0D8 /* KRQuaternion.cpp in Sources */, E43B0AC915DDBB8500A5CB9F /* KRNotified.cpp in Sources */, E43B0AD615DDCA0F00A5CB9F /* KRContextObject.cpp in Sources */, + E4924C2615EE95E800B965C6 /* KROctree.cpp in Sources */, + E4924C2B15EE96AB00B965C6 /* KROctreeNode.cpp in Sources */, 1000469D15E6EF550053B072 /* KRSkyBox.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/KREngine/KREngine/Classes/KRContext.cpp b/KREngine/KREngine/Classes/KRContext.cpp index 0cb3876..9c18f4c 100644 --- a/KREngine/KREngine/Classes/KRContext.cpp +++ b/KREngine/KREngine/Classes/KRContext.cpp @@ -83,40 +83,4 @@ void KRContext::loadResource(std::string path) { } else { fprintf(stderr, "KRContext::loadResource - Unknown resource file type: %s\n", path.c_str()); } -} - -void KRContext::registerNotified(KRNotified *pNotified) -{ - m_notifiedObjects.insert(pNotified); - for(std::set::iterator itr=m_allNodes.begin(); itr != m_allNodes.end(); itr++) { - pNotified->notify_sceneGraphCreate(*itr); - } -} - -void KRContext::unregisterNotified(KRNotified *pNotified) -{ - m_notifiedObjects.erase(pNotified); -} - -void KRContext::notify_sceneGraphCreate(KRNode *pNode) -{ - m_allNodes.insert(pNode); - for(std::set::iterator itr = m_notifiedObjects.begin(); itr != m_notifiedObjects.end(); itr++) { - (*itr)->notify_sceneGraphCreate(pNode); - } -} - -void KRContext::notify_sceneGraphDelete(KRNode *pNode) -{ - for(std::set::iterator itr = m_notifiedObjects.begin(); itr != m_notifiedObjects.end(); itr++) { - (*itr)->notify_sceneGraphDelete(pNode); - } - m_allNodes.erase(pNode); -} - -void KRContext::notify_sceneGraphModify(KRNode *pNode) -{ - for(std::set::iterator itr = m_notifiedObjects.begin(); itr != m_notifiedObjects.end(); itr++) { - (*itr)->notify_sceneGraphModify(pNode); - } } \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRContext.h b/KREngine/KREngine/Classes/KRContext.h index 4b29af0..2f6cf21 100644 --- a/KREngine/KREngine/Classes/KRContext.h +++ b/KREngine/KREngine/Classes/KRContext.h @@ -31,22 +31,12 @@ public: KRCamera *createCamera(int width, int height); - void registerNotified(KRNotified *pNotified); - void unregisterNotified(KRNotified *pNotified); - - void notify_sceneGraphCreate(KRNode *pNode); - void notify_sceneGraphDelete(KRNode *pNode); - void notify_sceneGraphModify(KRNode *pNode); - private: KRSceneManager *m_pSceneManager; KRTextureManager *m_pTextureManager; KRMaterialManager *m_pMaterialManager; KRShaderManager *m_pShaderManager; KRModelManager *m_pModelManager; - - std::set m_notifiedObjects; - std::set m_allNodes; }; #endif diff --git a/KREngine/KREngine/Classes/KRDirectionalLight.cpp b/KREngine/KREngine/Classes/KRDirectionalLight.cpp index f660c06..3b41a4a 100644 --- a/KREngine/KREngine/Classes/KRDirectionalLight.cpp +++ b/KREngine/KREngine/Classes/KRDirectionalLight.cpp @@ -13,7 +13,7 @@ #import "KRContext.h" #import "KRMat4.h" -KRDirectionalLight::KRDirectionalLight(KRContext &context, std::string name) : KRLight(context, name) +KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name) { } diff --git a/KREngine/KREngine/Classes/KRDirectionalLight.h b/KREngine/KREngine/Classes/KRDirectionalLight.h index 236c69e..593ac5a 100644 --- a/KREngine/KREngine/Classes/KRDirectionalLight.h +++ b/KREngine/KREngine/Classes/KRDirectionalLight.h @@ -16,7 +16,7 @@ class KRDirectionalLight : public KRLight { public: - KRDirectionalLight(KRContext &context, std::string name); + KRDirectionalLight(KRScene &scene, std::string name); virtual ~KRDirectionalLight(); virtual std::string getElementName(); diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index ab8bc9f..9aceb4f 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -32,9 +32,10 @@ #include #import "KRInstance.h" #import "KRContext.h" +#import "KRMesh.h" #include -KRInstance::KRInstance(KRContext &context, std::string instance_name, std::string model_name, const KRMat4 modelMatrix, std::string light_map) : KRNode(context, instance_name) { +KRInstance::KRInstance(KRScene &scene, std::string instance_name, std::string model_name, const KRMat4 modelMatrix, std::string light_map) : KRNode(scene, instance_name) { m_modelMatrix = modelMatrix; m_lightMap = light_map; m_pLightMap = NULL; @@ -68,9 +69,6 @@ KRMat4 &KRInstance::getModelMatrix() { void KRInstance::loadModel() { if(m_pModel == NULL) { m_pModel = m_pContext->getModelManager()->getModel(m_model_name.c_str()); - if(m_pModel->hasTransparency()) { - m_pContext->notify_sceneGraphModify(this); - } } } @@ -128,7 +126,7 @@ void KRInstance::calcExtents(KRContext *pContext) { KRNode::calcExtents(pContext); loadModel(); KRMesh *pMesh = m_pModel->getMesh(); - KRBoundingVolume mesh_bounds = KRBoundingVolume(KRVector3(pMesh->getMinX(), pMesh->getMinY(), pMesh->getMinZ()), KRVector3(pMesh->getMaxX(), pMesh->getMaxY(), pMesh->getMaxZ()), m_modelMatrix); + KRBoundingVolume mesh_bounds = KRBoundingVolume(pMesh->getMinPoint(), pMesh->getMaxPoint(), m_modelMatrix); if(m_pExtents) { *m_pExtents = m_pExtents->get_union(mesh_bounds); } else { @@ -142,5 +140,14 @@ bool KRInstance::hasTransparency() { } else { return false; } - +} + +KRVector3 KRInstance::getMinPoint() { + loadModel(); + return KRMat4::Dot(m_modelMatrix, m_pModel->getMesh()->getMinPoint()); +} + +KRVector3 KRInstance::getMaxPoint() { + loadModel(); + return KRMat4::Dot(m_modelMatrix, m_pModel->getMesh()->getMaxPoint()); } \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRInstance.h b/KREngine/KREngine/Classes/KRInstance.h index a3844db..264e37b 100644 --- a/KREngine/KREngine/Classes/KRInstance.h +++ b/KREngine/KREngine/Classes/KRInstance.h @@ -53,7 +53,7 @@ class KRBoundingVolume; class KRInstance : public KRNode { public: - KRInstance(KRContext &context, std::string instance_name, std::string model_name, const KRMat4 modelMatrix, std::string light_map); + KRInstance(KRScene &scene, std::string instance_name, std::string model_name, const KRMat4 modelMatrix, std::string light_map); virtual ~KRInstance(); virtual std::string getElementName(); @@ -70,6 +70,10 @@ public: bool hasTransparency(); + + virtual KRVector3 getMinPoint(); + virtual KRVector3 getMaxPoint(); + private: KRModel *m_pModel; KRMat4 m_modelMatrix; diff --git a/KREngine/KREngine/Classes/KRLight.cpp b/KREngine/KREngine/Classes/KRLight.cpp index 7dd2512..91aebe0 100644 --- a/KREngine/KREngine/Classes/KRLight.cpp +++ b/KREngine/KREngine/Classes/KRLight.cpp @@ -22,7 +22,7 @@ #import "KRShaderManager.h" #import "KRShader.h" -KRLight::KRLight(KRContext &context, std::string name) : KRNode(context, name) +KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) { m_intensity = 1.0f; m_flareTexture = ""; diff --git a/KREngine/KREngine/Classes/KRLight.h b/KREngine/KREngine/Classes/KRLight.h index 5425a12..806bf45 100644 --- a/KREngine/KREngine/Classes/KRLight.h +++ b/KREngine/KREngine/Classes/KRLight.h @@ -41,7 +41,7 @@ public: #endif protected: - KRLight(KRContext &context, std::string name); + KRLight(KRScene &scene, std::string name); float m_intensity; float m_decayStart; diff --git a/KREngine/KREngine/Classes/KRMesh.cpp b/KREngine/KREngine/Classes/KRMesh.cpp index 4549cf7..b3ba213 100644 --- a/KREngine/KREngine/Classes/KRMesh.cpp +++ b/KREngine/KREngine/Classes/KRMesh.cpp @@ -94,13 +94,8 @@ void KRMesh::loadPack(std::string path) { m_iPackFileSize = statbuf.st_size; pack_header *pHeader = (pack_header *)m_pPackData; - - m_minx = pHeader->minx; - m_miny = pHeader->miny; - m_minz = pHeader->minz; - m_maxx = pHeader->maxx; - m_maxy = pHeader->maxy; - m_maxz = pHeader->maxz; + m_minPoint = KRVector3(pHeader->minx, pHeader->miny, pHeader->minz); + m_maxPoint = KRVector3(pHeader->maxx, pHeader->maxy, pHeader->maxz); } } @@ -156,31 +151,12 @@ void KRMesh::unmap() { GLfloat KRMesh::getMaxDimension() { GLfloat m = 0.0; - if(m_maxx - m_minx > m) m = m_maxx - m_minx; - if(m_maxy - m_miny > m) m = m_maxy - m_miny; - if(m_maxz - m_minz > m) m = m_maxz - m_minz; + if(m_maxPoint.x - m_minPoint.x > m) m = m_maxPoint.x - m_minPoint.x; + if(m_maxPoint.y - m_minPoint.y > m) m = m_maxPoint.y - m_minPoint.y; + if(m_maxPoint.z - m_minPoint.z > m) m = m_maxPoint.z - m_minPoint.z; return m; } -GLfloat KRMesh::getMinX() { - return m_minx; -} -GLfloat KRMesh::getMaxX() { - return m_maxx; -} -GLfloat KRMesh::getMinY() { - return m_miny; -} -GLfloat KRMesh::getMaxY() { - return m_maxy; -} -GLfloat KRMesh::getMinZ() { - return m_minz; -} -GLfloat KRMesh::getMaxZ() { - return m_maxz; -} - vector KRMesh::getSubmeshes() { if(m_submeshes.size() == 0) { pack_header *pHeader = (pack_header *)m_pPackData; @@ -301,19 +277,15 @@ void KRMesh::LoadData(std::vector vertices, std::vector uv pVertex->vertex.z = source_vertex.z; if(bFirstVertex) { bFirstVertex = false; - m_minx = source_vertex.x; - m_miny = source_vertex.y; - m_minz = source_vertex.z; - m_maxx = source_vertex.x; - m_maxy = source_vertex.y; - m_maxz = source_vertex.z; + m_minPoint = source_vertex; + m_maxPoint = source_vertex; } else { - if(source_vertex.x < m_minx) m_minx = source_vertex.x; - if(source_vertex.y < m_miny) m_miny = source_vertex.y; - if(source_vertex.z < m_minz) m_minz = source_vertex.z; - if(source_vertex.x > m_maxx) m_maxx = source_vertex.x; - if(source_vertex.y > m_maxy) m_maxy = source_vertex.y; - if(source_vertex.z > m_maxz) m_maxz = source_vertex.z; + if(source_vertex.x < m_minPoint.x) m_minPoint.x = source_vertex.x; + if(source_vertex.y < m_minPoint.y) m_minPoint.y = source_vertex.y; + if(source_vertex.z < m_minPoint.z) m_minPoint.z = source_vertex.z; + if(source_vertex.x > m_maxPoint.x) m_maxPoint.x = source_vertex.x; + if(source_vertex.y > m_maxPoint.y) m_maxPoint.y = source_vertex.y; + if(source_vertex.z > m_maxPoint.z) m_maxPoint.z = source_vertex.z; } if(uva.size() > iVertex) { KRVector2 source_uva = uva[iVertex]; @@ -355,12 +327,12 @@ void KRMesh::LoadData(std::vector vertices, std::vector uv pVertex++; } - pHeader->minx = m_minx; - pHeader->miny = m_miny; - pHeader->minz = m_minz; - pHeader->maxx = m_maxx; - pHeader->maxy = m_maxy; - pHeader->maxz = m_maxz; + pHeader->minx = m_minPoint.x; + pHeader->miny = m_minPoint.y; + pHeader->minz = m_minPoint.z; + pHeader->maxx = m_maxPoint.x; + pHeader->maxy = m_maxPoint.y; + pHeader->maxz = m_maxPoint.z; // Calculate missing surface normals and tangents @@ -430,3 +402,10 @@ void KRMesh::LoadData(std::vector vertices, std::vector uv } } +KRVector3 KRMesh::getMinPoint() const { + return m_minPoint; +} + +KRVector3 KRMesh::getMaxPoint() const { + return m_maxPoint; +} \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRMesh.h b/KREngine/KREngine/Classes/KRMesh.h index 940db45..fa1f632 100644 --- a/KREngine/KREngine/Classes/KRMesh.h +++ b/KREngine/KREngine/Classes/KRMesh.h @@ -71,12 +71,9 @@ public: void renderSubmesh(int iSubmesh, int *iPrevBuffer); GLfloat getMaxDimension(); - GLfloat getMinX(); - GLfloat getMaxX(); - GLfloat getMinY(); - GLfloat getMaxY(); - GLfloat getMinZ(); - GLfloat getMaxZ(); + + KRVector3 getMinPoint() const; + KRVector3 getMaxPoint() const; typedef struct { GLint start_vertex; @@ -114,7 +111,7 @@ public: } pack_material; protected: - GLfloat m_minx, m_miny, m_minz, m_maxx, m_maxy, m_maxz; + KRVector3 m_minPoint, m_maxPoint; int m_fdPackFile; void *m_pPackData; diff --git a/KREngine/KREngine/Classes/KRNode.cpp b/KREngine/KREngine/Classes/KRNode.cpp index 397b9e9..271b175 100644 --- a/KREngine/KREngine/Classes/KRNode.cpp +++ b/KREngine/KREngine/Classes/KRNode.cpp @@ -8,6 +8,7 @@ #include #include +#include #import "KRNode.h" #import "KRPointLight.h" @@ -17,7 +18,7 @@ #import "KRSkyBox.h" -KRNode::KRNode(KRContext &context, std::string name) : KRContextObject(context) +KRNode::KRNode(KRScene &scene, std::string name) : KRContextObject(scene.getContext()) { m_pExtents = NULL; m_name = name; @@ -25,10 +26,11 @@ KRNode::KRNode(KRContext &context, std::string name) : KRContextObject(context) m_localRotation = KRVector3::Zero(); m_localTranslation = KRVector3::Zero(); m_parentNode = NULL; + m_pScene = &scene; } KRNode::~KRNode() { - m_pContext->notify_sceneGraphDelete(this); + getScene().notify_sceneGraphDelete(this); for(std::vector::iterator itr=m_childNodes.begin(); itr < m_childNodes.end(); ++itr) { delete *itr; } @@ -41,7 +43,7 @@ void KRNode::addChild(KRNode *child) { child->m_parentNode = this; m_childNodes.push_back(child); clearExtents(); - m_pContext->notify_sceneGraphCreate(child); + getScene().notify_sceneGraphCreate(child); } tinyxml2::XMLElement *KRNode::saveXML(tinyxml2::XMLNode *parent) { @@ -84,7 +86,7 @@ void KRNode::loadXML(tinyxml2::XMLElement *e) { m_localRotation = KRVector3(x,y,z); for(tinyxml2::XMLElement *child_element=e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) { - KRNode *child_node = KRNode::LoadXML(*m_pContext, child_element); + KRNode *child_node = KRNode::LoadXML(getScene(), child_element); if(child_node) { addChild(child_node); } @@ -129,22 +131,22 @@ std::string KRNode::getElementName() { return "node"; } -KRNode *KRNode::LoadXML(KRContext &context, tinyxml2::XMLElement *e) { +KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) { KRNode *new_node = NULL; const char *szElementName = e->Name(); const char *szName = e->Attribute("name"); if(strcmp(szElementName, "node") == 0) { - new_node = new KRNode(context, szName); + new_node = new KRNode(scene, szName); } else if(strcmp(szElementName, "point_light") == 0) { - new_node = new KRPointLight(context, szName); + new_node = new KRPointLight(scene, szName); } else if(strcmp(szElementName, "directional_light") == 0) { - new_node = new KRDirectionalLight(context, szName); + new_node = new KRDirectionalLight(scene, szName); } else if(strcmp(szElementName, "spot_light") == 0) { - new_node = new KRSpotLight(context, szName); + new_node = new KRSpotLight(scene, szName); } else if(strcmp(szElementName, "mesh") == 0) { - new_node = new KRInstance(context, szName, szName, KRMat4(), e->Attribute("light_map")); + new_node = new KRInstance(scene, szName, szName, KRMat4(), e->Attribute("light_map")); } else if(strcmp(szElementName, "sky_box") == 0) { - new_node = new KRSkyBox(context, szName); + new_node = new KRSkyBox(scene, szName); } if(new_node) { @@ -201,4 +203,17 @@ const std::vector &KRNode::getChildren() { const std::string &KRNode::getName() { return m_name; +} + +KRScene &KRNode::getScene() { + return *m_pScene; +} + + +KRVector3 KRNode::getMinPoint() { + return KRVector3::Min(); +} + +KRVector3 KRNode::getMaxPoint() { + return KRVector3::Max(); } \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRNode.h b/KREngine/KREngine/Classes/KRNode.h index 3296853..0b8e911 100644 --- a/KREngine/KREngine/Classes/KRNode.h +++ b/KREngine/KREngine/Classes/KRNode.h @@ -21,6 +21,7 @@ class KRMaterialManager; class KRMat4; class KRTextureManager; class KRContext; +class KRScene; class KRNode : public KRContextObject { @@ -36,11 +37,11 @@ public: RENDER_PASS_SKYBOX }; - KRNode(KRContext &context, std::string name); + KRNode(KRScene &scene, std::string name); virtual ~KRNode(); virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); - static KRNode *LoadXML(KRContext &context, tinyxml2::XMLElement *e); + static KRNode *LoadXML(KRScene &scene, tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement *e); virtual std::string getElementName(); @@ -63,7 +64,12 @@ public: void clearExtents(); virtual void calcExtents(KRContext *Context); - KRBoundingVolume getExtents(KRContext *pContext); + KRBoundingVolume getExtents(KRContext *pContext); + + virtual KRVector3 getMinPoint(); + virtual KRVector3 getMaxPoint(); + + KRScene &getScene(); #if TARGET_OS_IPHONE virtual void render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass); @@ -83,6 +89,8 @@ private: std::vector m_childNodes; KRNode *m_parentNode; + KRScene *m_pScene; + }; diff --git a/KREngine/KREngine/Classes/KRNotified.cpp b/KREngine/KREngine/Classes/KRNotified.cpp index 9302ed8..83c3710 100644 --- a/KREngine/KREngine/Classes/KRNotified.cpp +++ b/KREngine/KREngine/Classes/KRNotified.cpp @@ -34,10 +34,13 @@ KRNotified::KRNotified(KRContext &context) : KRContextObject(context) { - + m_pSubscribedScene = NULL; } KRNotified::~KRNotified() { - m_pContext->unregisterNotified(this); + if(m_pSubscribedScene) { + m_pSubscribedScene->unregisterNotified(this); + m_pSubscribedScene = NULL; + } } diff --git a/KREngine/KREngine/Classes/KRNotified.h b/KREngine/KREngine/Classes/KRNotified.h index 0491020..98de58e 100644 --- a/KREngine/KREngine/Classes/KRNotified.h +++ b/KREngine/KREngine/Classes/KRNotified.h @@ -36,6 +36,7 @@ class KRContext; class KRNode; +class KRScene; class KRNotified : public KRContextObject { @@ -46,6 +47,8 @@ public: virtual void notify_sceneGraphCreate(KRNode *pNode) = 0; virtual void notify_sceneGraphDelete(KRNode *pNode) = 0; virtual void notify_sceneGraphModify(KRNode *pNode) = 0; +private: + KRScene *m_pSubscribedScene; }; #endif diff --git a/KREngine/KREngine/Classes/KROctree.cpp b/KREngine/KREngine/Classes/KROctree.cpp new file mode 100644 index 0000000..8f2464c --- /dev/null +++ b/KREngine/KREngine/Classes/KROctree.cpp @@ -0,0 +1,84 @@ +// +// KROctree.cpp +// KREngine +// +// Created by Kearwood Gilbert on 2012-08-29. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#include "KROctree.h" +#include "KRNode.h" + +KROctree::KROctree() +{ + m_pRootNode = NULL; +} + +KROctree::~KROctree() +{ + if(m_pRootNode) { + delete m_pRootNode; + } +} + +void KROctree::add(KRNode *pNode) +{ + KRVector3 minPoint = pNode->getMinPoint(); + KRVector3 maxPoint = pNode->getMaxPoint(); + if(pNode->getMinPoint() == KRVector3::Min() && pNode->getMaxPoint() == KRVector3::Max()) { + // This item is infinitely large; we track it separately + m_outerSceneNodes.insert(pNode); + } else { + if(m_pRootNode == NULL) { + // First item inserted, create a node large enough to fit it + m_pRootNode = new KROctreeNode(pNode->getMinPoint(), pNode->getMaxPoint()); + m_pRootNode->add(pNode); + } else { + // Keep encapsulating the root node until the new root contains the inserted node + bool bInsideRoot = false; + while(!bInsideRoot) { + KRVector3 rootMinPoint = m_pRootNode->getMinPoint(); + KRVector3 rootMaxPoint = m_pRootNode->getMaxPoint(); + KRVector3 rootSize = rootMaxPoint - rootMinPoint; + if(minPoint.x < rootMinPoint.x || minPoint.y < rootMinPoint.y || minPoint.z < rootMinPoint.z) { + m_pRootNode = new KROctreeNode(rootMinPoint - rootSize, rootMaxPoint, 7, m_pRootNode); + } else if(maxPoint.x > rootMaxPoint.x || maxPoint.y > rootMaxPoint.y || maxPoint.z > rootMaxPoint.z) { + m_pRootNode = new KROctreeNode(rootMaxPoint, rootMaxPoint + rootSize, 0, m_pRootNode); + } else { + bInsideRoot = true; + } + } + m_pRootNode->add(pNode); + } + } +} + +void KROctree::remove(KRNode *pNode) +{ + if(!m_outerSceneNodes.erase(pNode)) { + if(m_pRootNode) { + m_pRootNode->remove(pNode); + } + } + + shrink(); +} + +void KROctree::update(KRNode *pNode) +{ + // TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node + remove(pNode); + add(pNode); + shrink(); +} + +void KROctree::shrink() +{ + if(m_pRootNode) { + while(m_pRootNode->canShrinkRoot()) { + KROctreeNode *newRoot = m_pRootNode->stripChild(); + delete m_pRootNode; + m_pRootNode = newRoot; + } + } +} diff --git a/KREngine/KREngine/Classes/KROctree.h b/KREngine/KREngine/Classes/KROctree.h new file mode 100644 index 0000000..9ac49a6 --- /dev/null +++ b/KREngine/KREngine/Classes/KROctree.h @@ -0,0 +1,33 @@ +// +// KROctree.h +// KREngine +// +// Created by Kearwood Gilbert on 2012-08-29. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#ifndef KRAABBTREE_H +#define KRAABBTREE_H + +#import "KREngine-common.h" +#include "KROctreeNode.h" + +class KRNode; + +class KROctree { +public: + KROctree(); + ~KROctree(); + + void add(KRNode *pNode); + void remove(KRNode *pNode); + void update(KRNode *pNode); + +private: + KROctreeNode *m_pRootNode; + std::setm_outerSceneNodes; + + void shrink(); +}; + +#endif /* defined(KRAABBTREE_H) */ diff --git a/KREngine/KREngine/Classes/KROctreeNode.cpp b/KREngine/KREngine/Classes/KROctreeNode.cpp new file mode 100644 index 0000000..1040f38 --- /dev/null +++ b/KREngine/KREngine/Classes/KROctreeNode.cpp @@ -0,0 +1,172 @@ +// +// KROctreeNode.cpp +// KREngine +// +// Created by Kearwood Gilbert on 2012-08-29. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#include "KROctreeNode.h" +#include "KRNode.h" + +KROctreeNode::KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint) +{ + m_minPoint = minPoint; + m_maxPoint = maxPoint; + for(int i=0; i<8; i++) m_children[i] = NULL; +} + +KROctreeNode::KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint, int iChild, KROctreeNode *pChild) +{ + // This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it + m_minPoint = minPoint; + m_maxPoint = maxPoint; + for(int i=0; i<8; i++) m_children[i] = NULL; + m_children[iChild] = pChild; +} + +KROctreeNode::~KROctreeNode() +{ + for(int i=0; i<8; i++) { + if(m_children[i] != NULL) { + delete m_children[i]; + } + } +} + +void KROctreeNode::add(KRNode *pNode) +{ + + + KRVector3 center = (m_minPoint + m_maxPoint) / 2.0f; + + int iChild = getChildIndex(pNode); + if(iChild == -1) { + m_sceneNodes.insert(pNode); + } else { + if(m_children[iChild] == NULL) { + m_children[iChild] = new KROctreeNode( + KRVector3( + (iChild & 1) == 0 ? m_minPoint.x : center.x, + (iChild & 2) == 0 ? m_minPoint.y : center.y, + (iChild & 4) == 0 ? m_minPoint.z : center.z), + KRVector3( + (iChild & 1) == 0 ? center.x : m_maxPoint.x, + (iChild & 2) == 0 ? center.y : m_maxPoint.y, + (iChild & 4) == 0 ? center.z : m_maxPoint.z) + ); + } + m_children[iChild]->add(pNode); + } +} + +int KROctreeNode::getChildIndex(KRNode *pNode) +{ + KRVector3 min = pNode->getMinPoint(); + KRVector3 max = pNode->getMaxPoint(); + // 0: max.x < center.x && max.y < center.y && max.z < center.z + // 1: min.x > center.x && max.y < center.y && max.z < center.z + // 2: max.x < center.x && min.y > center.y && max.z < center.z + // 3: min.x > center.x && min.y > center.y && max.z < center.z + // 4: max.x < center.x && max.y < center.y && min.z > center.z + // 5: min.x > center.x && max.y < center.y && min.z > center.z + // 6: max.x < center.x && min.y > center.y && min.z > center.z + // 7: min.x > center.x && min.y > center.y && min.z > center.z + + KRVector3 center = (m_minPoint + m_maxPoint) / 2.0f; + int iChild = -1; + if(max.z < center.z) { + if(max.y < center.y) { + if(max.x < center.x) { + iChild = 0; + } else if(min.x > center.x) { + iChild = 1; + } + } else if(min.y > center.y) { + if(max.x < center.x) { + iChild = 2; + } else if(min.x > center.x) { + iChild = 3; + } + } + } else if(min.z > center.z) { + if(max.y < center.y) { + if(min.x > center.x) { + iChild = 4; + } else if(min.x > center.x) { + iChild = 5; + } + } else if(min.y > center.y) { + if(max.x < center.x) { + iChild = 6; + } else if(min.x > center.x) { + iChild = 7; + } + } + } + return iChild; +} + +void KROctreeNode::remove(KRNode *pNode) +{ + if(!m_sceneNodes.erase(pNode)) { + int iChild = getChildIndex(pNode); + if(m_children[iChild]) { + m_children[iChild]->remove(pNode); + if(m_children[iChild]->isEmpty()) { + delete m_children[iChild]; + m_children[iChild] = NULL; + } + } + } +} + +void KROctreeNode::update(KRNode *pNode) +{ + +} + +KRVector3 KROctreeNode::getMinPoint() +{ + return m_minPoint; +} + +KRVector3 KROctreeNode::getMaxPoint() +{ + return m_maxPoint; +} + +bool KROctreeNode::isEmpty() const +{ + for(int i=0; i<8; i++) { + if(m_children[i]) { + return false; + } + } + return m_sceneNodes.empty(); +} + +bool KROctreeNode::canShrinkRoot() const +{ + int cChildren = 0; + for(int i=0; i<8; i++) { + if(m_children[i]) { + cChildren++; + } + } + return cChildren <= 1 && m_sceneNodes.empty(); +} + +KROctreeNode *KROctreeNode::stripChild() +{ + // Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree + // NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL + for(int i=0; i<8; i++) { + if(m_children[i]) { + KROctreeNode *child = m_children[i]; + m_children[i] = NULL; + return child; + } + } + return NULL; +} diff --git a/KREngine/KREngine/Classes/KROctreeNode.h b/KREngine/KREngine/Classes/KROctreeNode.h new file mode 100644 index 0000000..5bbb67f --- /dev/null +++ b/KREngine/KREngine/Classes/KROctreeNode.h @@ -0,0 +1,47 @@ +// +// KROctreeNode.h +// KREngine +// +// Created by Kearwood Gilbert on 2012-08-29. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#ifndef KRAABBTREENODE_H +#define KRAABBTREENODE_H + +#import "KREngine-common.h" +#include "KRVector3.h" + +class KRNode; + +class KROctreeNode { +public: + KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint); + KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint, int iChild, KROctreeNode *pChild); + ~KROctreeNode(); + + void add(KRNode *pNode); + void remove(KRNode *pNode); + void update(KRNode *pNode); + + KRVector3 getMinPoint(); + KRVector3 getMaxPoint(); + + void setChildNode(int iChild, KROctreeNode *pChild); + int getChildIndex(KRNode *pNode); + bool isEmpty() const; + + bool canShrinkRoot() const; + KROctreeNode *stripChild(); + +private: + KRVector3 m_minPoint; + KRVector3 m_maxPoint; + + KROctreeNode *m_children[8]; + + std::setm_sceneNodes; +}; + + +#endif /* defined(KRAABBTREENODE_H) */ diff --git a/KREngine/KREngine/Classes/KRPointLight.cpp b/KREngine/KREngine/Classes/KRPointLight.cpp index 9c5d426..ae8da4b 100644 --- a/KREngine/KREngine/Classes/KRPointLight.cpp +++ b/KREngine/KREngine/Classes/KRPointLight.cpp @@ -16,7 +16,7 @@ #import "KRContext.h" #import "KRBoundingVolume.h" -KRPointLight::KRPointLight(KRContext &context, std::string name) : KRLight(context, name) +KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name) { m_sphereVertices = NULL; m_cVertices = 0; diff --git a/KREngine/KREngine/Classes/KRPointLight.h b/KREngine/KREngine/Classes/KRPointLight.h index 1ed3586..b6bc868 100644 --- a/KREngine/KREngine/Classes/KRPointLight.h +++ b/KREngine/KREngine/Classes/KRPointLight.h @@ -16,7 +16,7 @@ class KRPointLight : public KRLight { public: - KRPointLight(KRContext &context, std::string name); + KRPointLight(KRScene &scene, std::string name); virtual ~KRPointLight(); virtual std::string getElementName(); diff --git a/KREngine/KREngine/Classes/KRScene.cpp b/KREngine/KREngine/Classes/KRScene.cpp index 38b2f60..54ee3dd 100644 --- a/KREngine/KREngine/Classes/KRScene.cpp +++ b/KREngine/KREngine/Classes/KRScene.cpp @@ -42,7 +42,7 @@ KRScene::KRScene(KRContext &context, std::string name) : KRResource(context, name) { m_pContext = &context; m_pFirstDirectionalLight = NULL; - m_pRootNode = new KRNode(context, "scene_root"); + m_pRootNode = new KRNode(*this, "scene_root"); sun_yaw = 4.333; // TODO - Remove temporary testing code sun_pitch = 0.55; @@ -56,6 +56,8 @@ KRScene::~KRScene() { void KRScene::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { + updateOctree(); + if(renderPass != KRNode::RENDER_PASS_SHADOWMAP) { if(cShadowBuffers > 0) { @@ -145,7 +147,7 @@ KRScene *KRScene::LoadXML(KRContext &context, const std::string& path) doc.LoadFile(path.c_str()); KRScene *new_scene = new KRScene(context, KRResource::GetFileBase(path)); - KRNode *n = KRNode::LoadXML(context, doc.RootElement()->FirstChildElement()); + KRNode *n = KRNode::LoadXML(*new_scene, doc.RootElement()->FirstChildElement()); if(n) { new_scene->getRootNode()->addChild(n); } @@ -159,3 +161,57 @@ KRDirectionalLight *KRScene::getFirstDirectionalLight() } return m_pFirstDirectionalLight; } + +void KRScene::registerNotified(KRNotified *pNotified) +{ + m_notifiedObjects.insert(pNotified); + for(std::set::iterator itr=m_allNodes.begin(); itr != m_allNodes.end(); itr++) { + pNotified->notify_sceneGraphCreate(*itr); + } +} + +void KRScene::unregisterNotified(KRNotified *pNotified) +{ + m_notifiedObjects.erase(pNotified); +} + +void KRScene::notify_sceneGraphCreate(KRNode *pNode) +{ + m_allNodes.insert(pNode); + m_newNodes.insert(pNode); + for(std::set::iterator itr = m_notifiedObjects.begin(); itr != m_notifiedObjects.end(); itr++) { + (*itr)->notify_sceneGraphCreate(pNode); + } +} + +void KRScene::notify_sceneGraphDelete(KRNode *pNode) +{ + for(std::set::iterator itr = m_notifiedObjects.begin(); itr != m_notifiedObjects.end(); itr++) { + (*itr)->notify_sceneGraphDelete(pNode); + } + m_allNodes.erase(pNode); + m_modifiedNodes.erase(pNode); + if(!m_newNodes.erase(pNode)) { + m_nodeTree.remove(pNode); + } +} + +void KRScene::notify_sceneGraphModify(KRNode *pNode) +{ + m_modifiedNodes.insert(pNode); + for(std::set::iterator itr = m_notifiedObjects.begin(); itr != m_notifiedObjects.end(); itr++) { + (*itr)->notify_sceneGraphModify(pNode); + } +} + +void KRScene::updateOctree() +{ + for(std::set::iterator itr=m_newNodes.begin(); itr != m_newNodes.end(); itr++) { + m_nodeTree.add(*itr); + } + for(std::set::iterator itr=m_modifiedNodes.begin(); itr != m_modifiedNodes.end(); itr++) { + m_nodeTree.update(*itr); + } + m_newNodes.clear(); + m_modifiedNodes.clear(); +} diff --git a/KREngine/KREngine/Classes/KRScene.h b/KREngine/KREngine/Classes/KRScene.h index 2cf882d..051f537 100644 --- a/KREngine/KREngine/Classes/KRScene.h +++ b/KREngine/KREngine/Classes/KRScene.h @@ -42,6 +42,7 @@ #import "KRCamera.h" #import "KRModelManager.h" #import "KRNode.h" +#import "KROctree.h" class KRBoundingVolume; class KRInstance; class KRDirectionalLight; @@ -69,6 +70,14 @@ public: KRBoundingVolume getExtents(KRContext *pContext); double sun_pitch, sun_yaw; + + void registerNotified(KRNotified *pNotified); + void unregisterNotified(KRNotified *pNotified); + + void notify_sceneGraphCreate(KRNode *pNode); + void notify_sceneGraphDelete(KRNode *pNode); + void notify_sceneGraphModify(KRNode *pNode); + private: KRContext *m_pContext; KRDirectionalLight *findFirstDirectionalLight(KRNode &node); @@ -76,6 +85,14 @@ private: KRNode *m_pRootNode; KRBoundingVolume *m_pExtents; KRDirectionalLight *m_pFirstDirectionalLight; + + std::set m_notifiedObjects; + std::set m_allNodes; + std::set m_newNodes; + std::set m_modifiedNodes; + + KROctree m_nodeTree; + void updateOctree(); }; diff --git a/KREngine/KREngine/Classes/KRSkyBox.cpp b/KREngine/KREngine/Classes/KRSkyBox.cpp index bbd5fb8..306d378 100644 --- a/KREngine/KREngine/Classes/KRSkyBox.cpp +++ b/KREngine/KREngine/Classes/KRSkyBox.cpp @@ -14,7 +14,7 @@ #import "KRMat4.h" #import "KRResource.h" -KRSkyBox::KRSkyBox(KRContext &context, std::string name) : KRNode(context, name) +KRSkyBox::KRSkyBox(KRScene &scene, std::string name) : KRNode(scene, name) { m_frontTexture = ""; m_backTexture = ""; diff --git a/KREngine/KREngine/Classes/KRSkyBox.h b/KREngine/KREngine/Classes/KRSkyBox.h index 508348c..9bf0072 100644 --- a/KREngine/KREngine/Classes/KRSkyBox.h +++ b/KREngine/KREngine/Classes/KRSkyBox.h @@ -18,7 +18,7 @@ class KRSkyBox : public KRNode { public: - KRSkyBox(KRContext &context, std::string name); + KRSkyBox(KRScene &scene, std::string name); virtual ~KRSkyBox(); virtual std::string getElementName(); diff --git a/KREngine/KREngine/Classes/KRSpotLight.cpp b/KREngine/KREngine/Classes/KRSpotLight.cpp index 75d76f5..f937074 100644 --- a/KREngine/KREngine/Classes/KRSpotLight.cpp +++ b/KREngine/KREngine/Classes/KRSpotLight.cpp @@ -10,7 +10,7 @@ #import "KRSpotLight.h" -KRSpotLight::KRSpotLight(KRContext &context, std::string name) : KRLight(context, name) +KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name) { } diff --git a/KREngine/KREngine/Classes/KRSpotLight.h b/KREngine/KREngine/Classes/KRSpotLight.h index c1eedef..02f2a9e 100644 --- a/KREngine/KREngine/Classes/KRSpotLight.h +++ b/KREngine/KREngine/Classes/KRSpotLight.h @@ -13,7 +13,7 @@ class KRSpotLight : public KRLight { public: - KRSpotLight(KRContext &context, std::string name); + KRSpotLight(KRScene &scene, std::string name); virtual ~KRSpotLight(); virtual std::string getElementName(); diff --git a/KREngine/KREngine/Classes/KRVector2.cpp b/KREngine/KREngine/Classes/KRVector2.cpp index 3d24499..7d6926c 100644 --- a/KREngine/KREngine/Classes/KRVector2.cpp +++ b/KREngine/KREngine/Classes/KRVector2.cpp @@ -31,6 +31,14 @@ KRVector2::KRVector2(const KRVector2 &v) { y = v.y; } +KRVector2 KRVector2::Min() { + return KRVector2(-std::numeric_limits::max()); +} + +KRVector2 KRVector2::Max() { + return KRVector2(std::numeric_limits::max()); +} + KRVector2 KRVector2::Zero() { return KRVector2(0.0f); } diff --git a/KREngine/KREngine/Classes/KRVector2.h b/KREngine/KREngine/Classes/KRVector2.h index 5a9a674..420a928 100644 --- a/KREngine/KREngine/Classes/KRVector2.h +++ b/KREngine/KREngine/Classes/KRVector2.h @@ -73,7 +73,8 @@ public: static float Cross(const KRVector2 &v1, const KRVector2 &v2); static float Dot(const KRVector2 &v1, const KRVector2 &v2); - + static KRVector2 Min(); + static KRVector2 Max(); static KRVector2 Zero(); static KRVector2 One(); diff --git a/KREngine/KREngine/Classes/KRVector3.cpp b/KREngine/KREngine/Classes/KRVector3.cpp index df083d1..a6f5c64 100644 --- a/KREngine/KREngine/Classes/KRVector3.cpp +++ b/KREngine/KREngine/Classes/KRVector3.cpp @@ -32,6 +32,7 @@ #include "KRVector3.h" #include +#include //default constructor KRVector3::KRVector3() @@ -47,6 +48,14 @@ KRVector3::KRVector3(const KRVector3 &v) { z = v.z; } +KRVector3 KRVector3::Min() { + return KRVector3(-std::numeric_limits::max()); +} + +KRVector3 KRVector3::Max() { + return KRVector3(std::numeric_limits::max()); +} + KRVector3 KRVector3::Zero() { return KRVector3(0.0f, 0.0f, 0.0f); } diff --git a/KREngine/KREngine/Classes/KRVector3.h b/KREngine/KREngine/Classes/KRVector3.h index 4de6d93..3ece381 100644 --- a/KREngine/KREngine/Classes/KRVector3.h +++ b/KREngine/KREngine/Classes/KRVector3.h @@ -74,7 +74,8 @@ public: static KRVector3 Cross(const KRVector3 &v1, const KRVector3 &v2); static float Dot(const KRVector3 &v1, const KRVector3 &v2); - + static KRVector3 Min(); + static KRVector3 Max(); static KRVector3 Zero(); static KRVector3 One(); static KRVector3 Forward();