|
@@ -74,10 +74,19 @@ bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|
if( pos == std::string::npos)return false;
|
|
if( pos == std::string::npos)return false;
|
|
std::string extension = pFile.substr( pos);
|
|
std::string extension = pFile.substr( pos);
|
|
|
|
|
|
- return !(extension.length() != 4 || extension[0] != '.' ||
|
|
|
|
- extension[1] != 'n' && extension[1] != 'N' ||
|
|
|
|
- extension[2] != 'f' && extension[2] != 'F' ||
|
|
|
|
- extension[3] != 'f' && extension[3] != 'F');
|
|
|
|
|
|
+ // extensions: enff and nff
|
|
|
|
+ if (!extension.length() || extension[0] != '.')return false;
|
|
|
|
+ if (extension.length() == 4)
|
|
|
|
+ {
|
|
|
|
+ return !(extension[1] != 'n' && extension[1] != 'N' ||
|
|
|
|
+ extension[2] != 'f' && extension[2] != 'F' ||
|
|
|
|
+ extension[3] != 'f' && extension[3] != 'F');
|
|
|
|
+ }
|
|
|
|
+ else return !( extension.length() != 5 ||
|
|
|
|
+ extension[1] != 'e' && extension[1] != 'E' ||
|
|
|
|
+ extension[2] != 'n' && extension[2] != 'N' ||
|
|
|
|
+ extension[3] != 'f' && extension[3] != 'F' ||
|
|
|
|
+ extension[4] != 'f' && extension[4] != 'F');
|
|
}
|
|
}
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// ------------------------------------------------------------------------------------------------
|
|
@@ -87,9 +96,9 @@ bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// ------------------------------------------------------------------------------------------------
|
|
#define AI_NFF_PARSE_TRIPLE(v) \
|
|
#define AI_NFF_PARSE_TRIPLE(v) \
|
|
- AI_NFF_PARSE_FLOAT(v.x) \
|
|
|
|
- AI_NFF_PARSE_FLOAT(v.y) \
|
|
|
|
- AI_NFF_PARSE_FLOAT(v.z)
|
|
|
|
|
|
+ AI_NFF_PARSE_FLOAT(v[0]) \
|
|
|
|
+ AI_NFF_PARSE_FLOAT(v[1]) \
|
|
|
|
+ AI_NFF_PARSE_FLOAT(v[2])
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
// ------------------------------------------------------------------------------------------------
|
|
#define AI_NFF_PARSE_SHAPE_INFORMATION() \
|
|
#define AI_NFF_PARSE_SHAPE_INFORMATION() \
|
|
@@ -125,252 +134,504 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|
// the pointers below easier.
|
|
// the pointers below easier.
|
|
std::vector<MeshInfo> meshes;
|
|
std::vector<MeshInfo> meshes;
|
|
std::vector<MeshInfo> meshesWithNormals;
|
|
std::vector<MeshInfo> meshesWithNormals;
|
|
|
|
+ std::vector<MeshInfo> meshesWithUVCoords;
|
|
std::vector<MeshInfo> meshesLocked;
|
|
std::vector<MeshInfo> meshesLocked;
|
|
|
|
+
|
|
|
|
+ char line[4096];
|
|
|
|
+ const char* sz;
|
|
|
|
+
|
|
|
|
+ // camera parameters
|
|
|
|
+ aiVector3D camPos, camUp(0.f,1.f,0.f), camLookAt(0.f,0.f,1.f);
|
|
|
|
+ float angle;
|
|
|
|
+ aiVector2D resolution;
|
|
|
|
+
|
|
|
|
+ bool hasCam = false;
|
|
|
|
+
|
|
MeshInfo* currentMeshWithNormals = NULL;
|
|
MeshInfo* currentMeshWithNormals = NULL;
|
|
MeshInfo* currentMesh = NULL;
|
|
MeshInfo* currentMesh = NULL;
|
|
|
|
+ MeshInfo* currentMeshWithUVCoords = NULL;
|
|
|
|
|
|
ShadingInfo s; // current material info
|
|
ShadingInfo s; // current material info
|
|
|
|
|
|
// degree of tesselation
|
|
// degree of tesselation
|
|
unsigned int iTesselation = 4;
|
|
unsigned int iTesselation = 4;
|
|
|
|
|
|
- char line[4096];
|
|
|
|
- const char* sz;
|
|
|
|
- unsigned int sphere = 0,cylinder = 0,cone = 0,numNamed = 0,
|
|
|
|
- dodecahedron = 0,octahedron = 0,tetrahedron = 0, hexahedron = 0;
|
|
|
|
-
|
|
|
|
- while (GetNextLine(buffer,line))
|
|
|
|
|
|
+ // some temporary variables we need to parse the file
|
|
|
|
+ unsigned int sphere = 0,
|
|
|
|
+ cylinder = 0,
|
|
|
|
+ cone = 0,
|
|
|
|
+ numNamed = 0,
|
|
|
|
+ dodecahedron = 0,
|
|
|
|
+ octahedron = 0,
|
|
|
|
+ tetrahedron = 0,
|
|
|
|
+ hexahedron = 0;
|
|
|
|
+
|
|
|
|
+ // lights imported from the file
|
|
|
|
+ std::vector<Light> lights;
|
|
|
|
+
|
|
|
|
+ // check whether this is the NFF2 file format
|
|
|
|
+ if (TokenMatch(buffer,"nff",3))
|
|
{
|
|
{
|
|
- if ('p' == line[0])
|
|
|
|
|
|
+ // another NFF file format ... just a raw parser has been implemented
|
|
|
|
+ // no support for textures yet, I don't think it is worth the effort
|
|
|
|
+ // http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/nff/nff2.html
|
|
|
|
+
|
|
|
|
+ while (GetNextLine(buffer,line))
|
|
{
|
|
{
|
|
- MeshInfo* out = NULL;
|
|
|
|
- // 'pp' - polygon patch primitive
|
|
|
|
- if ('p' == line[1])
|
|
|
|
|
|
+ sz = line;
|
|
|
|
+ if (TokenMatch(sz,"version",7))
|
|
{
|
|
{
|
|
- if (meshesWithNormals.empty())
|
|
|
|
- {
|
|
|
|
- meshesWithNormals.push_back(MeshInfo(true));
|
|
|
|
- currentMeshWithNormals = &meshesWithNormals.back();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- sz = &line[2];out = currentMeshWithNormals;
|
|
|
|
|
|
+ DefaultLogger::get()->info("NFF (alt.) file format: " + std::string(sz));
|
|
}
|
|
}
|
|
- // 'p' - polygon primitive
|
|
|
|
- else
|
|
|
|
|
|
+ else if (TokenMatch(sz,"viewpos",7))
|
|
{
|
|
{
|
|
- if (meshes.empty())
|
|
|
|
- {
|
|
|
|
- meshes.push_back(MeshInfo(false));
|
|
|
|
- currentMesh = &meshes.back();
|
|
|
|
- }
|
|
|
|
- sz = &line[1];out = currentMesh;
|
|
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(camPos);
|
|
|
|
+ hasCam = true;
|
|
}
|
|
}
|
|
- SkipSpaces(sz,&sz);
|
|
|
|
- m = strtol10(sz);
|
|
|
|
-
|
|
|
|
- // ---- flip the face order
|
|
|
|
- out->vertices.resize(out->vertices.size()+m);
|
|
|
|
- if (out == currentMeshWithNormals)
|
|
|
|
|
|
+ else if (TokenMatch(sz,"viewdir",7))
|
|
{
|
|
{
|
|
- out->normals.resize(out->vertices.size());
|
|
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(camLookAt);
|
|
|
|
+ hasCam = true;
|
|
}
|
|
}
|
|
- for (unsigned int n = 0; n < m;++n)
|
|
|
|
|
|
+ else if (TokenMatch(sz,"//",2))
|
|
{
|
|
{
|
|
- if(!GetNextLine(buffer,line))
|
|
|
|
|
|
+ // comment ...
|
|
|
|
+ DefaultLogger::get()->info(sz);
|
|
|
|
+ }
|
|
|
|
+ else if (!IsSpace(*sz))
|
|
|
|
+ {
|
|
|
|
+ // must be a new object
|
|
|
|
+ meshes.push_back(MeshInfo(PatchType_Simple));
|
|
|
|
+ MeshInfo& mesh = meshes.back();
|
|
|
|
+
|
|
|
|
+ if (!GetNextLine(buffer,line))
|
|
|
|
+ {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read number of vertices");break;}
|
|
|
|
+
|
|
|
|
+ SkipSpaces(line,&sz);
|
|
|
|
+ unsigned int num = ::strtol10(sz,&sz);
|
|
|
|
+
|
|
|
|
+ std::vector<aiVector3D> tempPositions;
|
|
|
|
+ std::vector<aiVector3D> outPositions;
|
|
|
|
+ mesh.vertices.reserve(num*3);
|
|
|
|
+ mesh.colors.reserve (num*3);
|
|
|
|
+ tempPositions.reserve(num);
|
|
|
|
+ for (unsigned int i = 0; i < num; ++i)
|
|
{
|
|
{
|
|
- DefaultLogger::get()->error("NFF: Unexpected EOF was encountered");
|
|
|
|
- continue;
|
|
|
|
|
|
+ if (!GetNextLine(buffer,line))
|
|
|
|
+ {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read vertices");break;}
|
|
|
|
+
|
|
|
|
+ sz = line;
|
|
|
|
+ aiVector3D v;
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(v);
|
|
|
|
+ tempPositions.push_back(v);
|
|
}
|
|
}
|
|
|
|
+ if (!GetNextLine(buffer,line))
|
|
|
|
+ {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read number of faces");break;}
|
|
|
|
+
|
|
|
|
+ if (!num)throw new ImportErrorException("NFF2: There are zero vertices");
|
|
|
|
|
|
- aiVector3D v; sz = &line[0];
|
|
|
|
- AI_NFF_PARSE_TRIPLE(v);
|
|
|
|
- out->vertices[out->vertices.size()-n-1] = v;
|
|
|
|
|
|
+ SkipSpaces(line,&sz);
|
|
|
|
+ num = ::strtol10(sz,&sz);
|
|
|
|
+ mesh.faces.reserve(num);
|
|
|
|
|
|
- if (out == currentMeshWithNormals)
|
|
|
|
|
|
+ for (unsigned int i = 0; i < num; ++i)
|
|
{
|
|
{
|
|
- AI_NFF_PARSE_TRIPLE(v);
|
|
|
|
- out->normals[out->vertices.size()-n-1] = v;
|
|
|
|
|
|
+ if (!GetNextLine(buffer,line))
|
|
|
|
+ {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read faces");break;}
|
|
|
|
+
|
|
|
|
+ SkipSpaces(line,&sz);
|
|
|
|
+ unsigned int idx, numIdx = ::strtol10(sz,&sz);
|
|
|
|
+ if (numIdx)
|
|
|
|
+ {
|
|
|
|
+ mesh.faces.push_back(numIdx);
|
|
|
|
+ for (unsigned int a = 0; a < numIdx;++a)
|
|
|
|
+ {
|
|
|
|
+ SkipSpaces(sz,&sz);
|
|
|
|
+ idx = ::strtol10(sz,&sz);
|
|
|
|
+ if (idx >= (unsigned int)tempPositions.size())
|
|
|
|
+ {
|
|
|
|
+ DefaultLogger::get()->error("NFF2: Index overflow");
|
|
|
|
+ idx = 0;
|
|
|
|
+ }
|
|
|
|
+ mesh.vertices.push_back(tempPositions[idx]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ SkipSpaces(sz,&sz);
|
|
|
|
+ idx = ::strtol_cppstyle(sz,&sz);
|
|
|
|
+ aiColor4D clr;
|
|
|
|
+ clr.r = ((numIdx >> 8u) & 0xf) / 16.f;
|
|
|
|
+ clr.g = ((numIdx >> 4u) & 0xf) / 16.f;
|
|
|
|
+ clr.b = ((numIdx) & 0xf) / 16.f;
|
|
|
|
+ clr.a = 1.f;
|
|
|
|
+ for (unsigned int a = 0; a < numIdx;++a)
|
|
|
|
+ mesh.colors.push_back(clr);
|
|
}
|
|
}
|
|
|
|
+ if (!num)throw new ImportErrorException("NFF2: There are zero faces");
|
|
}
|
|
}
|
|
- out->faces.push_back(m);
|
|
|
|
}
|
|
}
|
|
- // 'f' - shading information block
|
|
|
|
- else if ('f' == line[0] && IsSpace(line[1]))
|
|
|
|
|
|
+ camLookAt = camLookAt + camPos;
|
|
|
|
+ }
|
|
|
|
+ else // "Normal" Neutral file format that is quite more common
|
|
|
|
+ {
|
|
|
|
+ while (GetNextLine(buffer,line))
|
|
{
|
|
{
|
|
- SkipSpaces(&line[1],&sz);
|
|
|
|
-
|
|
|
|
- // read just the RGB colors, the rest is ignored for the moment
|
|
|
|
- sz = fast_atof_move(sz, (float&)s.color.r);
|
|
|
|
- SkipSpaces(&sz);
|
|
|
|
- sz = fast_atof_move(sz, (float&)s.color.g);
|
|
|
|
- SkipSpaces(&sz);
|
|
|
|
- sz = fast_atof_move(sz, (float&)s.color.b);
|
|
|
|
-
|
|
|
|
- // check whether we have this material already -
|
|
|
|
- // although we have the RRM-Step, this is necessary here.
|
|
|
|
- // otherwise we would generate hundreds of small meshes
|
|
|
|
- // with just a few faces - this is surely never wanted.
|
|
|
|
- currentMesh = currentMeshWithNormals = NULL;
|
|
|
|
- for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end();
|
|
|
|
- it != end;++it)
|
|
|
|
|
|
+ sz = line;
|
|
|
|
+ if ('p' == line[0] || TokenMatch(sz,"tpp",3))
|
|
{
|
|
{
|
|
- if ((*it).bLocked)continue;
|
|
|
|
- if ((*it).shader == s)
|
|
|
|
|
|
+ MeshInfo* out = NULL;
|
|
|
|
+
|
|
|
|
+ // 'tpp' - texture polygon patch primitive
|
|
|
|
+ if ('t' == line[0])
|
|
{
|
|
{
|
|
- if ((*it).bHasNormals)currentMeshWithNormals = &(*it);
|
|
|
|
- else currentMesh = &(*it);
|
|
|
|
|
|
+ if (meshesWithUVCoords.empty())
|
|
|
|
+ {
|
|
|
|
+ meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
|
|
|
|
+ currentMeshWithUVCoords = &meshesWithUVCoords.back();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ out = currentMeshWithUVCoords;
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ // 'pp' - polygon patch primitive
|
|
|
|
+ else if ('p' == line[1])
|
|
|
|
+ {
|
|
|
|
+ if (meshesWithNormals.empty())
|
|
|
|
+ {
|
|
|
|
+ meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
|
|
|
|
+ currentMeshWithNormals = &meshesWithNormals.back();
|
|
|
|
+ }
|
|
|
|
|
|
- if (!currentMesh)
|
|
|
|
- {
|
|
|
|
- meshes.push_back(MeshInfo(false));
|
|
|
|
- currentMesh = &meshes.back();
|
|
|
|
- currentMesh->shader = s;
|
|
|
|
- }
|
|
|
|
|
|
+ sz = &line[2];out = currentMeshWithNormals;
|
|
|
|
+ }
|
|
|
|
+ // 'p' - polygon primitive
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ if (meshes.empty())
|
|
|
|
+ {
|
|
|
|
+ meshes.push_back(MeshInfo(PatchType_Simple));
|
|
|
|
+ currentMesh = &meshes.back();
|
|
|
|
+ }
|
|
|
|
+ sz = &line[1];out = currentMesh;
|
|
|
|
+ }
|
|
|
|
+ SkipSpaces(sz,&sz);
|
|
|
|
+ m = strtol10(sz);
|
|
|
|
|
|
- if (!currentMeshWithNormals)
|
|
|
|
|
|
+ // ---- flip the face order
|
|
|
|
+ out->vertices.resize(out->vertices.size()+m);
|
|
|
|
+ if (out != currentMesh)
|
|
|
|
+ {
|
|
|
|
+ out->normals.resize(out->vertices.size());
|
|
|
|
+ }
|
|
|
|
+ if (out == currentMeshWithUVCoords)
|
|
|
|
+ {
|
|
|
|
+ out->uvs.resize(out->vertices.size());
|
|
|
|
+ }
|
|
|
|
+ for (unsigned int n = 0; n < m;++n)
|
|
|
|
+ {
|
|
|
|
+ if(!GetNextLine(buffer,line))
|
|
|
|
+ {
|
|
|
|
+ DefaultLogger::get()->error("NFF: Unexpected EOF was encountered");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ aiVector3D v; sz = &line[0];
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(v);
|
|
|
|
+ out->vertices[out->vertices.size()-n-1] = v;
|
|
|
|
+
|
|
|
|
+ if (out != currentMesh)
|
|
|
|
+ {
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(v);
|
|
|
|
+ out->normals[out->vertices.size()-n-1] = v;
|
|
|
|
+ }
|
|
|
|
+ if (out == currentMeshWithUVCoords)
|
|
|
|
+ {
|
|
|
|
+ // FIX: in one test file this wraps over multiple lines
|
|
|
|
+ SkipSpaces(&sz);
|
|
|
|
+ if (IsLineEnd(*sz))
|
|
|
|
+ {
|
|
|
|
+ GetNextLine(buffer,line);
|
|
|
|
+ sz = line;
|
|
|
|
+ }
|
|
|
|
+ AI_NFF_PARSE_FLOAT(v.x);
|
|
|
|
+ SkipSpaces(&sz);
|
|
|
|
+ if (IsLineEnd(*sz))
|
|
|
|
+ {
|
|
|
|
+ GetNextLine(buffer,line);
|
|
|
|
+ sz = line;
|
|
|
|
+ }
|
|
|
|
+ AI_NFF_PARSE_FLOAT(v.y);
|
|
|
|
+ v.y = 1.f - v.y;
|
|
|
|
+ out->uvs[out->vertices.size()-n-1] = v;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ out->faces.push_back(m);
|
|
|
|
+ }
|
|
|
|
+ // 'f' - shading information block
|
|
|
|
+ else if (TokenMatch(sz,"f",1))
|
|
{
|
|
{
|
|
- meshesWithNormals.push_back(MeshInfo(true));
|
|
|
|
- currentMeshWithNormals = &meshesWithNormals.back();
|
|
|
|
- currentMeshWithNormals->shader = s;
|
|
|
|
|
|
+ float d;
|
|
|
|
+
|
|
|
|
+ // read the RGB colors
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(s.color);
|
|
|
|
+
|
|
|
|
+ // read the other properties
|
|
|
|
+ AI_NFF_PARSE_FLOAT(s.diffuse);
|
|
|
|
+ AI_NFF_PARSE_FLOAT(s.specular);
|
|
|
|
+ AI_NFF_PARSE_FLOAT(d); // skip shininess and transmittance
|
|
|
|
+ AI_NFF_PARSE_FLOAT(d);
|
|
|
|
+ AI_NFF_PARSE_FLOAT(s.refracti);
|
|
|
|
+
|
|
|
|
+ // if the next one is NOT a number we assume it is a texture file name
|
|
|
|
+ // this feature is used by some NFF files on the internet and it has
|
|
|
|
+ // been implemented as it can be really useful
|
|
|
|
+ SkipSpaces(&sz);
|
|
|
|
+ if (!IsNumeric(*sz))
|
|
|
|
+ {
|
|
|
|
+ // TODO: Support full file names with spaces and quotation marks ...
|
|
|
|
+ const char* p = sz;
|
|
|
|
+ while (!IsSpaceOrNewLine( *sz ))++sz;
|
|
|
|
+
|
|
|
|
+ unsigned int diff = (unsigned int)(sz-p);
|
|
|
|
+ if (diff)
|
|
|
|
+ {
|
|
|
|
+ s.texFile = std::string(p,diff);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ AI_NFF_PARSE_FLOAT(s.ambient); // optional
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // check whether we have this material already -
|
|
|
|
+ // although we have the RRM-Step, this is necessary here.
|
|
|
|
+ // otherwise we would generate hundreds of small meshes
|
|
|
|
+ // with just a few faces - this is surely never wanted.
|
|
|
|
+ currentMesh = currentMeshWithNormals = currentMeshWithUVCoords = NULL;
|
|
|
|
+ for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end();
|
|
|
|
+ it != end;++it)
|
|
|
|
+ {
|
|
|
|
+ if ((*it).bLocked)continue;
|
|
|
|
+ if ((*it).shader == s)
|
|
|
|
+ {
|
|
|
|
+ switch ((*it).pType)
|
|
|
|
+ {
|
|
|
|
+ case PatchType_Normals:
|
|
|
|
+ currentMeshWithNormals = &(*it);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case PatchType_Simple:
|
|
|
|
+ currentMesh = &(*it);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ currentMeshWithUVCoords = &(*it);
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!currentMesh)
|
|
|
|
+ {
|
|
|
|
+ meshes.push_back(MeshInfo(PatchType_Simple));
|
|
|
|
+ currentMesh = &meshes.back();
|
|
|
|
+ currentMesh->shader = s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!currentMeshWithNormals)
|
|
|
|
+ {
|
|
|
|
+ meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
|
|
|
|
+ currentMeshWithNormals = &meshesWithNormals.back();
|
|
|
|
+ currentMeshWithNormals->shader = s;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!currentMeshWithUVCoords)
|
|
|
|
+ {
|
|
|
|
+ meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
|
|
|
|
+ currentMeshWithUVCoords = &meshesWithUVCoords.back();
|
|
|
|
+ currentMeshWithUVCoords->shader = s;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
- // 's' - sphere
|
|
|
|
- else if ('s' == line[0] && IsSpace(line[1]))
|
|
|
|
- {
|
|
|
|
- meshesLocked.push_back(MeshInfo(false,true));
|
|
|
|
- MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
- currentMesh.shader = s;
|
|
|
|
|
|
+ // 'l' - light source
|
|
|
|
+ else if (TokenMatch(sz,"l",1))
|
|
|
|
+ {
|
|
|
|
+ lights.push_back(Light());
|
|
|
|
+ Light& light = lights.back();
|
|
|
|
|
|
- sz = &line[1];
|
|
|
|
- AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(light.position);
|
|
|
|
+ AI_NFF_PARSE_FLOAT (light.intensity);
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(light.color);
|
|
|
|
+ }
|
|
|
|
+ // 's' - sphere
|
|
|
|
+ else if (TokenMatch(sz,"s",1))
|
|
|
|
+ {
|
|
|
|
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
|
|
|
+ MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
+ currentMesh.shader = s;
|
|
|
|
|
|
- // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
- StandardShapes::MakeSphere(iTesselation, currentMesh.vertices);
|
|
|
|
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
+ AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
- // generate a name for the mesh
|
|
|
|
- ::sprintf(currentMesh.name,"sphere_%i",sphere++);
|
|
|
|
- }
|
|
|
|
- // 'dod' - dodecahedron
|
|
|
|
- else if (!strncmp(line,"dod",3) && IsSpace(line[3]))
|
|
|
|
- {
|
|
|
|
- meshesLocked.push_back(MeshInfo(false,true));
|
|
|
|
- MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
- currentMesh.shader = s;
|
|
|
|
|
|
+ // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
+ StandardShapes::MakeSphere(iTesselation, currentMesh.vertices);
|
|
|
|
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
- sz = &line[4];
|
|
|
|
- AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
+ // generate a name for the mesh
|
|
|
|
+ ::sprintf(currentMesh.name,"sphere_%i",sphere++);
|
|
|
|
+ }
|
|
|
|
+ // 'dod' - dodecahedron
|
|
|
|
+ else if (TokenMatch(sz,"dod",3))
|
|
|
|
+ {
|
|
|
|
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
|
|
|
+ MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
+ currentMesh.shader = s;
|
|
|
|
|
|
- // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
- StandardShapes::MakeDodecahedron(currentMesh.vertices);
|
|
|
|
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
+ AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
- // generate a name for the mesh
|
|
|
|
- ::sprintf(currentMesh.name,"dodecahedron_%i",dodecahedron++);
|
|
|
|
- }
|
|
|
|
|
|
+ // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
+ StandardShapes::MakeDodecahedron(currentMesh.vertices);
|
|
|
|
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
- // 'oct' - octahedron
|
|
|
|
- else if (!strncmp(line,"oct",3) && IsSpace(line[3]))
|
|
|
|
- {
|
|
|
|
- meshesLocked.push_back(MeshInfo(false,true));
|
|
|
|
- MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
- currentMesh.shader = s;
|
|
|
|
|
|
+ // generate a name for the mesh
|
|
|
|
+ ::sprintf(currentMesh.name,"dodecahedron_%i",dodecahedron++);
|
|
|
|
+ }
|
|
|
|
|
|
- sz = &line[4];
|
|
|
|
- AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
+ // 'oct' - octahedron
|
|
|
|
+ else if (TokenMatch(sz,"oct",3))
|
|
|
|
+ {
|
|
|
|
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
|
|
|
+ MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
+ currentMesh.shader = s;
|
|
|
|
|
|
- // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
- StandardShapes::MakeOctahedron(currentMesh.vertices);
|
|
|
|
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
+ AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
- // generate a name for the mesh
|
|
|
|
- ::sprintf(currentMesh.name,"octahedron_%i",octahedron++);
|
|
|
|
- }
|
|
|
|
|
|
+ // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
+ StandardShapes::MakeOctahedron(currentMesh.vertices);
|
|
|
|
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
- // 'tet' - tetrahedron
|
|
|
|
- else if (!strncmp(line,"tet",3) && IsSpace(line[3]))
|
|
|
|
- {
|
|
|
|
- meshesLocked.push_back(MeshInfo(false,true));
|
|
|
|
- MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
- currentMesh.shader = s;
|
|
|
|
|
|
+ // generate a name for the mesh
|
|
|
|
+ ::sprintf(currentMesh.name,"octahedron_%i",octahedron++);
|
|
|
|
+ }
|
|
|
|
|
|
- sz = &line[4];
|
|
|
|
- AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
+ // 'tet' - tetrahedron
|
|
|
|
+ else if (TokenMatch(sz,"tet",3))
|
|
|
|
+ {
|
|
|
|
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
|
|
|
+ MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
+ currentMesh.shader = s;
|
|
|
|
|
|
- // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
- StandardShapes::MakeTetrahedron(currentMesh.vertices);
|
|
|
|
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
+ AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
- // generate a name for the mesh
|
|
|
|
- ::sprintf(currentMesh.name,"tetrahedron_%i",tetrahedron++);
|
|
|
|
- }
|
|
|
|
|
|
+ // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
+ StandardShapes::MakeTetrahedron(currentMesh.vertices);
|
|
|
|
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
- // 'hex' - hexahedron
|
|
|
|
- else if (!strncmp(line,"hex",3) && IsSpace(line[3]))
|
|
|
|
- {
|
|
|
|
- meshesLocked.push_back(MeshInfo(false,true));
|
|
|
|
- MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
- currentMesh.shader = s;
|
|
|
|
|
|
+ // generate a name for the mesh
|
|
|
|
+ ::sprintf(currentMesh.name,"tetrahedron_%i",tetrahedron++);
|
|
|
|
+ }
|
|
|
|
|
|
- sz = &line[4];
|
|
|
|
- AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
+ // 'hex' - hexahedron
|
|
|
|
+ else if (TokenMatch(sz,"hex",3))
|
|
|
|
+ {
|
|
|
|
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
|
|
|
+ MeshInfo& currentMesh = meshesLocked.back();
|
|
|
|
+ currentMesh.shader = s;
|
|
|
|
|
|
- // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
- StandardShapes::MakeHexahedron(currentMesh.vertices);
|
|
|
|
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
+ AI_NFF_PARSE_SHAPE_INFORMATION();
|
|
|
|
|
|
- // generate a name for the mesh
|
|
|
|
- ::sprintf(currentMesh.name,"hexahedron_%i",hexahedron++);
|
|
|
|
- }
|
|
|
|
|
|
+ // we don't need scaling or translation here - we do it in the node's transform
|
|
|
|
+ StandardShapes::MakeHexahedron(currentMesh.vertices);
|
|
|
|
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
|
|
- // 'tess' - tesselation
|
|
|
|
- else if (!strncmp(line,"tess",4) && IsSpace(line[4]))
|
|
|
|
- {
|
|
|
|
- sz = &line[5];SkipSpaces(&sz);
|
|
|
|
- iTesselation = strtol10(sz);
|
|
|
|
- }
|
|
|
|
- // 'c' - cone
|
|
|
|
- else if ('c' == line[0] && IsSpace(line[1]))
|
|
|
|
- {
|
|
|
|
- meshesLocked.push_back(MeshInfo(false,true));
|
|
|
|
- MeshInfo& currentMesh = meshes.back();
|
|
|
|
- currentMesh.shader = s;
|
|
|
|
-
|
|
|
|
- sz = &line[1];
|
|
|
|
- aiVector3D center1, center2; float radius1, radius2;
|
|
|
|
- AI_NFF_PARSE_TRIPLE(center1);
|
|
|
|
- AI_NFF_PARSE_FLOAT(radius1);
|
|
|
|
- AI_NFF_PARSE_TRIPLE(center2);
|
|
|
|
- AI_NFF_PARSE_FLOAT(radius2);
|
|
|
|
-
|
|
|
|
- // compute the center point of the cone/cylinder
|
|
|
|
- center2 = (center2-center1)/2.f;
|
|
|
|
- currentMesh.center = center1+center2;
|
|
|
|
- center1 = -center2;
|
|
|
|
-
|
|
|
|
- // generate the cone - it consists of simple triangles
|
|
|
|
- StandardShapes::MakeCone(center1, radius1, center2, radius2, iTesselation, currentMesh.vertices);
|
|
|
|
- currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
-
|
|
|
|
- // generate a name for the mesh
|
|
|
|
- if (radius1 != radius2)
|
|
|
|
- ::sprintf(currentMesh.name,"cone_%i",cone++);
|
|
|
|
- else ::sprintf(currentMesh.name,"cylinder_%i",cylinder++);
|
|
|
|
- }
|
|
|
|
- // '#' - comment
|
|
|
|
- else if ('#' == line[0])
|
|
|
|
- {
|
|
|
|
- const char* sz;SkipSpaces(&line[1],&sz);
|
|
|
|
- if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz);
|
|
|
|
|
|
+ // generate a name for the mesh
|
|
|
|
+ ::sprintf(currentMesh.name,"hexahedron_%i",hexahedron++);
|
|
|
|
+ }
|
|
|
|
+ // 'c' - cone
|
|
|
|
+ else if (TokenMatch(sz,"c",1))
|
|
|
|
+ {
|
|
|
|
+ meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
|
|
|
+ MeshInfo& currentMesh = meshes.back();
|
|
|
|
+ currentMesh.shader = s;
|
|
|
|
+
|
|
|
|
+ aiVector3D center1, center2; float radius1, radius2;
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(center1);
|
|
|
|
+ AI_NFF_PARSE_FLOAT(radius1);
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(center2);
|
|
|
|
+ AI_NFF_PARSE_FLOAT(radius2);
|
|
|
|
+
|
|
|
|
+ // compute the center point of the cone/cylinder
|
|
|
|
+ center2 = (center2-center1)/2.f;
|
|
|
|
+ currentMesh.center = center1+center2;
|
|
|
|
+ center1 = -center2;
|
|
|
|
+
|
|
|
|
+ // generate the cone - it consists of simple triangles
|
|
|
|
+ StandardShapes::MakeCone(center1, radius1, center2, radius2, iTesselation, currentMesh.vertices);
|
|
|
|
+ currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
|
|
|
+
|
|
|
|
+ // generate a name for the mesh
|
|
|
|
+ if (radius1 != radius2)
|
|
|
|
+ ::sprintf(currentMesh.name,"cone_%i",cone++);
|
|
|
|
+ else ::sprintf(currentMesh.name,"cylinder_%i",cylinder++);
|
|
|
|
+ }
|
|
|
|
+ // 'tess' - tesselation
|
|
|
|
+ else if (TokenMatch(sz,"tess",4))
|
|
|
|
+ {
|
|
|
|
+ SkipSpaces(&sz);
|
|
|
|
+ iTesselation = strtol10(sz);
|
|
|
|
+ }
|
|
|
|
+ // 'from' - camera position
|
|
|
|
+ else if (TokenMatch(sz,"from",4))
|
|
|
|
+ {
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(camPos);
|
|
|
|
+ hasCam = true;
|
|
|
|
+ }
|
|
|
|
+ // 'at' - camera look-at vector
|
|
|
|
+ else if (TokenMatch(sz,"at",2))
|
|
|
|
+ {
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(camLookAt);
|
|
|
|
+ hasCam = true;
|
|
|
|
+ }
|
|
|
|
+ // 'up' - camera up vector
|
|
|
|
+ else if (TokenMatch(sz,"up",2))
|
|
|
|
+ {
|
|
|
|
+ AI_NFF_PARSE_TRIPLE(camUp);
|
|
|
|
+ hasCam = true;
|
|
|
|
+ }
|
|
|
|
+ // 'angle' - (half?) camera field of view
|
|
|
|
+ else if (TokenMatch(sz,"angle",5))
|
|
|
|
+ {
|
|
|
|
+ AI_NFF_PARSE_FLOAT(angle);
|
|
|
|
+ hasCam = true;
|
|
|
|
+ }
|
|
|
|
+ // 'resolution' - used to compute the screen aspect
|
|
|
|
+ else if (TokenMatch(sz,"resolution",10))
|
|
|
|
+ {
|
|
|
|
+ AI_NFF_PARSE_FLOAT(resolution.x);
|
|
|
|
+ AI_NFF_PARSE_FLOAT(resolution.y);
|
|
|
|
+ hasCam = true;
|
|
|
|
+ }
|
|
|
|
+ // 'pb' - bezier patch. Not supported yet
|
|
|
|
+ else if (TokenMatch(sz,"pb",2))
|
|
|
|
+ {
|
|
|
|
+ DefaultLogger::get()->error("NFF: Encountered unsupported ID: bezier patch");
|
|
|
|
+ }
|
|
|
|
+ // 'pn' - NURBS. Not supported yet
|
|
|
|
+ else if (TokenMatch(sz,"pn",2) || TokenMatch(sz,"pnn",3))
|
|
|
|
+ {
|
|
|
|
+ DefaultLogger::get()->error("NFF: Encountered unsupported ID: NURBS");
|
|
|
|
+ }
|
|
|
|
+ // '' - comment
|
|
|
|
+ else if ('#' == line[0])
|
|
|
|
+ {
|
|
|
|
+ const char* sz;SkipSpaces(&line[1],&sz);
|
|
|
|
+ if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// copy all arrays into one large
|
|
// copy all arrays into one large
|
|
- meshes.reserve(meshes.size()+meshesLocked.size()+meshesWithNormals.size());
|
|
|
|
- meshes.insert(meshes.end(),meshesLocked.begin(),meshesLocked.end());
|
|
|
|
- meshes.insert(meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end());
|
|
|
|
|
|
+ meshes.reserve (meshes.size()+meshesLocked.size()+meshesWithNormals.size()+meshesWithUVCoords.size());
|
|
|
|
+ meshes.insert (meshes.end(),meshesLocked.begin(),meshesLocked.end());
|
|
|
|
+ meshes.insert (meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end());
|
|
|
|
+ meshes.insert (meshes.end(),meshesWithUVCoords.begin(),meshesWithUVCoords.end());
|
|
|
|
|
|
// now generate output meshes. first find out how many meshes we'll need
|
|
// now generate output meshes. first find out how many meshes we'll need
|
|
std::vector<MeshInfo>::const_iterator it = meshes.begin(), end = meshes.end();
|
|
std::vector<MeshInfo>::const_iterator it = meshes.begin(), end = meshes.end();
|
|
@@ -388,7 +649,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|
// sub nodes for named objects such as spheres and cones.
|
|
// sub nodes for named objects such as spheres and cones.
|
|
aiNode* const root = new aiNode();
|
|
aiNode* const root = new aiNode();
|
|
root->mName.Set("<NFF_Root>");
|
|
root->mName.Set("<NFF_Root>");
|
|
- root->mNumChildren = numNamed;
|
|
|
|
|
|
+ root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int) lights.size();
|
|
root->mNumMeshes = pScene->mNumMeshes-numNamed;
|
|
root->mNumMeshes = pScene->mNumMeshes-numNamed;
|
|
|
|
|
|
aiNode** ppcChildren;
|
|
aiNode** ppcChildren;
|
|
@@ -398,6 +659,49 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|
if (root->mNumChildren)
|
|
if (root->mNumChildren)
|
|
ppcChildren = root->mChildren = new aiNode*[root->mNumChildren];
|
|
ppcChildren = root->mChildren = new aiNode*[root->mNumChildren];
|
|
|
|
|
|
|
|
+ // generate the camera
|
|
|
|
+ if (hasCam)
|
|
|
|
+ {
|
|
|
|
+ aiNode* nd = *ppcChildren = new aiNode();
|
|
|
|
+ nd->mName.Set("<NFF_Camera>");
|
|
|
|
+ nd->mParent = root;
|
|
|
|
+
|
|
|
|
+ // allocate the camera in the scene
|
|
|
|
+ pScene->mNumCameras = 1;
|
|
|
|
+ pScene->mCameras = new aiCamera*[1];
|
|
|
|
+ aiCamera* c = pScene->mCameras[0] = new aiCamera;
|
|
|
|
+
|
|
|
|
+ c->mName = nd->mName; // make sure the names are identical
|
|
|
|
+ c->mHorizontalFOV = AI_DEG_TO_RAD( angle );
|
|
|
|
+ c->mLookAt = camLookAt - camPos;
|
|
|
|
+ c->mPosition = camPos;
|
|
|
|
+ c->mUp = camUp;
|
|
|
|
+ c->mAspect = resolution.x / resolution.y;
|
|
|
|
+ ++ppcChildren;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // generate light sources
|
|
|
|
+ if (!lights.empty())
|
|
|
|
+ {
|
|
|
|
+ pScene->mNumLights = (unsigned int)lights.size();
|
|
|
|
+ pScene->mLights = new aiLight*[pScene->mNumLights];
|
|
|
|
+ for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren)
|
|
|
|
+ {
|
|
|
|
+ const Light& l = lights[i];
|
|
|
|
+
|
|
|
|
+ aiNode* nd = *ppcChildren = new aiNode();
|
|
|
|
+ nd->mParent = root;
|
|
|
|
+
|
|
|
|
+ nd->mName.length = ::sprintf(nd->mName.data,"<NFF_Light%i>",i);
|
|
|
|
+
|
|
|
|
+ // allocate the light in the scene data structure
|
|
|
|
+ aiLight* out = pScene->mLights[i] = new aiLight();
|
|
|
|
+ out->mName = nd->mName; // make sure the names are identical
|
|
|
|
+ out->mType = aiLightSource_POINT;
|
|
|
|
+ out->mColorDiffuse = out->mColorSpecular = l.color * l.intensity;
|
|
|
|
+ out->mPosition = l.position;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
if (!pScene->mNumMeshes)throw new ImportErrorException("NFF: No meshes loaded");
|
|
if (!pScene->mNumMeshes)throw new ImportErrorException("NFF: No meshes loaded");
|
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
|
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
|
|
@@ -436,14 +740,38 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|
|
|
|
|
// copy vertex positions
|
|
// copy vertex positions
|
|
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
|
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
|
|
- ::memcpy(mesh->mVertices,&src.vertices[0],sizeof(aiVector3D)*mesh->mNumVertices);
|
|
|
|
- if (src.bHasNormals)
|
|
|
|
|
|
+ ::memcpy(mesh->mVertices,&src.vertices[0],
|
|
|
|
+ sizeof(aiVector3D)*mesh->mNumVertices);
|
|
|
|
+
|
|
|
|
+ // NFF2: there could be vertex colors
|
|
|
|
+ if (!src.colors.empty())
|
|
|
|
+ {
|
|
|
|
+ ai_assert(src.colors.size() == src.vertices.size());
|
|
|
|
+
|
|
|
|
+ // copy vertex colors
|
|
|
|
+ mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
|
|
|
|
+ ::memcpy(mesh->mColors[0],&src.colors[0],
|
|
|
|
+ sizeof(aiColor4D)*mesh->mNumVertices);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (src.pType != PatchType_Simple)
|
|
{
|
|
{
|
|
ai_assert(src.normals.size() == src.vertices.size());
|
|
ai_assert(src.normals.size() == src.vertices.size());
|
|
|
|
|
|
// copy normal vectors
|
|
// copy normal vectors
|
|
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
|
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
|
|
- ::memcpy(mesh->mNormals,&src.normals[0],sizeof(aiVector3D)*mesh->mNumVertices);
|
|
|
|
|
|
+ ::memcpy(mesh->mNormals,&src.normals[0],
|
|
|
|
+ sizeof(aiVector3D)*mesh->mNumVertices);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (src.pType == PatchType_UVAndNormals)
|
|
|
|
+ {
|
|
|
|
+ ai_assert(src.uvs.size() == src.vertices.size());
|
|
|
|
+
|
|
|
|
+ // copy texture coordinates
|
|
|
|
+ mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
|
|
|
|
+ ::memcpy(mesh->mTextureCoords[0],&src.uvs[0],
|
|
|
|
+ sizeof(aiVector3D)*mesh->mNumVertices);
|
|
}
|
|
}
|
|
|
|
|
|
// generate faces
|
|
// generate faces
|
|
@@ -459,8 +787,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|
}
|
|
}
|
|
|
|
|
|
// generate a material for the mesh
|
|
// generate a material for the mesh
|
|
- MaterialHelper* pcMat = (MaterialHelper*)(pScene->
|
|
|
|
- mMaterials[m] = new MaterialHelper());
|
|
|
|
|
|
+ MaterialHelper* pcMat = (MaterialHelper*)(pScene->mMaterials[m] = new MaterialHelper());
|
|
|
|
|
|
mesh->mMaterialIndex = m++;
|
|
mesh->mMaterialIndex = m++;
|
|
|
|
|
|
@@ -468,8 +795,16 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|
s.Set(AI_DEFAULT_MATERIAL_NAME);
|
|
s.Set(AI_DEFAULT_MATERIAL_NAME);
|
|
pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
|
pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
|
|
|
|
|
- pcMat->AddProperty(&src.shader.color,1,AI_MATKEY_COLOR_DIFFUSE);
|
|
|
|
- pcMat->AddProperty(&src.shader.color,1,AI_MATKEY_COLOR_SPECULAR);
|
|
|
|
|
|
+ aiColor3D c = src.shader.color * src.shader.diffuse;
|
|
|
|
+ pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
|
|
|
|
+ c = src.shader.color * src.shader.specular;
|
|
|
|
+ pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
|
|
|
|
+
|
|
|
|
+ if (src.shader.texFile.length())
|
|
|
|
+ {
|
|
|
|
+ s.Set(src.shader.texFile);
|
|
|
|
+ pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
|
|
|
+ }
|
|
}
|
|
}
|
|
pScene->mRootNode = root;
|
|
pScene->mRootNode = root;
|
|
}
|
|
}
|