Implementation of FBX import workflow in progress
--HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%4018
This commit is contained in:
@@ -43,6 +43,18 @@
|
||||
E491019D13C99BDC0098455B /* KRTextureManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E491018513C99BDC0098455B /* KRTextureManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
E491019E13C99BDC0098455B /* KRTexture.h in Headers */ = {isa = PBXBuildFile; fileRef = E491018613C99BDC0098455B /* KRTexture.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
E49101A013C99BF50098455B /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E491019F13C99BF50098455B /* OpenGLES.framework */; };
|
||||
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, ); }; };
|
||||
E497B94A151BCEE900D3DC67 /* KRResource.h in Headers */ = {isa = PBXBuildFile; fileRef = E497B949151BCEE900D3DC67 /* KRResource.h */; };
|
||||
E497B94B151BCEE900D3DC67 /* KRResource.h in Headers */ = {isa = PBXBuildFile; fileRef = E497B949151BCEE900D3DC67 /* KRResource.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
E497B94D151BCF2500D3DC67 /* KRResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E497B94C151BCF2500D3DC67 /* KRResource.cpp */; };
|
||||
E497B94E151BCF2500D3DC67 /* KRResource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E497B94C151BCF2500D3DC67 /* KRResource.cpp */; };
|
||||
E497B950151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E497B94F151BD2CE00D3DC67 /* KRResource+obj.cpp */; };
|
||||
E497B951151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E497B94F151BD2CE00D3DC67 /* KRResource+obj.cpp */; };
|
||||
E497B954151BEDA600D3DC67 /* KRResource+fbx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E497B952151BEDA600D3DC67 /* KRResource+fbx.cpp */; };
|
||||
E497B95D151BF05F00D3DC67 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E497B95C151BF05F00D3DC67 /* CoreServices.framework */; };
|
||||
E497B95F151BF09600D3DC67 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E497B95E151BF09600D3DC67 /* SystemConfiguration.framework */; };
|
||||
E49E79FF1512615F009CF99C /* KRMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E49E79FE1512615F009CF99C /* KRMesh.cpp */; };
|
||||
E4BBBB8A1512A40300F43B5B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E4BBBB881512A40300F43B5B /* InfoPlist.strings */; };
|
||||
E4BBBB8E1512A40300F43B5B /* krengine_osx.m in Sources */ = {isa = PBXBuildFile; fileRef = E4BBBB8D1512A40300F43B5B /* krengine_osx.m */; };
|
||||
@@ -110,6 +122,14 @@
|
||||
E491018513C99BDC0098455B /* KRTextureManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRTextureManager.h; path = Classes/KRTextureManager.h; sourceTree = "<group>"; 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 = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
E491019F13C99BF50098455B /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
|
||||
E497B943151BA93400D3DC67 /* KRVector2.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = KRVector2.h; path = Classes/KRVector2.h; sourceTree = "<group>"; };
|
||||
E497B945151BA99400D3DC67 /* KRVector2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRVector2.cpp; path = Classes/KRVector2.cpp; sourceTree = "<group>"; };
|
||||
E497B949151BCEE900D3DC67 /* KRResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRResource.h; path = Classes/KRResource.h; sourceTree = "<group>"; };
|
||||
E497B94C151BCF2500D3DC67 /* KRResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRResource.cpp; path = Classes/KRResource.cpp; sourceTree = "<group>"; };
|
||||
E497B94F151BD2CE00D3DC67 /* KRResource+obj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "KRResource+obj.cpp"; path = "Classes/KRResource+obj.cpp"; sourceTree = "<group>"; };
|
||||
E497B952151BEDA600D3DC67 /* KRResource+fbx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "KRResource+fbx.cpp"; path = "Classes/KRResource+fbx.cpp"; sourceTree = "<group>"; };
|
||||
E497B95C151BF05F00D3DC67 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/CoreServices.framework; sourceTree = DEVELOPER_DIR; };
|
||||
E497B95E151BF09600D3DC67 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; };
|
||||
E49E79FC15126146009CF99C /* KRMesh.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRMesh.h; path = Classes/KRMesh.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
|
||||
E49E79FE1512615F009CF99C /* KRMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = KRMesh.cpp; path = Classes/KRMesh.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
E4BBBB7E1512A40300F43B5B /* krengine_osx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = krengine_osx.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -145,6 +165,8 @@
|
||||
E4BBBB9E1512A4AE00F43B5B /* AppKit.framework in Frameworks */,
|
||||
E4BBBB9F1512A4B100F43B5B /* Cocoa.framework in Frameworks */,
|
||||
E4F711A51512BB56007EE923 /* libfbxsdk-2012.2-static.a in Frameworks */,
|
||||
E497B95D151BF05F00D3DC67 /* CoreServices.framework in Frameworks */,
|
||||
E497B95F151BF09600D3DC67 /* SystemConfiguration.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -247,6 +269,12 @@
|
||||
E49E79FC15126146009CF99C /* KRMesh.h */,
|
||||
E49E79FE1512615F009CF99C /* KRMesh.cpp */,
|
||||
E46DBE841512B9E200D59F86 /* KREngine-common.h */,
|
||||
E497B943151BA93400D3DC67 /* KRVector2.h */,
|
||||
E497B945151BA99400D3DC67 /* KRVector2.cpp */,
|
||||
E497B949151BCEE900D3DC67 /* KRResource.h */,
|
||||
E497B94C151BCF2500D3DC67 /* KRResource.cpp */,
|
||||
E497B94F151BD2CE00D3DC67 /* KRResource+obj.cpp */,
|
||||
E497B952151BEDA600D3DC67 /* KRResource+fbx.cpp */,
|
||||
);
|
||||
name = Classes;
|
||||
sourceTree = "<group>";
|
||||
@@ -275,6 +303,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E4F711A41512BB56007EE923 /* libfbxsdk-2012.2-static.a */,
|
||||
E497B95E151BF09600D3DC67 /* SystemConfiguration.framework */,
|
||||
E497B95C151BF05F00D3DC67 /* CoreServices.framework */,
|
||||
E46DBE7D1512AD4900D59F86 /* OpenGL.framework */,
|
||||
E4BBBB9A1512A48200F43B5B /* Foundation.framework */,
|
||||
E4BBBB981512A47500F43B5B /* CoreData.framework */,
|
||||
@@ -306,6 +336,7 @@
|
||||
E414BAE7143557D200A668C4 /* KRScene.h in Headers */,
|
||||
E414BAEB14355E5500A668C4 /* KRBoundingVolume.h in Headers */,
|
||||
E48B3CBD14393DF5000C50E2 /* KRCamera.h in Headers */,
|
||||
E497B94A151BCEE900D3DC67 /* KRResource.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -313,7 +344,9 @@
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E497B948151BB89D00D3DC67 /* KRVector2.h in Headers */,
|
||||
E4D0683F1512A790005FFBEB /* KRVector3.h in Headers */,
|
||||
E497B94B151BCEE900D3DC67 /* KRResource.h in Headers */,
|
||||
E46DBE811512AFE600D59F86 /* KRMesh.h in Headers */,
|
||||
E46DBE851512B9FA00D59F86 /* KREngine-common.h in Headers */,
|
||||
);
|
||||
@@ -417,6 +450,9 @@
|
||||
E414BAED14355EFF00A668C4 /* KRBoundingVolume.cpp in Sources */,
|
||||
E48B3CC014393E30000C50E2 /* KRCamera.cpp in Sources */,
|
||||
E49E79FF1512615F009CF99C /* KRMesh.cpp in Sources */,
|
||||
E497B946151BA99500D3DC67 /* KRVector2.cpp in Sources */,
|
||||
E497B94D151BCF2500D3DC67 /* KRResource.cpp in Sources */,
|
||||
E497B950151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -427,6 +463,10 @@
|
||||
E46DBE7B1512ACE600D59F86 /* KRMesh.cpp in Sources */,
|
||||
E4BBBBA71512A6DC00F43B5B /* KRVector3.cpp in Sources */,
|
||||
E4BBBB8E1512A40300F43B5B /* krengine_osx.m in Sources */,
|
||||
E497B947151BA99500D3DC67 /* KRVector2.cpp in Sources */,
|
||||
E497B94E151BCF2500D3DC67 /* KRResource.cpp in Sources */,
|
||||
E497B951151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */,
|
||||
E497B954151BEDA600D3DC67 /* KRResource+fbx.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -478,7 +518,10 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
DSTROOT = /tmp/KREngine.dst;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)\"",
|
||||
);
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "KREngine/KREngine-Prefix.pch";
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
@@ -493,7 +536,10 @@
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
DSTROOT = /tmp/KREngine.dst;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"\"$(SRCROOT)\"",
|
||||
);
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = "KREngine/KREngine-Prefix.pch";
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
@@ -515,6 +561,7 @@
|
||||
"$(inherited)",
|
||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
|
||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks\"",
|
||||
"\"$(SRCROOT)\"",
|
||||
);
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
@@ -528,6 +575,7 @@
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
HEADER_SEARCH_PATHS = /Applications/Autodesk/FBXSDK20122/include;
|
||||
INFOPLIST_FILE = "krengine_osx/krengine_osx-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
@@ -555,6 +603,7 @@
|
||||
"$(inherited)",
|
||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
|
||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks\"",
|
||||
"\"$(SRCROOT)\"",
|
||||
);
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
@@ -563,6 +612,7 @@
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
HEADER_SEARCH_PATHS = /Applications/Autodesk/FBXSDK20122/include;
|
||||
INFOPLIST_FILE = "krengine_osx/krengine_osx-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
KRMesh::KRMesh() {
|
||||
KRMesh::KRMesh(std::string name) : KRResource(name) {
|
||||
m_fdPackFile = 0;
|
||||
m_pPackData = NULL;
|
||||
m_iPackFileSize = 0;
|
||||
@@ -49,12 +49,18 @@ KRMesh::KRMesh() {
|
||||
}
|
||||
|
||||
KRMesh::~KRMesh() {
|
||||
clearData();
|
||||
}
|
||||
|
||||
void KRMesh::clearData() {
|
||||
clearBuffers();
|
||||
if(m_fdPackFile) {
|
||||
if(m_pPackData != NULL) {
|
||||
munmap(m_pPackData, m_iPackFileSize);
|
||||
m_pPackData = NULL;
|
||||
}
|
||||
close(m_fdPackFile);
|
||||
m_fdPackFile = 0;
|
||||
} else {
|
||||
// If we didn't load a packed file, then the data was calculated at run time and malloc'ed
|
||||
if(m_pPackData != NULL) {
|
||||
@@ -62,8 +68,6 @@ KRMesh::~KRMesh() {
|
||||
m_pPackData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
clearBuffers();
|
||||
}
|
||||
|
||||
void KRMesh::clearBuffers() {
|
||||
@@ -76,6 +80,7 @@ void KRMesh::clearBuffers() {
|
||||
}
|
||||
|
||||
void KRMesh::loadPack(std::string path) {
|
||||
clearData();
|
||||
struct stat statbuf;
|
||||
m_fdPackFile = open(path.c_str(), O_RDONLY);
|
||||
if(m_fdPackFile >= 0) {
|
||||
@@ -84,8 +89,6 @@ void KRMesh::loadPack(std::string path) {
|
||||
} else {
|
||||
m_iPackFileSize = statbuf.st_size;
|
||||
|
||||
clearBuffers();
|
||||
|
||||
pack_header *pHeader = (pack_header *)m_pPackData;
|
||||
|
||||
m_minx = pHeader->minx;
|
||||
@@ -100,13 +103,18 @@ void KRMesh::loadPack(std::string path) {
|
||||
}
|
||||
}
|
||||
|
||||
bool KRMesh::writePack(std::string path) {
|
||||
bool KRMesh::save(const std::string& path) {
|
||||
clearBuffers();
|
||||
|
||||
int fdNewFile = open(path.c_str(), O_RDWR);
|
||||
if(fdNewFile == 0) {
|
||||
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
|
||||
if(fdNewFile == -1) {
|
||||
return false;
|
||||
} else {
|
||||
// Seek to end of file and write a byte to enlarge it
|
||||
lseek(fdNewFile, m_iPackFileSize-1, SEEK_SET);
|
||||
write(fdNewFile, "", 1);
|
||||
|
||||
// Now map it...
|
||||
void *pNewData = mmap(0, m_iPackFileSize, PROT_READ | PROT_WRITE, MAP_SHARED, fdNewFile, 0);
|
||||
if(pNewData == (caddr_t) -1) {
|
||||
close(fdNewFile);
|
||||
@@ -251,3 +259,151 @@ KRMesh::VertexData *KRMesh::getVertexData() {
|
||||
pack_material *pPackMaterials = (pack_material *)(pHeader+1);
|
||||
return (VertexData *)(pPackMaterials + pHeader->submesh_count);
|
||||
}
|
||||
|
||||
void KRMesh::LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uva, std::vector<KRVector3> normals, std::vector<KRVector3> tangents, std::vector<int> submesh_starts, std::vector<int> submesh_lengths, std::vector<std::string> material_names) {
|
||||
|
||||
clearData();
|
||||
|
||||
int submesh_count = submesh_lengths.size();
|
||||
int vertex_count = vertices.size();
|
||||
m_iPackFileSize = sizeof(pack_header) + sizeof(pack_material) * submesh_count + sizeof(VertexData) * vertex_count;
|
||||
m_pPackData = malloc(m_iPackFileSize);
|
||||
|
||||
pack_header *pHeader = (pack_header *)m_pPackData;
|
||||
memset(pHeader, 0, sizeof(pack_header));
|
||||
|
||||
pHeader->submesh_count = submesh_lengths.size();
|
||||
pHeader->vertex_count = vertices.size();
|
||||
strcpy(pHeader->szTag, "KROBJPACK1.0 ");
|
||||
|
||||
pack_material *pPackMaterials = (pack_material *)(pHeader+1);
|
||||
|
||||
for(int iMaterial=0; iMaterial < pHeader->submesh_count; iMaterial++) {
|
||||
pack_material *pPackMaterial = pPackMaterials + iMaterial;
|
||||
pPackMaterial->start_vertex = submesh_starts[iMaterial];
|
||||
pPackMaterial->vertex_count = submesh_lengths[iMaterial];
|
||||
strcpy(pPackMaterial->szName, material_names[iMaterial].c_str());
|
||||
}
|
||||
|
||||
bool bFirstVertex = true;
|
||||
|
||||
VertexData *pVertexData = (VertexData *)(pPackMaterials + pHeader->submesh_count);
|
||||
VertexData *pVertex = pVertexData;
|
||||
for(int iVertex=0; iVertex < vertices.size(); iVertex++) {
|
||||
memset(pVertex, 0, sizeof(VertexData));
|
||||
KRVector3 source_vertex = vertices[iVertex];
|
||||
pVertex->vertex.x = source_vertex.x;
|
||||
pVertex->vertex.y = source_vertex.y;
|
||||
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;
|
||||
} 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(uva.size() > iVertex) {
|
||||
KRVector2 source_uva = uva[iVertex];
|
||||
pVertex->texcoord.u = source_uva.x;
|
||||
pVertex->texcoord.v = source_uva.y;
|
||||
}
|
||||
if(normals.size() > iVertex) {
|
||||
KRVector3 source_normal = normals[iVertex];
|
||||
pVertex->normal.x = source_normal.x;
|
||||
pVertex->normal.y = source_normal.y;
|
||||
pVertex->normal.z = source_normal.z;
|
||||
}
|
||||
if(tangents.size() > iVertex) {
|
||||
KRVector3 source_tangent = tangents[iVertex];
|
||||
pVertex->tangent.x = source_tangent.x;
|
||||
pVertex->tangent.y = source_tangent.y;
|
||||
pVertex->tangent.z = source_tangent.z;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
// Calculate missing surface normals and tangents
|
||||
//cout << " Calculate surface normals and tangents\n";
|
||||
VertexData *pStart = pVertexData;
|
||||
VertexData *pEnd = pStart + vertex_count;
|
||||
|
||||
for(VertexData *pVertex = pStart; pVertex < pEnd; pVertex+=3) {
|
||||
KRVector3 p1(pVertex[0].vertex.x, pVertex[0].vertex.y, pVertex[0].vertex.z);
|
||||
KRVector3 p2(pVertex[1].vertex.x, pVertex[1].vertex.y, pVertex[1].vertex.z);
|
||||
KRVector3 p3(pVertex[2].vertex.x, pVertex[2].vertex.y, pVertex[2].vertex.z);
|
||||
KRVector3 v1 = p2 - p1;
|
||||
KRVector3 v2 = p3 - p1;
|
||||
|
||||
// -- Calculate normal --
|
||||
if(pVertex->normal.x == 0 && pVertex->normal.y == 0 && pVertex->normal.z == 0) {
|
||||
|
||||
KRVector3 normal = v1.cross( v2 );
|
||||
|
||||
normal.normalize();
|
||||
|
||||
pVertex[0].normal.x = normal.x;
|
||||
pVertex[0].normal.y = normal.y;
|
||||
pVertex[0].normal.z = normal.z;
|
||||
|
||||
pVertex[1].normal.x = normal.x;
|
||||
pVertex[1].normal.y = normal.y;
|
||||
pVertex[1].normal.z = normal.z;
|
||||
|
||||
pVertex[2].normal.x = normal.x;
|
||||
pVertex[2].normal.y = normal.y;
|
||||
pVertex[2].normal.z = normal.z;
|
||||
}
|
||||
|
||||
// -- Calculate tangent vector for normal mapping --
|
||||
if(pVertex->tangent.x == 0 && pVertex->tangent.y == 0 && pVertex->tangent.z == 0) {
|
||||
TexCoord st1; // = pVertex[2].texcoord;
|
||||
TexCoord st2; // = pVertex[1].texcoord;
|
||||
st1.u = pVertex[1].texcoord.u - pVertex[0].texcoord.u;
|
||||
st1.v = pVertex[1].texcoord.v - pVertex[0].texcoord.v;
|
||||
st2.u = pVertex[2].texcoord.u - pVertex[0].texcoord.u;
|
||||
st2.v = pVertex[2].texcoord.v - pVertex[0].texcoord.v;
|
||||
double coef = 1/ (st1.u * st2.v - st2.u * st1.v);
|
||||
|
||||
pVertex[0].tangent.x = coef * ((v1.x * st2.v) + (v2.x * -st1.v));
|
||||
pVertex[0].tangent.y = coef * ((v1.y * st2.v) + (v2.y * -st1.v));
|
||||
pVertex[0].tangent.z = coef * ((v1.z * st2.v) + (v2.z * -st1.v));
|
||||
|
||||
KRVector3 tangent(
|
||||
coef * ((v1.x * st2.v) + (v2.x * -st1.v)),
|
||||
coef * ((v1.y * st2.v) + (v2.y * -st1.v)),
|
||||
coef * ((v1.z * st2.v) + (v2.z * -st1.v))
|
||||
);
|
||||
|
||||
tangent.normalize();
|
||||
|
||||
pVertex[0].tangent.x = tangent.x;
|
||||
pVertex[0].tangent.y = tangent.y;
|
||||
pVertex[0].tangent.z = tangent.z;
|
||||
pVertex[1].tangent.x = tangent.x;
|
||||
pVertex[1].tangent.y = tangent.y;
|
||||
pVertex[1].tangent.z = tangent.z;
|
||||
pVertex[2].tangent.x = tangent.x;
|
||||
pVertex[2].tangent.y = tangent.y;
|
||||
pVertex[2].tangent.z = tangent.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,22 @@
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
#import <stdint.h>
|
||||
#import <vector>
|
||||
#import <set>
|
||||
#import <list>
|
||||
#import <string>
|
||||
#import "KRMesh.h"
|
||||
#import "KRVector2.h"
|
||||
#import "KRVector3.h"
|
||||
#import "KRResource.h"
|
||||
|
||||
#import "KREngine-common.h"
|
||||
|
||||
using std::vector;
|
||||
using std::set;
|
||||
using std::list;
|
||||
|
||||
|
||||
#define MAX_VBO_SIZE 65535
|
||||
// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects...
|
||||
@@ -42,13 +56,17 @@
|
||||
|
||||
using std::vector;
|
||||
|
||||
class KRMesh {
|
||||
class KRMesh : public KRResource {
|
||||
public:
|
||||
KRMesh();
|
||||
static vector<KRMesh> loadObj(const char *szPath);
|
||||
|
||||
KRMesh(std::string name);
|
||||
~KRMesh();
|
||||
|
||||
void LoadData(std::vector<KRVector3> vertices, std::vector<KRVector2> uva, std::vector<KRVector3> normals, std::vector<KRVector3> tangents, std::vector<int> submesh_starts, std::vector<int> submesh_lengths, std::vector<std::string> material_names);
|
||||
void loadPack(std::string path);
|
||||
bool writePack(std::string path);
|
||||
virtual bool save(const std::string& path);
|
||||
|
||||
void renderSubmesh(int iSubmesh, int *iPrevBuffer);
|
||||
|
||||
GLfloat getMaxDimension();
|
||||
@@ -87,6 +105,12 @@ public:
|
||||
|
||||
vector<Submesh *> getSubmeshes();
|
||||
|
||||
typedef struct {
|
||||
int32_t start_vertex;
|
||||
int32_t vertex_count;
|
||||
char szName[64];
|
||||
} pack_material;
|
||||
|
||||
protected:
|
||||
GLfloat m_minx, m_miny, m_minz, m_maxx, m_maxy, m_maxz;
|
||||
|
||||
@@ -101,11 +125,7 @@ protected:
|
||||
int32_t submesh_count;
|
||||
} pack_header;
|
||||
|
||||
typedef struct {
|
||||
int32_t start_vertex;
|
||||
int32_t vertex_count;
|
||||
char szName[64];
|
||||
} pack_material;
|
||||
|
||||
|
||||
|
||||
GLsizei m_cBuffers;
|
||||
@@ -114,6 +134,7 @@ protected:
|
||||
vector<Submesh *> m_submeshes;
|
||||
|
||||
void unmap();
|
||||
void clearData();
|
||||
void clearBuffers();
|
||||
};
|
||||
|
||||
|
||||
@@ -50,9 +50,10 @@ KRModel::KRModel(std::string path, KRMaterialManager *pMaterialManager) {
|
||||
}
|
||||
|
||||
void KRModel::loadPack(std::string path, KRMaterialManager *pMaterialManager) {
|
||||
m_mesh.loadPack(path);
|
||||
m_pMesh = new KRMesh(KRResource::GetFileBase(path));
|
||||
m_pMesh->loadPack(path);
|
||||
|
||||
vector<KRMesh::Submesh *> submeshes = m_mesh.getSubmeshes();
|
||||
vector<KRMesh::Submesh *> submeshes = m_pMesh->getSubmeshes();
|
||||
|
||||
for(std::vector<KRMesh::Submesh *>::iterator itr = submeshes.begin(); itr != submeshes.end(); itr++) {
|
||||
KRMaterial *pMaterial = pMaterialManager->getMaterial((*itr)->szMaterialName);
|
||||
@@ -70,7 +71,7 @@ void KRModel::render(KRCamera *pCamera, KRMaterialManager *pMaterialManager, boo
|
||||
int iPrevBuffer = -1;
|
||||
char szPrevShaderKey[128];
|
||||
szPrevShaderKey[0] = '\0';
|
||||
int cSubmeshes = m_mesh.getSubmeshes().size();
|
||||
int cSubmeshes = m_pMesh->getSubmeshes().size();
|
||||
if(bRenderShadowMap) {
|
||||
for(int iSubmesh=0; iSubmesh<cSubmeshes; iSubmesh++) {
|
||||
KRMaterial *pMaterial = m_materials[iSubmesh];
|
||||
@@ -79,7 +80,7 @@ void KRModel::render(KRCamera *pCamera, KRMaterialManager *pMaterialManager, boo
|
||||
|
||||
if(pMaterial->isTransparent()) {
|
||||
// Exclude transparent and semi-transparent meshes from shadow maps
|
||||
m_mesh.renderSubmesh(iSubmesh, &iPrevBuffer);
|
||||
m_pMesh->renderSubmesh(iSubmesh, &iPrevBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ void KRModel::render(KRCamera *pCamera, KRMaterialManager *pMaterialManager, boo
|
||||
|
||||
if(pMaterial != NULL && pMaterial == (*mat_itr)) {
|
||||
pMaterial->bind(&pPrevBoundMaterial, szPrevShaderKey, pCamera, mvpMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers);
|
||||
m_mesh.renderSubmesh(iSubmesh, &iPrevBuffer);
|
||||
m_pMesh->renderSubmesh(iSubmesh, &iPrevBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,5 +102,7 @@ void KRModel::render(KRCamera *pCamera, KRMaterialManager *pMaterialManager, boo
|
||||
}
|
||||
|
||||
KRMesh *KRModel::getMesh() {
|
||||
return &m_mesh;
|
||||
return m_pMesh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#import <set>
|
||||
#import <string>
|
||||
#import "KRMesh.h"
|
||||
#import "KRVector2.h"
|
||||
|
||||
#import "KREngine-common.h"
|
||||
|
||||
@@ -60,7 +61,7 @@ private:
|
||||
|
||||
vector<KRMaterial *> m_materials;
|
||||
set<KRMaterial *> m_uniqueMaterials;
|
||||
KRMesh m_mesh;
|
||||
KRMesh *m_pMesh;
|
||||
|
||||
};
|
||||
|
||||
|
||||
302
KREngine/KREngine/Classes/KRResource+fbx.cpp
Normal file
302
KREngine/KREngine/Classes/KRResource+fbx.cpp
Normal file
@@ -0,0 +1,302 @@
|
||||
//
|
||||
// KRResource+fbx.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <vector.h>
|
||||
|
||||
#include <fbxsdk.h>
|
||||
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRMesh.h"
|
||||
|
||||
#ifdef IOS_REF
|
||||
#undef IOS_REF
|
||||
#define IOS_REF (*(pSdkManager->GetIOSettings()))
|
||||
#endif
|
||||
|
||||
void InitializeSdkObjects(KFbxSdkManager*& pSdkManager, KFbxScene*& pScene);
|
||||
void DestroySdkObjects(KFbxSdkManager* pSdkManager);
|
||||
bool LoadScene(KFbxSdkManager* pSdkManager, KFbxDocument* pScene, const char* pFilename);
|
||||
void LoadNode(std::vector<KRResource *> &resources, KFbxGeometryConverter *pGeometryConverter, KFbxNode* pNode);
|
||||
void LoadMesh(std::vector<KRResource *> &resources, KFbxGeometryConverter *pGeometryConverter, KFbxNode* pNode);
|
||||
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadFbx(const std::string& path)
|
||||
{
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
|
||||
KFbxSdkManager* lSdkManager = NULL;
|
||||
KFbxScene* pScene = NULL;
|
||||
bool lResult;
|
||||
KFbxGeometryConverter *pGeometryConverter = NULL;
|
||||
|
||||
// Prepare the FBX SDK.
|
||||
InitializeSdkObjects(lSdkManager, pScene);
|
||||
|
||||
// Initialize Geometry Converter
|
||||
pGeometryConverter = new KFbxGeometryConverter(lSdkManager);
|
||||
|
||||
// Load the scene.
|
||||
lResult = LoadScene(lSdkManager, pScene, path.c_str());
|
||||
|
||||
|
||||
// ----====---- Walk Through Scene ----====----
|
||||
|
||||
int i;
|
||||
KFbxNode* pNode = pScene->GetRootNode();
|
||||
|
||||
if(pNode)
|
||||
{
|
||||
for(i = 0; i < pNode->GetChildCount(); i++)
|
||||
{
|
||||
LoadNode(resources, pGeometryConverter, pNode->GetChild(i));
|
||||
}
|
||||
}
|
||||
|
||||
DestroySdkObjects(lSdkManager);
|
||||
|
||||
/*
|
||||
|
||||
KRMesh *new_mesh = new KRMesh(KRResource::GetFileBase(path));
|
||||
|
||||
std::vector<KRVector3> vertices;
|
||||
std::vector<KRVector2> uva;
|
||||
std::vector<KRVector3> normals;
|
||||
std::vector<KRVector3> tangents;
|
||||
std::vector<int> submesh_lengths;
|
||||
std::vector<int> submesh_starts;
|
||||
std::vector<std::string> material_names;
|
||||
|
||||
new_mesh->LoadData(vertices, uva, normals, tangents, submesh_starts, submesh_lengths, material_names);
|
||||
resources.push_back(new_mesh);
|
||||
*/
|
||||
return resources;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void InitializeSdkObjects(KFbxSdkManager*& pSdkManager, KFbxScene*& pScene)
|
||||
{
|
||||
// The first thing to do is to create the FBX SDK manager which is the
|
||||
// object allocator for almost all the classes in the SDK.
|
||||
pSdkManager = KFbxSdkManager::Create();
|
||||
|
||||
if (!pSdkManager)
|
||||
{
|
||||
printf("Unable to create the FBX SDK manager\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// create an IOSettings object
|
||||
KFbxIOSettings * ios = KFbxIOSettings::Create(pSdkManager, IOSROOT );
|
||||
pSdkManager->SetIOSettings(ios);
|
||||
|
||||
// Load plugins from the executable directory
|
||||
KString lPath = KFbxGetApplicationDirectory();
|
||||
#if defined(KARCH_ENV_WIN)
|
||||
KString lExtension = "dll";
|
||||
#elif defined(KARCH_ENV_MACOSX)
|
||||
KString lExtension = "dylib";
|
||||
#elif defined(KARCH_ENV_LINUX)
|
||||
KString lExtension = "so";
|
||||
#endif
|
||||
pSdkManager->LoadPluginsDirectory(lPath.Buffer(), lExtension.Buffer());
|
||||
|
||||
// Create the entity that will hold the scene.
|
||||
pScene = KFbxScene::Create(pSdkManager,"");
|
||||
}
|
||||
|
||||
void DestroySdkObjects(KFbxSdkManager* pSdkManager)
|
||||
{
|
||||
// Delete the FBX SDK manager. All the objects that have been allocated
|
||||
// using the FBX SDK manager and that haven't been explicitly destroyed
|
||||
// are automatically destroyed at the same time.
|
||||
if (pSdkManager) pSdkManager->Destroy();
|
||||
pSdkManager = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool LoadScene(KFbxSdkManager* pSdkManager, KFbxDocument* pScene, const char* pFilename)
|
||||
{
|
||||
int lFileMajor, lFileMinor, lFileRevision;
|
||||
int lSDKMajor, lSDKMinor, lSDKRevision;
|
||||
//int lFileFormat = -1;
|
||||
int i, lAnimStackCount;
|
||||
bool lStatus;
|
||||
char lPassword[1024];
|
||||
|
||||
// Get the file version number generate by the FBX SDK.
|
||||
KFbxSdkManager::GetFileFormatVersion(lSDKMajor, lSDKMinor, lSDKRevision);
|
||||
|
||||
// Create an importer.
|
||||
KFbxImporter* lImporter = KFbxImporter::Create(pSdkManager,"");
|
||||
|
||||
// Initialize the importer by providing a filename.
|
||||
const bool lImportStatus = lImporter->Initialize(pFilename, -1, pSdkManager->GetIOSettings());
|
||||
lImporter->GetFileVersion(lFileMajor, lFileMinor, lFileRevision);
|
||||
|
||||
if( !lImportStatus )
|
||||
{
|
||||
printf("Call to KFbxImporter::Initialize() failed.\n");
|
||||
printf("Error returned: %s\n\n", lImporter->GetLastErrorString());
|
||||
|
||||
if (lImporter->GetLastErrorID() == KFbxIO::eFILE_VERSION_NOT_SUPPORTED_YET ||
|
||||
lImporter->GetLastErrorID() == KFbxIO::eFILE_VERSION_NOT_SUPPORTED_ANYMORE)
|
||||
{
|
||||
printf("FBX version number for this FBX SDK is %d.%d.%d\n", lSDKMajor, lSDKMinor, lSDKRevision);
|
||||
printf("FBX version number for file %s is %d.%d.%d\n\n", pFilename, lFileMajor, lFileMinor, lFileRevision);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("FBX version number for this FBX SDK is %d.%d.%d\n", lSDKMajor, lSDKMinor, lSDKRevision);
|
||||
|
||||
if (lImporter->IsFBX())
|
||||
{
|
||||
printf("FBX version number for file %s is %d.%d.%d\n\n", pFilename, lFileMajor, lFileMinor, lFileRevision);
|
||||
|
||||
// From this point, it is possible to access animation stack information without
|
||||
// the expense of loading the entire file.
|
||||
|
||||
printf("Animation Stack Information\n");
|
||||
|
||||
lAnimStackCount = lImporter->GetAnimStackCount();
|
||||
|
||||
printf(" Number of Animation Stacks: %d\n", lAnimStackCount);
|
||||
printf(" Current Animation Stack: \"%s\"\n", lImporter->GetActiveAnimStackName().Buffer());
|
||||
printf("\n");
|
||||
|
||||
for(i = 0; i < lAnimStackCount; i++)
|
||||
{
|
||||
KFbxTakeInfo* lTakeInfo = lImporter->GetTakeInfo(i);
|
||||
|
||||
printf(" Animation Stack %d\n", i);
|
||||
printf(" Name: \"%s\"\n", lTakeInfo->mName.Buffer());
|
||||
printf(" Description: \"%s\"\n", lTakeInfo->mDescription.Buffer());
|
||||
|
||||
// Change the value of the import name if the animation stack should be imported
|
||||
// under a different name.
|
||||
printf(" Import Name: \"%s\"\n", lTakeInfo->mImportName.Buffer());
|
||||
|
||||
// Set the value of the import state to false if the animation stack should be not
|
||||
// be imported.
|
||||
printf(" Import State: %s\n", lTakeInfo->mSelect ? "true" : "false");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Set the import states. By default, the import states are always set to
|
||||
// true. The code below shows how to change these states.
|
||||
IOS_REF.SetBoolProp(IMP_FBX_MATERIAL, true);
|
||||
IOS_REF.SetBoolProp(IMP_FBX_TEXTURE, true);
|
||||
IOS_REF.SetBoolProp(IMP_FBX_LINK, true);
|
||||
IOS_REF.SetBoolProp(IMP_FBX_SHAPE, true);
|
||||
IOS_REF.SetBoolProp(IMP_FBX_GOBO, true);
|
||||
IOS_REF.SetBoolProp(IMP_FBX_ANIMATION, true);
|
||||
IOS_REF.SetBoolProp(IMP_FBX_GLOBAL_SETTINGS, true);
|
||||
}
|
||||
|
||||
// Import the scene.
|
||||
lStatus = lImporter->Import(pScene);
|
||||
|
||||
if(lStatus == false && lImporter->GetLastErrorID() == KFbxIO::ePASSWORD_ERROR)
|
||||
{
|
||||
printf("Please enter password: ");
|
||||
|
||||
lPassword[0] = '\0';
|
||||
|
||||
scanf("%s", lPassword);
|
||||
KString lString(lPassword);
|
||||
|
||||
IOS_REF.SetStringProp(IMP_FBX_PASSWORD, lString);
|
||||
IOS_REF.SetBoolProp(IMP_FBX_PASSWORD_ENABLE, true);
|
||||
|
||||
lStatus = lImporter->Import(pScene);
|
||||
|
||||
if(lStatus == false && lImporter->GetLastErrorID() == KFbxIO::ePASSWORD_ERROR)
|
||||
{
|
||||
printf("\nPassword is wrong, import aborted.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the importer.
|
||||
lImporter->Destroy();
|
||||
|
||||
return lStatus;
|
||||
}
|
||||
|
||||
void LoadNode(std::vector<KRResource *> &resources, KFbxGeometryConverter *pGeometryConverter, KFbxNode* pNode) {
|
||||
KFbxVector4 lTmpVector;
|
||||
|
||||
/*
|
||||
lTmpVector = pNode->GetGeometricTranslation(KFbxNode::eSOURCE_SET);
|
||||
printf(" Translation: %f %f %f\n", lTmpVector[0], lTmpVector[1], lTmpVector[2]);
|
||||
lTmpVector = pNode->GetGeometricRotation(KFbxNode::eSOURCE_SET);
|
||||
printf(" Rotation: %f %f %f\n", lTmpVector[0], lTmpVector[1], lTmpVector[2]);
|
||||
lTmpVector = pNode->GetGeometricScaling(KFbxNode::eSOURCE_SET);
|
||||
printf(" Scaling: %f %f %f\n", lTmpVector[0], lTmpVector[1], lTmpVector[2]);
|
||||
*/
|
||||
|
||||
KFbxNodeAttribute::EAttributeType attribute_type = (pNode->GetNodeAttribute()->GetAttributeType());
|
||||
switch(attribute_type) {
|
||||
case KFbxNodeAttribute::eMESH:
|
||||
LoadMesh(resources, pGeometryConverter, pNode);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Load child nodes
|
||||
for(int i = 0; i < pNode->GetChildCount(); i++)
|
||||
{
|
||||
LoadNode(resources, pGeometryConverter, pNode->GetChild(i));
|
||||
}
|
||||
}
|
||||
|
||||
void LoadMesh(std::vector<KRResource *> &resources, KFbxGeometryConverter *pGeometryConverter, KFbxNode* pNode) {
|
||||
printf("Mesh: %s\n", pNode->GetName());
|
||||
KFbxMesh* pSourceMesh = (KFbxMesh*) pNode->GetNodeAttribute();
|
||||
KFbxMesh* pMesh = pGeometryConverter->TriangulateMesh(pSourceMesh);
|
||||
|
||||
KFbxVector4* control_points = pMesh->GetControlPoints();
|
||||
|
||||
int polygon_count = pMesh->GetPolygonCount();
|
||||
|
||||
printf(" Polygon Count: %i (before triangulation: %i)\n", polygon_count, pSourceMesh->GetPolygonCount());
|
||||
|
||||
std::vector<KRVector3> vertices;
|
||||
std::vector<KRVector2> uva;
|
||||
std::vector<KRVector3> normals;
|
||||
std::vector<KRVector3> tangents;
|
||||
std::vector<int> submesh_lengths;
|
||||
std::vector<int> submesh_starts;
|
||||
std::vector<std::string> material_names;
|
||||
|
||||
for(int iPolygon = 0; iPolygon < polygon_count; iPolygon++) {
|
||||
int lPolygonSize = pMesh->GetPolygonSize(iPolygon);
|
||||
if(lPolygonSize != 3) {
|
||||
assert(lPolygonSize == 3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KRMesh *new_mesh = new KRMesh(pNode->GetName());
|
||||
new_mesh->LoadData(vertices, uva, normals, tangents, submesh_starts, submesh_lengths, material_names);
|
||||
resources.push_back(new_mesh);
|
||||
}
|
||||
|
||||
362
KREngine/KREngine/Classes/KRResource+obj.cpp
Normal file
362
KREngine/KREngine/Classes/KRResource+obj.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
//
|
||||
// KRResource_obj.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <vector.h>
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRMesh.h"
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadObj(const std::string& path)
|
||||
{
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
KRMesh *new_mesh = new KRMesh(KRResource::GetFileBase(path));
|
||||
resources.push_back(new_mesh);
|
||||
std::vector<KRVector3> vertices;
|
||||
std::vector<KRVector2> uva;
|
||||
std::vector<KRVector3> normals;
|
||||
std::vector<KRVector3> tangents;
|
||||
std::vector<int> submesh_lengths;
|
||||
std::vector<int> submesh_starts;
|
||||
std::vector<std::string> material_names;
|
||||
|
||||
std::vector<std::string> material_names_t;
|
||||
|
||||
int fdFile = 0;
|
||||
int fileSize = 0;
|
||||
void *pFile = NULL;
|
||||
char szSymbol[500][64];
|
||||
|
||||
int *pFaces = NULL;
|
||||
|
||||
vector<KRMesh::pack_material *> m_materials;
|
||||
|
||||
struct stat statbuf;
|
||||
fdFile = open(path.c_str(), O_RDONLY);
|
||||
if(fdFile >= 0) {
|
||||
if(fstat(fdFile, &statbuf) >= 0) {
|
||||
if ((pFile = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fdFile, 0)) == (caddr_t) -1) {
|
||||
} else {
|
||||
fileSize = statbuf.st_size;
|
||||
|
||||
// -----=====----- Get counts -----=====-----
|
||||
|
||||
int cVertexData = 0;
|
||||
|
||||
|
||||
int cFaces = 1;
|
||||
int cMaterialFaceStart = 1;
|
||||
|
||||
char *pScan = (char *)pFile;
|
||||
char *pEnd = (char *)pFile + fileSize;
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||
cVertexData += cFaceVertexes;
|
||||
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(cMaterialFaceStart - cFaces > 0) {
|
||||
cFaces++;
|
||||
|
||||
}
|
||||
material_names_t.push_back(std::string(szSymbol[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----=====----- Populate vertexes and faces -----=====-----
|
||||
|
||||
int *pFaces = (int *)malloc(sizeof(int *) * (cFaces + 1));
|
||||
|
||||
|
||||
std::vector<KRVector3> indexed_vertices;
|
||||
std::vector<KRVector2> indexed_uva;
|
||||
std::vector<KRVector3> indexed_normals;
|
||||
|
||||
int *pFace = pFaces;
|
||||
int *pMaterialFaces = pFace++;
|
||||
*pMaterialFaces = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// --------
|
||||
|
||||
pScan = (char *)pFile;
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
float x, y, z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_vertices.push_back(KRVector3(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
char *pChar = szSymbol[1];
|
||||
float u,v;
|
||||
|
||||
u = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
v = strtof(pChar, &pChar);
|
||||
indexed_uva.push_back(KRVector2(u,v));
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
float x,y,z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_normals.push_back(KRVector3(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertices = cSymbols - 1;
|
||||
|
||||
*pFace++ = cFaceVertices;
|
||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||
char *pChar = szSymbol[iSymbol];
|
||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
while(*pChar == '/') {
|
||||
pChar++;
|
||||
strtol(pChar, &pChar, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(pFace - pMaterialFaces > 1) {
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
pMaterialFaces = pFace++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
*pFace++ = 0;
|
||||
|
||||
|
||||
int iVertex = 0;
|
||||
|
||||
|
||||
std::vector<std::string>::iterator material_itr = material_names_t.begin();
|
||||
KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 64, 0);
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 64);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
|
||||
|
||||
pFace = pFaces;
|
||||
while(*pFace != 0 && iVertex < cVertexData) {
|
||||
pMaterial->start_vertex = iVertex;
|
||||
|
||||
int *pMaterialEndFace = pFace + *pFace++;
|
||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||
int cFaceVertexes = *pFace;
|
||||
KRVector3 firstFaceVertex;
|
||||
KRVector3 prevFaceVertex;
|
||||
KRVector3 firstFaceNormal;
|
||||
KRVector3 prevFaceNormal;
|
||||
KRVector2 firstFaceUva;
|
||||
KRVector2 prevFaceUva;
|
||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||
if(iFaceVertex > 2) {
|
||||
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
|
||||
iVertex+=2;
|
||||
|
||||
vertices.push_back(firstFaceVertex);
|
||||
uva.push_back(firstFaceUva);
|
||||
normals.push_back(firstFaceNormal);
|
||||
|
||||
vertices.push_back(prevFaceVertex);
|
||||
uva.push_back(prevFaceUva);
|
||||
normals.push_back(prevFaceNormal);
|
||||
}
|
||||
KRVector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
||||
KRVector2 new_uva;
|
||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
||||
}
|
||||
KRVector3 normal;
|
||||
if(pFace[iFaceVertex*3+3] >= 0){
|
||||
KRVector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
|
||||
}
|
||||
|
||||
vertices.push_back(vertex);
|
||||
uva.push_back(new_uva);
|
||||
normals.push_back(normal);
|
||||
|
||||
if(iFaceVertex==0) {
|
||||
firstFaceVertex = vertex;
|
||||
firstFaceUva = new_uva;
|
||||
firstFaceNormal = normal;
|
||||
}
|
||||
prevFaceVertex = vertex;
|
||||
prevFaceUva = new_uva;
|
||||
prevFaceNormal = normal;
|
||||
|
||||
iVertex++;
|
||||
}
|
||||
pFace += cFaceVertexes * 3 + 1;
|
||||
}
|
||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||
if(*pFace != 0) {
|
||||
pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 64, 0);
|
||||
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 64);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
|
||||
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
|
||||
if(pNewMaterial->vertex_count > 0) {
|
||||
material_names.push_back(std::string(pNewMaterial->szName));
|
||||
submesh_starts.push_back(pNewMaterial->start_vertex);
|
||||
submesh_lengths.push_back(pNewMaterial->vertex_count);
|
||||
}
|
||||
delete pNewMaterial;
|
||||
}
|
||||
|
||||
new_mesh->LoadData(vertices, uva, normals, tangents, submesh_starts, submesh_lengths, material_names);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(pFile != NULL) {
|
||||
munmap(pFile, fileSize);
|
||||
}
|
||||
|
||||
if(fdFile != 0) {
|
||||
close(fdFile);
|
||||
}
|
||||
|
||||
if(pFaces) {
|
||||
free(pFaces);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
70
KREngine/KREngine/Classes/KRResource.cpp
Normal file
70
KREngine/KREngine/Classes/KRResource.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// KRResource.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#import "KRResource.h"
|
||||
|
||||
KRResource::KRResource(std::string name) {
|
||||
m_name = name;
|
||||
}
|
||||
KRResource::~KRResource() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRResource::getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string KRResource::GetFileExtension(const std::string& name)
|
||||
{
|
||||
if(name.find_last_of(".") != std::string::npos) {
|
||||
return name.substr(name.find_last_of(".")+1);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRResource::GetFileBase(const std::string& name)
|
||||
{
|
||||
std::string f = name;
|
||||
// Strip off directory
|
||||
if(f.find_last_of("/") != std::string::npos) {
|
||||
f = f.substr(f.find_last_of("/") + 1);
|
||||
}
|
||||
|
||||
// Strip off extension
|
||||
if(f.find_last_of(".") != std::string::npos) {
|
||||
f = f.substr(0, f.find_last_of("."));
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
std::string KRResource::GetFilePath(const std::string& name)
|
||||
{
|
||||
if(name.find_last_of("/") != std::string::npos) {
|
||||
return name.substr(0, name.find_last_of("/"));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<KRResource *> KRResource::Load(const std::string& path)
|
||||
{
|
||||
std::vector<KRResource *> resources;
|
||||
std::string extension = GetFileExtension(path);
|
||||
if(extension.compare("obj") == 0) {
|
||||
return LoadObj(path);
|
||||
} else if(extension.compare("fbx") == 0) {
|
||||
return LoadFbx(path);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
43
KREngine/KREngine/Classes/KRResource.h
Normal file
43
KREngine/KREngine/Classes/KRResource.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// KRResource.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#import <stdint.h>
|
||||
#import <vector>
|
||||
#import <set>
|
||||
#import <list>
|
||||
#import <string>
|
||||
#import "KREngine-common.h"
|
||||
|
||||
#ifndef KREngine_KRResource_h
|
||||
#define KREngine_KRResource_h
|
||||
|
||||
class KRResource
|
||||
{
|
||||
public:
|
||||
std::string getName();
|
||||
|
||||
static std::string GetFileExtension(const std::string& name);
|
||||
static std::string GetFileBase(const std::string& name);
|
||||
static std::string GetFilePath(const std::string& name);
|
||||
|
||||
static std::vector<KRResource *> Load(const std::string& path);
|
||||
|
||||
virtual ~KRResource();
|
||||
virtual bool save(const std::string& path) = 0;
|
||||
protected:
|
||||
KRResource(std::string name);
|
||||
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
|
||||
static std::vector<KRResource *> LoadObj(const std::string& path);
|
||||
static std::vector<KRResource *> LoadFbx(const std::string& path);
|
||||
};
|
||||
|
||||
#endif
|
||||
25
KREngine/KREngine/Classes/KRVector2.cpp
Normal file
25
KREngine/KREngine/Classes/KRVector2.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// KRVector2.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "KRVector2.h"
|
||||
|
||||
KRVector2::KRVector2() {
|
||||
x = 0.0;
|
||||
y = 0.0;
|
||||
}
|
||||
|
||||
KRVector2::KRVector2(float X, float Y) {
|
||||
x = X;
|
||||
y = Y;
|
||||
}
|
||||
|
||||
KRVector2::~KRVector2() {
|
||||
|
||||
}
|
||||
25
KREngine/KREngine/Classes/KRVector2.h
Normal file
25
KREngine/KREngine/Classes/KRVector2.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// KRVector2.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KREngine_KRVector2_h
|
||||
#define KREngine_KRVector2_h
|
||||
|
||||
class KRVector2 {
|
||||
public:
|
||||
float x, y;
|
||||
KRVector2();
|
||||
KRVector2(float X, float Y);
|
||||
~KRVector2();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -40,8 +40,9 @@
|
||||
#include <vector.h>
|
||||
|
||||
#include "KROBJPacker.h"
|
||||
#import <KREngine_osx/KRVector2.h>
|
||||
#import <KREngine_osx/KRVector3.h>
|
||||
|
||||
#import <KREngine_osx/KRMesh.h>
|
||||
|
||||
KROBJPacker::KROBJPacker() {
|
||||
|
||||
@@ -52,461 +53,36 @@ KROBJPacker::~KROBJPacker() {
|
||||
}
|
||||
|
||||
void KROBJPacker::pack(const char *szPath) {
|
||||
int fdFile = 0;
|
||||
int fileSize = 0;
|
||||
void *pFile = NULL;
|
||||
char szSymbol[16][64];
|
||||
std::cout << "Reading " << szPath << " ...\n";
|
||||
std::string base_path = KRResource::GetFilePath(szPath);
|
||||
|
||||
std::vector<std::string> materials;
|
||||
vector<KRResource *> resources = KRResource::Load(szPath);
|
||||
|
||||
Vertex3D *pVertices = NULL;
|
||||
KRVector3D *pNormals = NULL;
|
||||
TexCoord *pTexCoords = NULL;
|
||||
int *pFaces = NULL;
|
||||
|
||||
vector<pack_material *> m_materials;
|
||||
VertexData *m_pVertexData = NULL;
|
||||
|
||||
pack_header header;
|
||||
strcpy(header.szTag, "KROBJPACK1.0 ");
|
||||
|
||||
struct stat statbuf;
|
||||
fdFile = open(szPath, O_RDONLY);
|
||||
if(fdFile >= 0) {
|
||||
if(fstat(fdFile, &statbuf) >= 0) {
|
||||
if ((pFile = mmap (0, statbuf.st_size, PROT_READ, MAP_SHARED, fdFile, 0)) == (caddr_t) -1) {
|
||||
try {
|
||||
vector<KRResource *>::iterator resource_itr = resources.begin();
|
||||
for(vector<KRResource *>::iterator resource_itr = resources.begin(); resource_itr != resources.end(); resource_itr++) {
|
||||
KRResource *pResource = (*resource_itr);
|
||||
std::string out_file_name = base_path;
|
||||
out_file_name.append("/output/");
|
||||
//out_file_name.append(pResource->GetFileBase(pResource->getName()));
|
||||
out_file_name.append(pResource->getName());
|
||||
out_file_name.append(".krobject");
|
||||
std::cout << "Writing " << out_file_name << " ... ";
|
||||
if(pResource->save(out_file_name)) {
|
||||
std::cout << " SUCCESS!\n";
|
||||
} else {
|
||||
fileSize = statbuf.st_size;
|
||||
|
||||
// Pass 1 - Get counts
|
||||
cout << " Pass 1 - Getting Counts\n";
|
||||
|
||||
int cVertices = 0;
|
||||
int cNormals = 0;
|
||||
int cTexCoords = 0;
|
||||
int cVertexData = 0;
|
||||
|
||||
|
||||
cVertices = 0;
|
||||
int cFaces = 1;
|
||||
int cMaterialFaceStart = 1;
|
||||
|
||||
char *pScan = (char *)pFile;
|
||||
char *pEnd = (char *)pFile + fileSize;
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
cVertices++;
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
cTexCoords++;
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
cNormals++;
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||
cVertexData += cFaceVertexes;
|
||||
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(cMaterialFaceStart - cFaces > 0) {
|
||||
cFaces++;
|
||||
|
||||
}
|
||||
materials.push_back(std::string(szSymbol[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pass 2 - Populate vertexes and faces
|
||||
cout << " Pass 2 - Populate vertexes and faces\n";
|
||||
|
||||
Vertex3D *pVertices = (Vertex3D *)malloc(sizeof(Vertex3D) * cVertices);
|
||||
KRVector3D *pNormals = (KRVector3D *)malloc(sizeof(KRVector3D) *cNormals);
|
||||
TexCoord *pTexCoords = (TexCoord *)malloc(sizeof(TexCoord) * cTexCoords);
|
||||
int *pFaces = (int *)malloc(sizeof(int *) * (cFaces + 1));
|
||||
|
||||
|
||||
Vertex3D *pVertice = pVertices;
|
||||
KRVector3D *pNormal = pNormals;
|
||||
TexCoord *pTexCoord = pTexCoords;
|
||||
int *pFace = pFaces;
|
||||
int *pMaterialFaces = pFace++;
|
||||
*pMaterialFaces = 0;
|
||||
|
||||
|
||||
std::vector<std::string>::iterator material_itr = materials.begin();
|
||||
|
||||
// --------
|
||||
|
||||
pScan = (char *)pFile;
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
char *pChar = szSymbol[1];
|
||||
pVertice -> x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
pVertice -> y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
pVertice -> z = strtof(pChar, &pChar);
|
||||
pVertice++;
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
char *pChar = szSymbol[1];
|
||||
pTexCoord -> u = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
pTexCoord -> v = strtof(pChar, &pChar);
|
||||
pTexCoord++;
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
char *pChar = szSymbol[1];
|
||||
pNormal -> x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
pNormal -> y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
pNormal -> z = strtof(pChar, &pChar);
|
||||
pNormal++;
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertices = cSymbols - 1;
|
||||
|
||||
*pFace++ = cFaceVertices;
|
||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||
char *pChar = szSymbol[iSymbol];
|
||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
while(*pChar == '/') {
|
||||
pChar++;
|
||||
strtol(pChar, &pChar, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(pFace - pMaterialFaces > 1) {
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
pMaterialFaces = pFace++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
*pFace++ = 0;
|
||||
|
||||
|
||||
m_pVertexData = (VertexData *)malloc(sizeof(VertexData) * cVertexData);
|
||||
|
||||
VertexData *pData = m_pVertexData;
|
||||
|
||||
int iVertex = 0;
|
||||
pack_material *pMaterial = new pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 64, 0);
|
||||
if(material_itr < materials.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 64);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
|
||||
|
||||
pFace = pFaces;
|
||||
while(*pFace != 0 && iVertex < cVertexData) {
|
||||
pMaterial->start_vertex = iVertex;
|
||||
|
||||
int *pMaterialEndFace = pFace + *pFace++;
|
||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||
int cFaceVertexes = *pFace;
|
||||
VertexData *pFirstFaceVertex = NULL;
|
||||
VertexData *pPrevFaceVertex = NULL;
|
||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||
if(iFaceVertex > 2) {
|
||||
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
|
||||
memcpy(pData++, pFirstFaceVertex, sizeof(VertexData));
|
||||
memcpy(pData++, pPrevFaceVertex, sizeof(VertexData));
|
||||
iVertex+=2;
|
||||
}
|
||||
Vertex3D *pVertex = pVertices + pFace[iFaceVertex*3+1];
|
||||
if(iFaceVertex==0) {
|
||||
pFirstFaceVertex = pData;
|
||||
}
|
||||
pPrevFaceVertex = pData;
|
||||
pData->vertex.x = pVertex -> x;
|
||||
pData->vertex.y = pVertex -> y;
|
||||
pData->vertex.z = pVertex -> z;
|
||||
|
||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||
TexCoord *pTexCoord = pTexCoords + pFace[iFaceVertex*3+2];
|
||||
pData->texcoord.u = pTexCoord -> u;
|
||||
pData->texcoord.v = pTexCoord -> v;
|
||||
} else {
|
||||
pData->texcoord.u = 0;
|
||||
pData->texcoord.v = 0;
|
||||
}
|
||||
|
||||
if(pFace[iFaceVertex*3+3] >= 0){
|
||||
KRVector3D *pNormal = pNormals + pFace[iFaceVertex*3+3];
|
||||
pData->normal.x = pNormal -> x;
|
||||
pData->normal.y = pNormal -> y;
|
||||
pData->normal.z = pNormal -> z;
|
||||
} else {
|
||||
pData->normal.x = 0;
|
||||
pData->normal.y = 0;
|
||||
pData->normal.z = 0;
|
||||
}
|
||||
|
||||
pData++;
|
||||
iVertex++;
|
||||
}
|
||||
pFace += cFaceVertexes * 3 + 1;
|
||||
}
|
||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||
if(*pFace != 0) {
|
||||
pMaterial = new pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 64, 0);
|
||||
|
||||
if(material_itr < materials.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 64);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
header.minx = 0.0;
|
||||
header.miny = 0.0;
|
||||
header.minz = 0.0;
|
||||
header.maxx = 0.0;
|
||||
header.maxy = 0.0;
|
||||
header.maxz = 0.0;
|
||||
|
||||
// Calculate surface normals and tangents
|
||||
cout << " Pass 3 - Calculate surface normals and tangents\n";
|
||||
|
||||
for(std::vector<pack_material *>::iterator itr = m_materials.begin(); itr != m_materials.end(); itr++) {
|
||||
VertexData *pStart = m_pVertexData + (*itr)->start_vertex;
|
||||
VertexData *pEnd = pStart + (*itr)->vertex_count;
|
||||
for(VertexData *pVertex = pStart; pVertex < pEnd; pVertex+=3) {
|
||||
if(pVertex->vertex.x < header.minx) header.minx = pVertex->vertex.x;
|
||||
if(pVertex->vertex.x > header.maxx) header.maxx = pVertex->vertex.x;
|
||||
if(pVertex->vertex.y < header.miny) header.miny = pVertex->vertex.y;
|
||||
if(pVertex->vertex.y > header.maxy) header.maxy = pVertex->vertex.y;
|
||||
if(pVertex->vertex.z < header.minz) header.minz = pVertex->vertex.z;
|
||||
if(pVertex->vertex.z > header.maxz) header.maxz = pVertex->vertex.z;
|
||||
}
|
||||
|
||||
|
||||
for(VertexData *pVertex = pStart; pVertex < pEnd; pVertex+=3) {
|
||||
KRVector3 p1(pVertex[0].vertex.x, pVertex[0].vertex.y, pVertex[0].vertex.z);
|
||||
KRVector3 p2(pVertex[1].vertex.x, pVertex[1].vertex.y, pVertex[1].vertex.z);
|
||||
KRVector3 p3(pVertex[2].vertex.x, pVertex[2].vertex.y, pVertex[2].vertex.z);
|
||||
KRVector3 v1 = p2 - p1;
|
||||
KRVector3 v2 = p3 - p1;
|
||||
|
||||
// -- Calculate normal --
|
||||
if(pVertex->normal.x == 0 && pVertex->normal.y == 0 && pVertex->normal.z == 0) {
|
||||
|
||||
|
||||
KRVector3 normal = v1.cross( v2 );
|
||||
|
||||
normal.normalize();
|
||||
|
||||
pVertex[0].normal.x = normal.x;
|
||||
pVertex[0].normal.y = normal.y;
|
||||
pVertex[0].normal.z = normal.z;
|
||||
|
||||
pVertex[1].normal.x = normal.x;
|
||||
pVertex[1].normal.y = normal.y;
|
||||
pVertex[1].normal.z = normal.z;
|
||||
|
||||
pVertex[2].normal.x = normal.x;
|
||||
pVertex[2].normal.y = normal.y;
|
||||
pVertex[2].normal.z = normal.z;
|
||||
}
|
||||
|
||||
// -- Calculate tangent vector for normal mapping --
|
||||
TexCoord st1; // = pVertex[2].texcoord;
|
||||
TexCoord st2; // = pVertex[1].texcoord;
|
||||
st1.u = pVertex[1].texcoord.u - pVertex[0].texcoord.u;
|
||||
st1.v = pVertex[1].texcoord.v - pVertex[0].texcoord.v;
|
||||
st2.u = pVertex[2].texcoord.u - pVertex[0].texcoord.u;
|
||||
st2.v = pVertex[2].texcoord.v - pVertex[0].texcoord.v;
|
||||
double coef = 1/ (st1.u * st2.v - st2.u * st1.v);
|
||||
|
||||
pVertex[0].tangent.x = coef * ((v1.x * st2.v) + (v2.x * -st1.v));
|
||||
pVertex[0].tangent.y = coef * ((v1.y * st2.v) + (v2.y * -st1.v));
|
||||
pVertex[0].tangent.z = coef * ((v1.z * st2.v) + (v2.z * -st1.v));
|
||||
|
||||
KRVector3 tangent(
|
||||
coef * ((v1.x * st2.v) + (v2.x * -st1.v)),
|
||||
coef * ((v1.y * st2.v) + (v2.y * -st1.v)),
|
||||
coef * ((v1.z * st2.v) + (v2.z * -st1.v))
|
||||
);
|
||||
|
||||
tangent.normalize();
|
||||
|
||||
pVertex[0].tangent.x = tangent.x;
|
||||
pVertex[0].tangent.y = tangent.y;
|
||||
pVertex[0].tangent.z = tangent.z;
|
||||
pVertex[1].tangent.x = tangent.x;
|
||||
pVertex[1].tangent.y = tangent.y;
|
||||
pVertex[1].tangent.z = tangent.z;
|
||||
pVertex[2].tangent.x = tangent.x;
|
||||
pVertex[2].tangent.y = tangent.y;
|
||||
pVertex[2].tangent.z = tangent.z;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Write output file
|
||||
std::string out_file_name = szPath;
|
||||
out_file_name.append(".pack");
|
||||
cout << " Writing obj.pack file:" << out_file_name << " ... \n";
|
||||
FILE *out_file = fopen(out_file_name.c_str(), "w");
|
||||
|
||||
header.material_count = 0;
|
||||
for(std::vector<pack_material *>::iterator itr = m_materials.begin(); itr != m_materials.end(); itr++) {
|
||||
pack_material *pMaterial = (*itr);
|
||||
if(pMaterial->vertex_count) { // Skip materials with no vertices
|
||||
header.material_count++;
|
||||
}
|
||||
}
|
||||
|
||||
header.vertex_count = cVertexData;
|
||||
|
||||
fwrite(&header, sizeof(header), 1, out_file);
|
||||
|
||||
for(std::vector<pack_material *>::iterator itr = m_materials.begin(); itr != m_materials.end(); itr++) {
|
||||
pack_material *pMaterial = (*itr);
|
||||
if(pMaterial->vertex_count) { // Skip materials with no vertices
|
||||
fwrite(pMaterial, sizeof(pack_material), 1, out_file);
|
||||
cout << " " << pMaterial->szName << ": " << pMaterial->vertex_count << " vertices\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fwrite(m_pVertexData, sizeof(VertexData), cVertexData, out_file);
|
||||
|
||||
fclose(out_file);
|
||||
|
||||
std::cout << " FAIL...\n";
|
||||
}
|
||||
}
|
||||
} catch(...) {
|
||||
for(vector<KRResource *>::iterator resource_itr = resources.begin(); resource_itr != resources.end(); resource_itr++) {
|
||||
KRResource *pResource = (*resource_itr);
|
||||
delete pResource;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
if(pFile != NULL) {
|
||||
munmap(pFile, fileSize);
|
||||
}
|
||||
|
||||
if(fdFile != 0) {
|
||||
close(fdFile);
|
||||
}
|
||||
|
||||
if(m_pVertexData) {
|
||||
free(m_pVertexData);
|
||||
}
|
||||
|
||||
if(pVertices) {
|
||||
free(pVertices);
|
||||
}
|
||||
if(pNormals) {
|
||||
free(pNormals);
|
||||
}
|
||||
if(pTexCoords) {
|
||||
free(pTexCoords);
|
||||
}
|
||||
if(pFaces) {
|
||||
free(pFaces);
|
||||
for(vector<KRResource *>::iterator resource_itr = resources.begin(); resource_itr != resources.end(); resource_itr++) {
|
||||
KRResource *pResource = (*resource_itr);
|
||||
delete pResource;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,37 +42,6 @@ public:
|
||||
~KROBJPacker();
|
||||
void pack(const char *szPath);
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
char szTag[16];
|
||||
float minx, miny, minz, maxx, maxy, maxz;
|
||||
int32_t vertex_count;
|
||||
int32_t material_count;
|
||||
} pack_header;
|
||||
|
||||
typedef struct {
|
||||
int32_t start_vertex;
|
||||
int32_t vertex_count;
|
||||
char szName[64];
|
||||
} pack_material;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
} Vertex3D, KRVector3D;
|
||||
|
||||
typedef struct {
|
||||
float u;
|
||||
float v;
|
||||
} TexCoord;
|
||||
|
||||
typedef struct {
|
||||
Vertex3D vertex;
|
||||
KRVector3D normal;
|
||||
KRVector3D tangent;
|
||||
TexCoord texcoord;
|
||||
} VertexData;
|
||||
};
|
||||
|
||||
#endif // OBJPACKER_H
|
||||
@@ -41,7 +41,6 @@ int main (int argc, const char * argv[])
|
||||
} else {
|
||||
KROBJPacker p;
|
||||
for(int i=1; i < argc; i++) {
|
||||
std::cout << "Packing " << argv[i] << " ...\n";
|
||||
p.pack(argv[i]);
|
||||
}
|
||||
std::cout << "Done.\n";
|
||||
|
||||
@@ -125,7 +125,8 @@
|
||||
|
||||
KRModelManager *pModelManager = [renderEngine getModelManager];
|
||||
//m_scene.addInstance(pModelManager->getModel("fachwerkhaus12"), KRMat4());
|
||||
m_scene.addInstance(pModelManager->getModel("ballroom"), KRMat4());
|
||||
//m_scene.addInstance(pModelManager->getModel("ballroom"), KRMat4());
|
||||
m_scene.addInstance(pModelManager->getModel("HoganCombined"), KRMat4());
|
||||
|
||||
[renderEngine setNearZ: 25.0];
|
||||
[renderEngine setFarZ: 5000.0];
|
||||
|
||||
Reference in New Issue
Block a user