Commit 11e37d62 authored by hybrid's avatar hybrid

Improved inputs handling. Implemented instance before geometry handling. Enhanced debug output.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3223 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 9e23a048
......@@ -211,6 +211,7 @@ namespace
if (m)
{
m->setName(getId());
// m->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
// m->setDebugDataVisible(scene::EDS_FULL);
}
return m;
......@@ -445,6 +446,7 @@ void CColladaFileLoader::readColladaSection(io::IXMLReaderUTF8* reader)
if (reader->isEmptyElement())
return;
// todo: patch level needs to be handled
const f32 version = core::fast_atof(core::stringc(reader->getAttributeValue("version")).c_str());
Version = core::floor32(version)*10000+core::round32(core::fract(version)*1000.0f);
// Version 1.4 can be checked for by if (Version >= 10400)
......@@ -663,7 +665,7 @@ void CColladaFileLoader::readSceneSection(io::IXMLReaderUTF8* reader)
}
else
if ((instanceSceneName == reader->getNodeName()))
readInstanceNode(reader, SceneManager->getRootSceneNode(), 0);
readInstanceNode(reader, SceneManager->getRootSceneNode(), 0, 0,instanceSceneName);
else
if (extraNodeName == reader->getNodeName())
skipSection(reader, false);
......@@ -714,14 +716,18 @@ void CColladaFileLoader::readAssetSection(io::IXMLReaderUTF8* reader)
//! reads a <node> section and its content
void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent, CScenePrefab* p)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading node");
#endif
if (reader->isEmptyElement())
{
return;
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading empty node");
#endif
}
core::stringc name = readId(reader);
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading node", name);
#endif
core::matrix4 transform; // transformation of this node
core::aabbox3df bbox;
......@@ -774,7 +780,7 @@ void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISce
(instanceLightName == reader->getNodeName()))
{
scene::ISceneNode* newnode = 0;
readInstanceNode(reader, parent, &newnode, nodeprefab);
readInstanceNode(reader, parent, &newnode, nodeprefab, reader->getNodeName());
if (node && newnode)
{
......@@ -1081,16 +1087,17 @@ core::matrix4 CColladaFileLoader::readTranslateNode(io::IXMLReaderUTF8* reader)
//! reads any kind of <instance*> node
void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader,
scene::ISceneNode* parent, scene::ISceneNode** outNode, CScenePrefab* p)
scene::ISceneNode* parent, scene::ISceneNode** outNode,
CScenePrefab* p, const core::stringc& type)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading instance");
#endif
// find prefab of the specified id
core::stringc url = reader->getAttributeValue("url");
uriToId(url);
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading instance", url);
#endif
if (!reader->isEmptyElement())
{
while(reader->read())
......@@ -1108,12 +1115,13 @@ void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader,
break;
}
}
instantiateNode(parent, outNode, p, url);
instantiateNode(parent, outNode, p, url, type);
}
void CColladaFileLoader::instantiateNode(scene::ISceneNode* parent,
scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& url)
scene::ISceneNode** outNode, CScenePrefab* p, const core::stringc& url,
const core::stringc& type)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA instantiate node");
......@@ -1140,6 +1148,14 @@ void CColladaFileLoader::instantiateNode(scene::ISceneNode* parent,
return;
}
}
if (p)
{
if (instanceGeometryName==type)
{
Prefabs.push_back(new CGeometryPrefab(url));
p->Childs.push_back(Prefabs.getLast());
}
}
}
......@@ -1181,15 +1197,14 @@ void CColladaFileLoader::readCameraPrefab(io::IXMLReaderUTF8* reader)
//! reads a <image> element and stores it in the image section
void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading image");
#endif
// add image to list of loaded images.
Images.push_back(SColladaImage());
SColladaImage& image=Images.getLast();
image.Id = readId(reader);
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading image", core::stringc(image.Id));
#endif
image.Dimension.Height = (u32)reader->getAttributeValueAsInt("height");
image.Dimension.Width = (u32)reader->getAttributeValueAsInt("width");
......@@ -1241,15 +1256,14 @@ void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader)
//! reads a <texture> element and stores it in the texture section
void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading texture");
#endif
// add texture to list of loaded textures.
Textures.push_back(SColladaTexture());
SColladaTexture& texture=Textures.getLast();
texture.Id = readId(reader);
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading texture", core::stringc(texture.Id));
#endif
if (!reader->isEmptyElement())
{
......@@ -1267,15 +1281,14 @@ void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader)
//! reads a <material> element and stores it in the material section
void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading material");
#endif
// add material to list of loaded materials.
Materials.push_back(SColladaMaterial());
SColladaMaterial& material = Materials.getLast();
material.Id = readId(reader);
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading material", core::stringc(material.Id));
#endif
if (Version >= 10400)
{
......@@ -1338,10 +1351,6 @@ void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader)
void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect * effect)
{
#ifdef COLLADA_READER_DEBUG
if (!effect) os::Printer::log("COLLADA reading effect");
#endif
static const core::stringc constantNode("constant");
static const core::stringc lambertNode("lambert");
static const core::stringc phongNode("phong");
......@@ -1365,6 +1374,9 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
effect->Transparency = 1.f;
effect->Mat.Lighting=true;
effect->Mat.NormalizeNormals=true;
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading effect", core::stringc(effect->Id));
#endif
}
while(reader->read())
{
......@@ -1634,20 +1646,16 @@ void CColladaFileLoader::readBindMaterialSection(io::IXMLReaderUTF8* reader, con
//! reads a <geometry> element and stores it as mesh if possible
void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
{
core::stringc id = readId(reader);
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading geometry");
os::Printer::log("COLLADA reading geometry", id);
#endif
core::stringc id = readId(reader);
core::stringc VertexPositionSource; // each mesh has exactly one <vertex> member, containing
// a POSITION input. This string stores the source of this input.
core::array<SSource> sources;
bool okToReadArray = false;
SAnimatedMesh* amesh = new SAnimatedMesh();
scene::SMesh* mesh = new SMesh();
amesh->addMesh(mesh);
core::array<SSource> sources;
bool okToReadArray = false;
// handles geometry node and the mesh childs in this loop
// read sources with arrays and accessor for each mesh
......@@ -1728,9 +1736,6 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
#endif
// read vertex input position source
readColladaInputs(reader, verticesSectionName);
SColladaInput* input = getColladaInput(ECIS_POSITION);
if (input)
VertexPositionSource = input->Source;
}
else
// lines and linestrips missing
......@@ -1739,7 +1744,7 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
trianglesSectionName == nodeName)
{
// read polygons section
readPolygonSection(reader, VertexPositionSource, sources, mesh, id);
readPolygonSection(reader, sources, mesh, id);
}
else
// trifans, and tristrips missing
......@@ -1829,9 +1834,21 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
amesh->drop();
// create geometry prefab
CGeometryPrefab* prefab = new CGeometryPrefab(id.c_str());
prefab->Mesh = mesh;
Prefabs.push_back(prefab);
u32 i;
for (i=0; i<Prefabs.size(); ++i)
{
if (Prefabs[i]->getId()==id)
{
((CGeometryPrefab*)Prefabs[i])->Mesh=mesh;
break;
}
}
if (i==Prefabs.size())
{
CGeometryPrefab* prefab = new CGeometryPrefab(id);
prefab->Mesh = mesh;
Prefabs.push_back(prefab);
}
// store as dummy mesh if no instances will be created
if (!CreateInstances && !DummyMesh)
......@@ -1849,8 +1866,8 @@ struct SPolygon
//! reads a polygons section and creates a mesh from it
void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
const core::stringc& vertexPositionSource, core::array<SSource>& sources,
scene::SMesh* mesh, const core::stringc& geometryId)
core::array<SSource>& sources, scene::SMesh* mesh,
const core::stringc& geometryId)
{
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA reading polygon section");
......@@ -1869,7 +1886,7 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
u32 inputSemanticCount = 0;
bool unresolvedInput=false;
u32 maxOffset = 0;
Inputs.clear();
core::array<SColladaInput> localInputs;
// read all <input> and primitives
if (!reader->isEmptyElement())
......@@ -1883,52 +1900,25 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
if (inputTagName == nodeName)
{
// read input tag
readColladaInput(reader);
readColladaInput(reader, localInputs);
// resolve input source
SColladaInput& inp = Inputs.getLast();
core::stringc sourceArrayURI;
SColladaInput& inp = localInputs.getLast();
// get input source array id, if it is a vertex input, take
// the <vertex><input>-source attribute.
if (inp.Semantic == ECIS_VERTEX)
sourceArrayURI = vertexPositionSource;
else
sourceArrayURI = inp.Source;
uriToId(sourceArrayURI);
// find source array (we'll ignore accessors for this implementation)
u32 s;
for (s=0; s<sources.size(); ++s)
{
if (sources[s].Id == sourceArrayURI)
inp.Source = Inputs[0].Source;
for (u32 i=1; i<Inputs.size(); ++i)
{
// slot found
inp.Data = sources[s].Array.Data.pointer();
inp.Stride = sources[s].Accessors[0].Stride;
break;
localInputs.push_back(Inputs[i]);
uriToId(localInputs.getLast().Source);
maxOffset = core::max_(maxOffset,localInputs.getLast().Offset);
++inputSemanticCount;
}
}
if (s == sources.size())
{
os::Printer::log("COLLADA Warning, polygon input source not found",
sourceArrayURI.c_str());
unresolvedInput=true;
}
else
{
#ifdef COLLADA_READER_DEBUG
// print slot
core::stringc tmp = "Added slot ";
tmp += inputSemanticNames[inp.Semantic];
tmp += " sourceArray:";
tmp += sourceArrayURI;
os::Printer::log(tmp.c_str());
#endif
}
uriToId(inp.Source);
maxOffset = core::max_(maxOffset,inp.Offset);
++inputSemanticCount;
}
......@@ -1998,7 +1988,6 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
for (u32 i = 0; i < vCounts.size(); i++)
{
const int polyVCount = vCounts[i];
core::array<int> polyCorners;
for (u32 j = 0; j < polyVCount * inputSemanticCount; j++)
......@@ -2029,10 +2018,43 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
}
} // end while reader->read()
if (inputSemanticCount == 0 || unresolvedInput)
return; // we cannot create the mesh if one of the input semantics wasn't found.
// find source array (we'll ignore accessors for this implementation)
for (u32 i=0; i<localInputs.size(); ++i)
{
SColladaInput& inp = localInputs[i];
u32 s;
for (s=0; s<sources.size(); ++s)
{
if (sources[s].Id == inp.Source)
{
// slot found
inp.Data = sources[s].Array.Data.pointer();
inp.Stride = sources[s].Accessors[0].Stride;
break;
}
}
if (!polygons.size())
if (s == sources.size())
{
os::Printer::log("COLLADA Warning, polygon input source not found",
inp.Source.c_str());
inp.Semantic=ECIS_COUNT; // for unknown
unresolvedInput=true;
}
else
{
#ifdef COLLADA_READER_DEBUG
// print slot
core::stringc tmp = "Added slot ";
tmp += inputSemanticNames[inp.Semantic];
tmp += " sourceArray:";
tmp += inp.Source;
os::Printer::log(tmp.c_str());
#endif
}
}
if ((inputSemanticCount == 0) || !polygons.size())
return; // cancel if there are no polygons anyway.
// analyze content of Inputs to create a fitting mesh buffer
......@@ -2084,47 +2106,47 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
vtx.Color.set(255,255,255,255);
// for all input semantics
for (u32 k=0; k<Inputs.size(); ++k)
for (u32 k=0; k<localInputs.size(); ++k)
{
if (!Inputs[k].Data)
if (!localInputs[k].Data)
continue;
// build vertex from input semantics.
const u32 idx = Inputs[k].Stride*polygons[i].Indices[v+Inputs[k].Offset];
const u32 idx = localInputs[k].Stride*polygons[i].Indices[v+localInputs[k].Offset];
switch(Inputs[k].Semantic)
switch(localInputs[k].Semantic)
{
case ECIS_POSITION:
case ECIS_VERTEX:
vtx.Pos.X = Inputs[k].Data[idx+0];
vtx.Pos.X = localInputs[k].Data[idx+0];
if (FlipAxis)
{
vtx.Pos.Z = Inputs[k].Data[idx+1];
vtx.Pos.Y = Inputs[k].Data[idx+2];
vtx.Pos.Z = localInputs[k].Data[idx+1];
vtx.Pos.Y = localInputs[k].Data[idx+2];
}
else
{
vtx.Pos.Y = Inputs[k].Data[idx+1];
vtx.Pos.Z = Inputs[k].Data[idx+2];
vtx.Pos.Y = localInputs[k].Data[idx+1];
vtx.Pos.Z = localInputs[k].Data[idx+2];
}
break;
case ECIS_NORMAL:
vtx.Normal.X = Inputs[k].Data[idx+0];
vtx.Normal.X = localInputs[k].Data[idx+0];
if (FlipAxis)
{
vtx.Normal.Z = Inputs[k].Data[idx+1];
vtx.Normal.Y = Inputs[k].Data[idx+2];
vtx.Normal.Z = localInputs[k].Data[idx+1];
vtx.Normal.Y = localInputs[k].Data[idx+2];
}
else
{
vtx.Normal.Y = Inputs[k].Data[idx+1];
vtx.Normal.Z = Inputs[k].Data[idx+2];
vtx.Normal.Y = localInputs[k].Data[idx+1];
vtx.Normal.Z = localInputs[k].Data[idx+2];
}
break;
case ECIS_TEXCOORD:
case ECIS_UV:
vtx.TCoords.X = Inputs[k].Data[idx+0];
vtx.TCoords.Y = 1-Inputs[k].Data[idx+1];
vtx.TCoords.X = localInputs[k].Data[idx+0];
vtx.TCoords.Y = 1-localInputs[k].Data[idx+1];
break;
case ECIS_TANGENT:
break;
......@@ -2216,48 +2238,48 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
{
// build vertex from input semantics.
const u32 idx = Inputs[k].Stride*polygons[i].Indices[v+Inputs[k].Offset];
const u32 idx = localInputs[k].Stride*polygons[i].Indices[v+Inputs[k].Offset];
switch(Inputs[k].Semantic)
switch(localInputs[k].Semantic)
{
case ECIS_POSITION:
case ECIS_VERTEX:
vtx.Pos.X = Inputs[k].Data[idx+0];
vtx.Pos.X = localInputs[k].Data[idx+0];
if (FlipAxis)
{
vtx.Pos.Z = Inputs[k].Data[idx+1];
vtx.Pos.Y = Inputs[k].Data[idx+2];
vtx.Pos.Z = localInputs[k].Data[idx+1];
vtx.Pos.Y = localInputs[k].Data[idx+2];
}
else
{
vtx.Pos.Y = Inputs[k].Data[idx+1];
vtx.Pos.Z = Inputs[k].Data[idx+2];
vtx.Pos.Y = localInputs[k].Data[idx+1];
vtx.Pos.Z = localInputs[k].Data[idx+2];
}
break;
case ECIS_NORMAL:
vtx.Normal.X = Inputs[k].Data[idx+0];
vtx.Normal.X = localInputs[k].Data[idx+0];
if (FlipAxis)
{
vtx.Normal.Z = Inputs[k].Data[idx+1];
vtx.Normal.Y = Inputs[k].Data[idx+2];
vtx.Normal.Z = localInputs[k].Data[idx+1];
vtx.Normal.Y = localInputs[k].Data[idx+2];
}
else
{
vtx.Normal.Y = Inputs[k].Data[idx+1];
vtx.Normal.Z = Inputs[k].Data[idx+2];
vtx.Normal.Y = localInputs[k].Data[idx+1];
vtx.Normal.Z = localInputs[k].Data[idx+2];
}
break;
case ECIS_TEXCOORD:
case ECIS_UV:
if (k==secondTexCoordSetIndex)
{
vtx.TCoords2.X = Inputs[k].Data[idx+0];
vtx.TCoords2.Y = 1-Inputs[k].Data[idx+1];
vtx.TCoords2.X = localInputs[k].Data[idx+0];
vtx.TCoords2.Y = 1-localInputs[k].Data[idx+1];
}
else
{
vtx.TCoords.X = Inputs[k].Data[idx+0];
vtx.TCoords.Y = 1-Inputs[k].Data[idx+1];
vtx.TCoords.X = localInputs[k].Data[idx+0];
vtx.TCoords.Y = 1-localInputs[k].Data[idx+1];
}
break;
case ECIS_TANGENT:
......@@ -2312,6 +2334,9 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
// add mesh buffer
mesh->addMeshBuffer(buffer);
#ifdef COLLADA_READER_DEBUG
os::Printer::log("COLLADA added meshbuffer", core::stringc(buffer->getVertexCount())+" vertices, "+core::stringc(buffer->getIndexCount())+" indices.");
#endif
buffer->drop();
}
......@@ -2414,7 +2439,7 @@ SColladaInput* CColladaFileLoader::getColladaInput(ECOLLADA_INPUT_SEMANTIC input
//! reads a collada input tag and adds it to the input parameter
void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader)
void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs)
{
// parse param
SColladaInput p;
......@@ -2439,7 +2464,7 @@ void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader)
p.Set = (u32)reader->getAttributeValueAsInt("set");
// add input
Inputs.push_back(p);
inputs.push_back(p);
}
//! parses all collada inputs inside an element and stores them in Inputs
......@@ -2452,7 +2477,7 @@ void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const cor
if (reader->getNodeType() == io::EXN_ELEMENT &&
inputTagName == reader->getNodeName())
{
readColladaInput(reader);
readColladaInput(reader, Inputs);
}
else
if (reader->getNodeType() == io::EXN_ELEMENT_END)
......
......@@ -247,12 +247,14 @@ private:
f32 readFloatNode(io::IXMLReaderUTF8* reader);
//! reads a <instance> node
void readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISceneNode* parent,
scene::ISceneNode** outNode, CScenePrefab* p=0);
void readInstanceNode(io::IXMLReaderUTF8* reader,
scene::ISceneNode* parent, scene::ISceneNode** outNode,
CScenePrefab* p=0, const core::stringc& type=core::stringc());
//! creates a scene node from Prefabs (with name given in 'url')
void instantiateNode(scene::ISceneNode* parent, scene::ISceneNode** outNode=0,
CScenePrefab* p=0, const core::stringc& url="");
CScenePrefab* p=0, const core::stringc& url="",
const core::stringc& type=core::stringc());
//! reads a <light> element and stores it as prefab
void readLightPrefab(io::IXMLReaderUTF8* reader);
......@@ -306,7 +308,7 @@ private:
void readColladaInputs(io::IXMLReaderUTF8* reader, const core::stringc& parentName);
//! reads a collada input tag and adds it to the input parameter
void readColladaInput(io::IXMLReaderUTF8* reader);
void readColladaInput(io::IXMLReaderUTF8* reader, core::array<SColladaInput>& inputs);
//! returns a collada input or none if not found
SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input);
......@@ -319,8 +321,8 @@ private:
//! reads a polygons section and creates a mesh from it
void readPolygonSection(io::IXMLReaderUTF8* reader,
const core::stringc& vertexPositionSource, core::array<SSource>& sources,
scene::SMesh* mesh, const core::stringc& geometryId);
core::array<SSource>& sources, scene::SMesh* mesh,
const core::stringc& geometryId);
//! finds a material, possible instancing it
const SColladaMaterial * findMaterial(const core::stringc & materialName);
......
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