Commit d296e17f authored by hybrid's avatar hybrid

Fixed normal generation for obj files without normals.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1437 dfc29bdd-3216-0410-991c-e03cc46cb475
parent c1b36e96
......@@ -21,6 +21,8 @@ namespace irr
namespace scene
{
static const u32 WORD_BUFFER_LENGTH = 512;
//! Constructor
COBJMeshFileLoader::COBJMeshFileLoader(scene::ISceneManager* smgr, io::IFileSystem* fs)
: SceneManager(smgr), FileSystem(fs)
......@@ -190,7 +192,10 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
if ( -1 != Idx[2] )
v.Normal = normalsBuffer[Idx[2]];
else
{
v.Normal.set(0.0f,0.0f,0.0f);
currMtl->RecalculateNormals=true;
}
int vertLocation;
core::map<video::S3DVertex, int>::Node* n = currMtl->VertMap.find(v);
......@@ -240,6 +245,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
if ( Materials[m]->Meshbuffer->getIndexCount() > 0 )
{
Materials[m]->Meshbuffer->recalculateBoundingBox();
if (Materials[m]->RecalculateNormals)
SceneManager->getMeshManipulator()->recalculateNormals(Materials[m]->Meshbuffer);
if (Materials[m]->Meshbuffer->Material.MaterialType == video::EMT_PARALLAX_MAP_SOLID)
{
SMesh tmp;
......@@ -274,120 +281,8 @@ IAnimatedMesh* COBJMeshFileLoader::createMesh(io::IReadFile* file)
}
void COBJMeshFileLoader::readMTL(const c8* fileName, core::stringc relPath)
const c8* COBJMeshFileLoader::readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const core::stringc& relPath)
{
const u32 WORD_BUFFER_LENGTH = 512;
io::IReadFile * mtlReader;
if (FileSystem->existFile(fileName))
mtlReader = FileSystem->createAndOpenFile(fileName);
else
// try to read in the relative path, the .obj is loaded from
mtlReader = FileSystem->createAndOpenFile((relPath + fileName).c_str());
if (!mtlReader) // fail to open and read file
return;
const long filesize = mtlReader->getSize();
if (!filesize)
return;
c8* buf = new c8[filesize];
mtlReader->read((void*)buf, filesize);
const c8* bufEnd = buf+filesize;
SObjMtl* currMaterial = 0;
const c8* bufPtr = buf;
while(bufPtr != bufEnd)
{
switch(*bufPtr)
{
case 'n': // newmtl
{
// if there's an existing material, store it first
if ( currMaterial )
Materials.push_back( currMaterial );
// extract new material's name
c8 mtlNameBuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
currMaterial = new SObjMtl;
currMaterial->Name = mtlNameBuf;
}
break;
case 'i': // illum - illumination
if ( currMaterial )
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 illumStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(illumStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
currMaterial->Illumination = (c8)atol(illumStr);
}
break;
case 'N':
if ( currMaterial )
{
switch(bufPtr[1])
{
case 's': // Ns - shininess
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 nsStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(nsStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
f32 shininessValue = core::fast_atof(nsStr);
// wavefront shininess is from [0, 1000], so scale for OpenGL
shininessValue *= 0.128f;
currMaterial->Meshbuffer->Material.Shininess = shininessValue;
}
break;
case 'i': // Ni - refraction index
{
c8 tmpbuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(tmpbuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
}
break;
}
}
break;
case 'K':
if ( currMaterial )
{
switch(bufPtr[1])
{
case 'd': // Kd = diffuse
{
bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.DiffuseColor, bufEnd);
}
break;
case 's': // Ks = specular
{
bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.SpecularColor, bufEnd);
}
break;
case 'a': // Ka = ambience
{
bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.AmbientColor, bufEnd);
}
break;
case 'e': // Ke = emissive
{
bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.EmissiveColor, bufEnd);
}
break;
} // end switch(bufPtr[1])
} // end case 'K': if ( 0 != currMaterial )...
break;
case 'b': // bump
case 'm': // texture maps
if (currMaterial)
{
u8 type=0; // map_Kd - diffuse color texture map
// map_Ks - specular color texture map
// map_Ka - ambient color texture map
......@@ -514,6 +409,123 @@ void COBJMeshFileLoader::readMTL(const c8* fileName, core::stringc relPath)
currMaterial->Meshbuffer->Material.DiffuseColor.set(
currMaterial->Meshbuffer->Material.DiffuseColor.getAlpha(), 255, 255, 255 );
}
return bufPtr;
}
void COBJMeshFileLoader::readMTL(const c8* fileName, const core::stringc& relPath)
{
io::IReadFile * mtlReader;
if (FileSystem->existFile(fileName))
mtlReader = FileSystem->createAndOpenFile(fileName);
else
// try to read in the relative path, the .obj is loaded from
mtlReader = FileSystem->createAndOpenFile((relPath + fileName).c_str());
if (!mtlReader) // fail to open and read file
return;
const long filesize = mtlReader->getSize();
if (!filesize)
return;
c8* buf = new c8[filesize];
mtlReader->read((void*)buf, filesize);
const c8* bufEnd = buf+filesize;
SObjMtl* currMaterial = 0;
const c8* bufPtr = buf;
while(bufPtr != bufEnd)
{
switch(*bufPtr)
{
case 'n': // newmtl
{
// if there's an existing material, store it first
if ( currMaterial )
Materials.push_back( currMaterial );
// extract new material's name
c8 mtlNameBuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(mtlNameBuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
currMaterial = new SObjMtl;
currMaterial->Name = mtlNameBuf;
}
break;
case 'i': // illum - illumination
if ( currMaterial )
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 illumStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(illumStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
currMaterial->Illumination = (c8)atol(illumStr);
}
break;
case 'N':
if ( currMaterial )
{
switch(bufPtr[1])
{
case 's': // Ns - shininess
{
const u32 COLOR_BUFFER_LENGTH = 16;
c8 nsStr[COLOR_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(nsStr, bufPtr, COLOR_BUFFER_LENGTH, bufEnd);
f32 shininessValue = core::fast_atof(nsStr);
// wavefront shininess is from [0, 1000], so scale for OpenGL
shininessValue *= 0.128f;
currMaterial->Meshbuffer->Material.Shininess = shininessValue;
}
break;
case 'i': // Ni - refraction index
{
c8 tmpbuf[WORD_BUFFER_LENGTH];
bufPtr = goAndCopyNextWord(tmpbuf, bufPtr, WORD_BUFFER_LENGTH, bufEnd);
}
break;
}
}
break;
case 'K':
if ( currMaterial )
{
switch(bufPtr[1])
{
case 'd': // Kd = diffuse
{
bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.DiffuseColor, bufEnd);
}
break;
case 's': // Ks = specular
{
bufPtr = readColor(bufPtr, currMaterial->Meshbuffer->Material.SpecularColor, bufEnd);
}
break;
case 'a': // Ka = ambience
{
bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.AmbientColor, bufEnd);
}
break;
case 'e': // Ke = emissive
{
bufPtr=readColor(bufPtr, currMaterial->Meshbuffer->Material.EmissiveColor, bufEnd);
}
break;
} // end switch(bufPtr[1])
} // end case 'K': if ( 0 != currMaterial )...
break;
case 'b': // bump
case 'm': // texture maps
if (currMaterial)
{
bufPtr=readTextures(bufPtr, bufEnd, currMaterial, relPath);
}
break;
case 'd': // d - transparency
......
......@@ -42,7 +42,8 @@ private:
struct SObjMtl
{
SObjMtl() : Meshbuffer(0), Bumpiness (1.0f), Illumination(0)
SObjMtl() : Meshbuffer(0), Bumpiness (1.0f), Illumination(0),
RecalculateNormals(false)
{
Meshbuffer = new SMeshBuffer();
Meshbuffer->Material.Shininess = 0.0f;
......@@ -51,9 +52,10 @@ private:
Meshbuffer->Material.SpecularColor = video::SColorf(1.0f, 1.0f, 1.0f, 1.0f).toSColor();
}
SObjMtl(SObjMtl& o)
SObjMtl(const SObjMtl& o)
: Name(o.Name), Group(o.Group),
Bumpiness(o.Bumpiness), Illumination(o.Illumination)
Bumpiness(o.Bumpiness), Illumination(o.Illumination),
RecalculateNormals(false)
{
Meshbuffer = new SMeshBuffer();
Meshbuffer->Material = o.Meshbuffer->Material;
......@@ -65,8 +67,12 @@ private:
core::stringc Group;
f32 Bumpiness;
c8 Illumination;
bool RecalculateNormals;
};
// helper method for material reading
const c8* readTextures(const c8* bufPtr, const c8* const bufEnd, SObjMtl* currMaterial, const core::stringc& relPath);
// returns a pointer to the first printable character available in the buffer
const c8* goFirstWord(const c8* buf, const c8* const bufEnd);
// returns a pointer to the first printable character after the first non-printable
......@@ -81,7 +87,7 @@ private:
const c8* goAndCopyNextWord(c8* outBuf, const c8* inBuf, u32 outBufLength, const c8* const pBufEnd);
//! Read the material from the given file
void readMTL(const c8* fileName, core::stringc relPath);
void readMTL(const c8* fileName, const core::stringc& relPath);
//! Find and return the material with the given name
SObjMtl* findMtl(const core::stringc& mtlName, const core::stringc& grpName);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment