Better geometry support for Collada loader.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1203 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
94e8a3e360
commit
78b1d0f18c
|
@ -56,6 +56,7 @@ namespace scene
|
|||
const core::stringc arraySectionName = "array";
|
||||
const core::stringc floatArraySectionName ="float_array";
|
||||
const core::stringc intArraySectionName = "int_array";
|
||||
const core::stringc techniqueCommonSectionName = "technique_common";
|
||||
const core::stringc accessorSectionName = "accessor";
|
||||
const core::stringc verticesSectionName = "vertices";
|
||||
const core::stringc inputTagName = "input";
|
||||
|
@ -88,9 +89,13 @@ namespace scene
|
|||
const core::stringc techniqueNodeName = "technique";
|
||||
const core::stringc colorNodeName = "color";
|
||||
const core::stringc floatNodeName = "float";
|
||||
const core::stringc float2NodeName = "float2";
|
||||
const core::stringc float3NodeName = "float3";
|
||||
|
||||
const core::stringc newParamName = "newparam";
|
||||
const core::stringc paramTagName = "param";
|
||||
const core::stringc initFromName = "init_from";
|
||||
const core::stringc dataName = "data";
|
||||
|
||||
const core::stringc textureNodeName = "texture";
|
||||
const core::stringc doubleSidedName = "double_sided";
|
||||
|
@ -106,7 +111,7 @@ namespace scene
|
|||
{
|
||||
public:
|
||||
|
||||
CPrefab(const char* id) : Id(id)
|
||||
CPrefab(const core::stringc& id) : Id(id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -119,9 +124,9 @@ namespace scene
|
|||
}
|
||||
|
||||
//! returns id of this prefab
|
||||
virtual const c8* getId()
|
||||
virtual const core::stringc& getId()
|
||||
{
|
||||
return Id.c_str();
|
||||
return Id;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -135,7 +140,7 @@ namespace scene
|
|||
{
|
||||
public:
|
||||
|
||||
CLightPrefab(const char* id) : CPrefab(id)
|
||||
CLightPrefab(const core::stringc& id) : CPrefab(id)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA: loaded light prefab:", Id.c_str());
|
||||
|
@ -164,7 +169,7 @@ namespace scene
|
|||
{
|
||||
public:
|
||||
|
||||
CGeometryPrefab(const char* id) : CPrefab(id)
|
||||
CGeometryPrefab(const core::stringc& id) : CPrefab(id)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -189,7 +194,7 @@ namespace scene
|
|||
{
|
||||
public:
|
||||
|
||||
CCameraPrefab(const char* id)
|
||||
CCameraPrefab(const core::stringc& id)
|
||||
: CPrefab(id), YFov(core::PI / 2.5f), ZNear(1.0f), ZFar(3000.0f)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
|
@ -225,7 +230,7 @@ namespace scene
|
|||
class CScenePrefab : public CPrefab
|
||||
{
|
||||
public:
|
||||
CScenePrefab(const char* id) : CPrefab(id)
|
||||
CScenePrefab(const core::stringc& id) : CPrefab(id)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA: loaded scene prefab:", Id.c_str());
|
||||
|
@ -529,7 +534,7 @@ void CColladaFileLoader::readVisualSceneLibrary(io::IXMLReaderUTF8* reader)
|
|||
if (reader->getNodeType() == io::EXN_ELEMENT)
|
||||
{
|
||||
if (visualSceneSectionName == reader->getNodeName())
|
||||
p = new CScenePrefab(reader->getAttributeValue("id"));
|
||||
p = new CScenePrefab(readId(reader));
|
||||
else
|
||||
if (p && nodeSectionName == reader->getNodeName()) // as a child of visual_scene
|
||||
readNodeSection(reader, SceneManager->getRootSceneNode(), p);
|
||||
|
@ -657,9 +662,7 @@ void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISce
|
|||
if (reader->isEmptyElement())
|
||||
return;
|
||||
|
||||
core::stringc name = reader->getAttributeValue("name"); // name of the node
|
||||
if (name.size()==0)
|
||||
name = reader->getAttributeValue("id");
|
||||
core::stringc name = readId(reader);
|
||||
|
||||
core::matrix4 transform; // transformation of this node
|
||||
core::aabbox3df bbox;
|
||||
|
@ -668,7 +671,7 @@ void CColladaFileLoader::readNodeSection(io::IXMLReaderUTF8* reader, scene::ISce
|
|||
|
||||
if (p)
|
||||
{
|
||||
nodeprefab = new CScenePrefab(reader->getAttributeValue("id"));
|
||||
nodeprefab = new CScenePrefab(readId(reader));
|
||||
p->Childs.push_back(nodeprefab);
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1040,7 @@ void CColladaFileLoader::readInstanceNode(io::IXMLReaderUTF8* reader, scene::ISc
|
|||
{
|
||||
*outNode = newNode;
|
||||
if (*outNode)
|
||||
(*outNode)->setName(reader->getAttributeValue("id"));
|
||||
(*outNode)->setName(readId(reader).c_str());
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -1053,7 +1056,7 @@ void CColladaFileLoader::readCameraPrefab(io::IXMLReaderUTF8* reader)
|
|||
os::Printer::log("COLLADA reading camera prefab");
|
||||
#endif
|
||||
|
||||
CCameraPrefab* prefab = new CCameraPrefab(reader->getAttributeValue("id"));
|
||||
CCameraPrefab* prefab = new CCameraPrefab(readId(reader));
|
||||
|
||||
if (!reader->isEmptyElement())
|
||||
{
|
||||
|
@ -1088,18 +1091,39 @@ void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader)
|
|||
os::Printer::log("COLLADA reading image");
|
||||
#endif
|
||||
|
||||
SColladaImage image;
|
||||
image.Id = reader->getAttributeValue("id");
|
||||
// add image to list of loaded images.
|
||||
Images.push_back(SColladaImage());
|
||||
SColladaImage& image=Images.getLast();
|
||||
|
||||
image.Id = readId(reader);
|
||||
image.Dimension.Height = (u32)reader->getAttributeValue("height");
|
||||
image.Dimension.Width = (u32)reader->getAttributeValue("width");
|
||||
|
||||
if (Version >= 10400) // start with 1.4
|
||||
{
|
||||
while(reader->read())
|
||||
{
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT &&
|
||||
initFromName == reader->getNodeName())
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT)
|
||||
{
|
||||
image.Filename = reader->getNodeData();
|
||||
image.Filename.trim();
|
||||
readColladaInput(reader);
|
||||
if (assetSectionName == reader->getNodeName())
|
||||
skipSection(reader, false);
|
||||
else
|
||||
if (initFromName == reader->getNodeName())
|
||||
{
|
||||
image.Source = reader->getNodeData();
|
||||
image.Source.trim();
|
||||
image.SourceIsFilename=true;
|
||||
}
|
||||
else
|
||||
if (dataName == reader->getNodeName())
|
||||
{
|
||||
image.Source = reader->getNodeData();
|
||||
image.Source.trim();
|
||||
image.SourceIsFilename=false;
|
||||
}
|
||||
else
|
||||
if (extraNodeName == reader->getNodeName())
|
||||
skipSection(reader, false);
|
||||
}
|
||||
else
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT_END)
|
||||
|
@ -1107,14 +1131,14 @@ void CColladaFileLoader::readImage(io::IXMLReaderUTF8* reader)
|
|||
if (initFromName == reader->getNodeName())
|
||||
return;
|
||||
}
|
||||
|
||||
} // end while reader->read();
|
||||
}
|
||||
}
|
||||
else
|
||||
image.Filename = reader->getAttributeValue("source");
|
||||
|
||||
// add image to list of loaded images.
|
||||
Images.push_back(image);
|
||||
{
|
||||
image.Source = reader->getAttributeValue("source");
|
||||
image.Source.trim();
|
||||
image.SourceIsFilename=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1125,8 +1149,11 @@ void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader)
|
|||
os::Printer::log("COLLADA reading texture");
|
||||
#endif
|
||||
|
||||
SColladaTexture texture;
|
||||
texture.Id = reader->getAttributeValue("id");
|
||||
// add texture to list of loaded textures.
|
||||
Textures.push_back(SColladaTexture());
|
||||
SColladaTexture& texture=Textures.getLast();
|
||||
|
||||
texture.Id = readId(reader);
|
||||
|
||||
if (!reader->isEmptyElement())
|
||||
{
|
||||
|
@ -1134,19 +1161,10 @@ void CColladaFileLoader::readTexture(io::IXMLReaderUTF8* reader)
|
|||
SColladaInput* input = getColladaInput(ECIS_IMAGE);
|
||||
if (input)
|
||||
{
|
||||
core::stringc imageName = input->Source;
|
||||
uriToId(imageName);
|
||||
for (u32 i=0; i<Images.size(); ++i)
|
||||
if ((imageName == Images[i].Id) && Images[i].Filename.size())
|
||||
{
|
||||
texture.Texture = Driver->getTexture(Images[i].Filename.c_str());
|
||||
break;
|
||||
}
|
||||
const core::stringc imageName = input->Source;
|
||||
texture.Texture = getTextureFromImage(imageName);
|
||||
}
|
||||
}
|
||||
|
||||
// add texture to list of loaded textures.
|
||||
Textures.push_back(texture);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1158,7 +1176,7 @@ void CColladaFileLoader::readMaterial(io::IXMLReaderUTF8* reader)
|
|||
#endif
|
||||
|
||||
SColladaMaterial material;
|
||||
material.Id = reader->getAttributeValue("id");
|
||||
material.Id = readId(reader);
|
||||
|
||||
if (Version >= 10400)
|
||||
{
|
||||
|
@ -1247,24 +1265,30 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
|
|||
{
|
||||
Effects.push_back(SColladaEffect());
|
||||
effect = &Effects.getLast();
|
||||
effect->Id = reader->getAttributeValue("id");
|
||||
effect->Id = readId(reader);
|
||||
}
|
||||
video::SColorf transparency;
|
||||
while(reader->read())
|
||||
{
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT)
|
||||
{
|
||||
if (profileCOMMONSectionName == reader->getNodeName())
|
||||
// first come the tags we descend, but ignore the top-levels
|
||||
if ((profileCOMMONSectionName == reader->getNodeName()) ||
|
||||
(techniqueNodeName == reader->getNodeName()))
|
||||
readEffect(reader,effect);
|
||||
else
|
||||
if (techniqueNodeName == reader->getNodeName())
|
||||
readEffect(reader,effect);
|
||||
if (newParamName == reader->getNodeName())
|
||||
readParameter(reader);
|
||||
else
|
||||
// these are the actual materials inside technique
|
||||
if (constantNode == reader->getNodeName() ||
|
||||
lambertNode == reader->getNodeName() ||
|
||||
phongNode == reader->getNodeName() ||
|
||||
blinnNode == reader->getNodeName())
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA reading effect part", reader->getNodeName());
|
||||
#endif
|
||||
effect->Mat.setFlag(irr::video::EMF_GOURAUD_SHADING,
|
||||
phongNode == reader->getNodeName() ||
|
||||
blinnNode == reader->getNodeName());
|
||||
|
@ -1272,7 +1296,10 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
|
|||
{
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT)
|
||||
{
|
||||
core::stringc node = reader->getNodeName();
|
||||
const core::stringc node = reader->getNodeName();
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA reading effect technique part", reader->getNodeName());
|
||||
#endif
|
||||
if (emissionNode == node || ambientNode == node ||
|
||||
diffuseNode == node || specularNode == node ||
|
||||
reflectiveNode == node || transparentNode == node )
|
||||
|
@ -1305,12 +1332,11 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
|
|||
textureNodeName == reader->getNodeName())
|
||||
{
|
||||
const core::stringc tname = reader->getAttributeValue("texture");
|
||||
for (u32 i=0; i<Images.size(); ++i)
|
||||
if ((tname == Images[i].Id) && Images[i].Filename.size())
|
||||
{
|
||||
effect->Mat.setTexture(0, Driver->getTexture(Images[i].Filename.c_str()));
|
||||
break;
|
||||
}
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA reading effect technique texture", tname.c_str());
|
||||
#endif
|
||||
effect->Mat.setTexture(0, getTextureFromImage(tname));
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT)
|
||||
|
@ -1397,6 +1423,7 @@ void CColladaFileLoader::readEffect(io::IXMLReaderUTF8* reader, SColladaEffect *
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (effect->Mat.AmbientColor == video::SColor(0) &&
|
||||
effect->Mat.DiffuseColor != video::SColor(0))
|
||||
effect->Mat.AmbientColor = effect->Mat.DiffuseColor;
|
||||
|
@ -1506,7 +1533,7 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
os::Printer::log("COLLADA reading geometry");
|
||||
#endif
|
||||
|
||||
core::stringc id = reader->getAttributeValue("id");
|
||||
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.
|
||||
|
@ -1534,10 +1561,10 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
{
|
||||
// create a new source
|
||||
sources.push_back(SSource());
|
||||
sources.getLast().Id = reader->getAttributeValue("id");
|
||||
sources.getLast().Id = readId(reader);
|
||||
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("Loaded source", sources.getLast().Id.c_str());
|
||||
os::Printer::log("Reading source", sources.getLast().Id.c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -1546,7 +1573,7 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
// create a new array and read it.
|
||||
if (!sources.empty())
|
||||
{
|
||||
sources.getLast().Array.Name = reader->getAttributeValue("id");
|
||||
sources.getLast().Array.Name = readId(reader);
|
||||
|
||||
int count = reader->getAttributeValueAsInt("count");
|
||||
sources.getLast().Array.Data.set_used(count); // pre allocate
|
||||
|
@ -1561,14 +1588,17 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
}
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
else
|
||||
os::Printer::log("Warning, array found, but no source",
|
||||
reader->getAttributeValue("id"));
|
||||
os::Printer::log("Warning, array outside source found",
|
||||
readId(reader).c_str());
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
if (accessorSectionName == nodeName) // child of source (below a technique tag)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("Reading accessor");
|
||||
#endif
|
||||
SAccessor accessor;
|
||||
accessor.Count = reader->getAttributeValueAsInt("count");
|
||||
accessor.Offset = reader->getAttributeValueAsInt("offset");
|
||||
|
@ -1582,12 +1612,15 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
if (!sources.empty())
|
||||
{
|
||||
sources.getLast().Accessors.push_back(accessor);
|
||||
sources.getLast().Accessors.getLast().Parameters = Parameters;
|
||||
sources.getLast().Accessors.getLast().Parameters = ColladaParameters;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (verticesSectionName == nodeName)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("Reading vertices");
|
||||
#endif
|
||||
// read vertex input position source
|
||||
readColladaInputs(reader, verticesSectionName);
|
||||
SColladaInput* input = getColladaInput(ECIS_POSITION);
|
||||
|
@ -1597,7 +1630,7 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
else
|
||||
// lines and linestrips missing
|
||||
if (polygonsSectionName == nodeName ||
|
||||
// polylistSectionName == nodeName ||
|
||||
polylistSectionName == nodeName ||
|
||||
trianglesSectionName == nodeName)
|
||||
{
|
||||
// read polygons section
|
||||
|
@ -1608,11 +1641,11 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
if (extraNodeName == reader->getNodeName())
|
||||
skipSection(reader, false);
|
||||
else
|
||||
if (techniqueCommonSectionName != nodeName) // techniqueCommon must not be skipped
|
||||
{
|
||||
// os::Printer::log("COLLADA loader warning: Wrong tag usage found", reader->getNodeName(), ELL_WARNING);
|
||||
skipSection(reader, true); // ignore all other sections
|
||||
}
|
||||
|
||||
} // end if node type is element
|
||||
else
|
||||
if (reader->getNodeType() == io::EXN_TEXT)
|
||||
|
@ -1690,12 +1723,6 @@ void CColladaFileLoader::readGeometry(io::IXMLReaderUTF8* reader)
|
|||
}
|
||||
|
||||
|
||||
struct SInputSlot
|
||||
{
|
||||
f32* Data; // Pointer to source data
|
||||
ECOLLADA_INPUT_SEMANTIC Semantic;
|
||||
};
|
||||
|
||||
struct SPolygon
|
||||
{
|
||||
core::array<s32> Indices;
|
||||
|
@ -1713,15 +1740,17 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
core::stringc materialName = reader->getAttributeValue("material");
|
||||
|
||||
core::stringc polygonType = reader->getNodeName();
|
||||
// int polygonCount = reader->getAttributeValueAsInt("count"); // Not useful because it only determines the number of p tags, not the number of tris
|
||||
core::array<SInputSlot> slots;
|
||||
// int polygonCount = reader->getAttributeValueAsInt("count"); // Not useful because it only determines the number of primitives, which have arbitrary vertices n case of polygon
|
||||
core::array<SPolygon> polygons;
|
||||
core::array<int> vCounts;
|
||||
bool parsePolygonOK = false;
|
||||
bool parseVcountOK = false;
|
||||
u32 inputSemanticCount = 0;
|
||||
bool unresolvedInput=false;
|
||||
u32 maxOffset = 0;
|
||||
Inputs.clear();
|
||||
|
||||
// read all <input> and
|
||||
// read all <input> and primitives
|
||||
if (!reader->isEmptyElement())
|
||||
while(reader->read())
|
||||
{
|
||||
|
@ -1735,52 +1764,53 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
// read input tag
|
||||
readColladaInput(reader);
|
||||
|
||||
// create new input slot
|
||||
if (!Inputs.empty())
|
||||
// resolve input source
|
||||
SColladaInput& inp = Inputs.getLast();
|
||||
core::stringc sourceArrayURI;
|
||||
|
||||
// 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)
|
||||
{
|
||||
SInputSlot slot;
|
||||
slot.Data=0;
|
||||
slot.Semantic = Inputs.getLast().Semantic;
|
||||
|
||||
core::stringc sourceArrayURI;
|
||||
|
||||
// get input source array id, if it is a vertex input, take
|
||||
// the <vertex><input>-source attribute.
|
||||
if (slot.Semantic == ECIS_VERTEX)
|
||||
sourceArrayURI = vertexPositionSource;
|
||||
else
|
||||
sourceArrayURI = Inputs.getLast().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)
|
||||
{
|
||||
// slot found
|
||||
slot.Data = sources[s].Array.Data.pointer();
|
||||
break;
|
||||
}
|
||||
|
||||
if (s == sources.size())
|
||||
os::Printer::log("COLLADA Warning, polygon input source not found",
|
||||
sourceArrayURI.c_str());
|
||||
else
|
||||
slots.push_back(slot);
|
||||
if (sources[s].Id == sourceArrayURI)
|
||||
{
|
||||
// slot found
|
||||
inp.Data = sources[s].Array.Data.pointer();
|
||||
inp.Stride = sources[s].Accessors[0].Stride;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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[Inputs.getLast().Semantic];
|
||||
tmp += inputSemanticNames[inp.Semantic];
|
||||
tmp += " sourceArray:";
|
||||
tmp += sourceArrayURI;
|
||||
os::Printer::log(tmp.c_str());
|
||||
#endif
|
||||
|
||||
++inputSemanticCount;
|
||||
}
|
||||
} // end is input node
|
||||
|
||||
maxOffset = core::max_(maxOffset,inp.Offset);
|
||||
++inputSemanticCount;
|
||||
}
|
||||
else
|
||||
if (primitivesName == nodeName)
|
||||
{
|
||||
|
@ -1792,8 +1822,6 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
{
|
||||
parseVcountOK = true;
|
||||
} // end is polygon node
|
||||
|
||||
|
||||
} // end is element node
|
||||
else
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT_END)
|
||||
|
@ -1875,25 +1903,24 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
parsePolygonOK = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // end while reader->read()
|
||||
|
||||
if (inputSemanticCount == 0 || inputSemanticCount != slots.size())
|
||||
if (inputSemanticCount == 0 || unresolvedInput)
|
||||
return; // we cannot create the mesh if one of the input semantics wasn't found.
|
||||
|
||||
if (!polygons.size())
|
||||
return; // cancel if there are no polygons anyway.
|
||||
|
||||
// analyze content of slots to create a fitting mesh buffer
|
||||
// analyze content of Inputs to create a fitting mesh buffer
|
||||
|
||||
u32 u;
|
||||
u32 textureCoordSetCount = 0;
|
||||
bool normalSlotCount = false;
|
||||
u32 secondTexCoordSetIndex = 0xFFFFFFFF;
|
||||
|
||||
for (u=0; u<slots.size(); ++u)
|
||||
for (u=0; u<Inputs.size(); ++u)
|
||||
{
|
||||
if (slots[u].Semantic == ECIS_TEXCOORD || slots[u].Semantic == ECIS_UV )
|
||||
if (Inputs[u].Semantic == ECIS_TEXCOORD || Inputs[u].Semantic == ECIS_UV )
|
||||
{
|
||||
++textureCoordSetCount;
|
||||
|
||||
|
@ -1901,7 +1928,7 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
secondTexCoordSetIndex = u;
|
||||
}
|
||||
else
|
||||
if (slots[u].Semantic == ECIS_NORMAL)
|
||||
if (Inputs[u].Semantic == ECIS_NORMAL)
|
||||
normalSlotCount=true;
|
||||
}
|
||||
|
||||
|
@ -1909,6 +1936,7 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
// otherwise use a standard mesh buffer
|
||||
|
||||
scene::IMeshBuffer* buffer = 0;
|
||||
++maxOffset; // +1 to jump to the next value
|
||||
|
||||
if ( textureCoordSetCount <= 1 )
|
||||
{
|
||||
|
@ -1924,37 +1952,37 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
core::array<u16> indices;
|
||||
|
||||
// for all index/semantic groups
|
||||
for (u32 v=0; v<polygons[i].Indices.size(); v+=inputSemanticCount)
|
||||
for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset)
|
||||
{
|
||||
video::S3DVertex vtx;
|
||||
vtx.Color.set(255,255,255,255);
|
||||
|
||||
// for all input semantics
|
||||
for (u32 k=0; k<slots.size(); ++k)
|
||||
for (u32 k=0; k<Inputs.size(); ++k)
|
||||
{
|
||||
if (!slots[k].Data)
|
||||
if (!Inputs[k].Data)
|
||||
continue;
|
||||
// build vertex from input semantics.
|
||||
|
||||
s32 idx = polygons[i].Indices[v+k];
|
||||
const u32 idx = Inputs[k].Stride*polygons[i].Indices[v+Inputs[k].Offset];
|
||||
|
||||
switch(slots[k].Semantic)
|
||||
switch(Inputs[k].Semantic)
|
||||
{
|
||||
case ECIS_POSITION:
|
||||
case ECIS_VERTEX:
|
||||
vtx.Pos.X = slots[k].Data[(idx*3)+0];
|
||||
vtx.Pos.Y = slots[k].Data[(idx*3)+1];
|
||||
vtx.Pos.Z = slots[k].Data[(idx*3)+2];
|
||||
vtx.Pos.X = Inputs[k].Data[idx+0];
|
||||
vtx.Pos.Y = Inputs[k].Data[idx+1];
|
||||
vtx.Pos.Z = Inputs[k].Data[idx+2];
|
||||
break;
|
||||
case ECIS_NORMAL:
|
||||
vtx.Normal.X = slots[k].Data[(idx*3)+0];
|
||||
vtx.Normal.Y = slots[k].Data[(idx*3)+1];
|
||||
vtx.Normal.Z = slots[k].Data[(idx*3)+2];
|
||||
vtx.Normal.X = Inputs[k].Data[idx+0];
|
||||
vtx.Normal.Y = Inputs[k].Data[idx+1];
|
||||
vtx.Normal.Z = Inputs[k].Data[idx+2];
|
||||
break;
|
||||
case ECIS_TEXCOORD:
|
||||
case ECIS_UV:
|
||||
vtx.TCoords.X = slots[k].Data[(idx*2)+0];
|
||||
vtx.TCoords.Y = slots[k].Data[(idx*2)+1];
|
||||
vtx.TCoords.X = Inputs[k].Data[idx+0];
|
||||
vtx.TCoords.Y = Inputs[k].Data[idx+1];
|
||||
break;
|
||||
case ECIS_TANGENT:
|
||||
break;
|
||||
|
@ -2011,45 +2039,45 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
|
|||
|
||||
for (u32 i=0; i<polygons.size(); ++i)
|
||||
{
|
||||
u32 vertexCount = polygons[i].Indices.size() / inputSemanticCount;
|
||||
u32 vertexCount = polygons[i].Indices.size() / maxOffset;
|
||||
|
||||
// for all vertices in array
|
||||
for (u32 v=0; v<polygons[i].Indices.size(); v+=inputSemanticCount)
|
||||
for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset)
|
||||
{
|
||||
video::S3DVertex2TCoords vtx;
|
||||
vtx.Color.set(100,255,255,255);
|
||||
|
||||
// for all input semantics
|
||||
for (u32 k=0; k<slots.size(); ++k)
|
||||
for (u32 k=0; k<Inputs.size(); ++k)
|
||||
{
|
||||
// build vertex from input semantics.
|
||||
|
||||
u32 idx = polygons[i].Indices[v+k];
|
||||
const u32 idx = Inputs[k].Stride*polygons[i].Indices[v+Inputs[k].Offset];
|
||||
|
||||
switch(slots[k].Semantic)
|
||||
switch(Inputs[k].Semantic)
|
||||
{
|
||||
case ECIS_POSITION:
|
||||
case ECIS_VERTEX:
|
||||
vtx.Pos.X = slots[k].Data[(idx*3)+0];
|
||||
vtx.Pos.Y = slots[k].Data[(idx*3)+1];
|
||||
vtx.Pos.Z = slots[k].Data[(idx*3)+2];
|
||||
vtx.Pos.X = Inputs[k].Data[idx+0];
|
||||
vtx.Pos.Y = Inputs[k].Data[idx+1];
|
||||
vtx.Pos.Z = Inputs[k].Data[idx+2];
|
||||
break;
|
||||
case ECIS_NORMAL:
|
||||
vtx.Normal.X = slots[k].Data[(idx*3)+0];
|
||||
vtx.Normal.Y = slots[k].Data[(idx*3)+1];
|
||||
vtx.Normal.Z = slots[k].Data[(idx*3)+2];
|
||||
vtx.Normal.X = Inputs[k].Data[idx+0];
|
||||
vtx.Normal.Y = Inputs[k].Data[idx+1];
|
||||
vtx.Normal.Z = Inputs[k].Data[idx+2];
|
||||
break;
|
||||
case ECIS_TEXCOORD:
|
||||
case ECIS_UV:
|
||||
if (k==secondTexCoordSetIndex)
|
||||
{
|
||||
vtx.TCoords2.X = slots[k].Data[(idx*2)+0];
|
||||
vtx.TCoords2.Y = slots[k].Data[(idx*2)+1];
|
||||
vtx.TCoords2.X = Inputs[k].Data[idx+0];
|
||||
vtx.TCoords2.Y = Inputs[k].Data[idx+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
vtx.TCoords.X = slots[k].Data[(idx*2)+0];
|
||||
vtx.TCoords.Y = slots[k].Data[(idx*2)+1];
|
||||
vtx.TCoords.X = Inputs[k].Data[idx+0];
|
||||
vtx.TCoords.Y = Inputs[k].Data[idx+1];
|
||||
}
|
||||
break;
|
||||
case ECIS_TANGENT:
|
||||
|
@ -2106,7 +2134,7 @@ void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader)
|
|||
os::Printer::log("COLLADA reading light prefab");
|
||||
#endif
|
||||
|
||||
CLightPrefab* prefab = new CLightPrefab(reader->getAttributeValue("id"));
|
||||
CLightPrefab* prefab = new CLightPrefab(readId(reader));
|
||||
|
||||
if (!reader->isEmptyElement())
|
||||
{
|
||||
|
@ -2124,9 +2152,9 @@ void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader)
|
|||
//! returns a collada parameter or none if not found
|
||||
SColladaParam* CColladaFileLoader::getColladaParameter(ECOLLADA_PARAM_NAME name)
|
||||
{
|
||||
for (u32 i=0; i<Parameters.size(); ++i)
|
||||
if (Parameters[i].Name == name)
|
||||
return &Parameters[i];
|
||||
for (u32 i=0; i<ColladaParameters.size(); ++i)
|
||||
if (ColladaParameters[i].Name == name)
|
||||
return &ColladaParameters[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2151,14 +2179,18 @@ void CColladaFileLoader::readColladaInput(io::IXMLReaderUTF8* reader)
|
|||
// get type
|
||||
core::stringc semanticName = reader->getAttributeValue("semantic");
|
||||
for (u32 i=0; inputSemanticNames[i]; ++i)
|
||||
{
|
||||
if (semanticName == inputSemanticNames[i])
|
||||
{
|
||||
p.Semantic = (ECOLLADA_INPUT_SEMANTIC)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// get source
|
||||
p.Source = reader->getAttributeValue("source");
|
||||
p.Offset = (u32)reader->getAttributeValueAsInt("offset");
|
||||
p.Set = (u32)reader->getAttributeValueAsInt("set");
|
||||
|
||||
// add input
|
||||
Inputs.push_back(p);
|
||||
|
@ -2190,7 +2222,7 @@ void CColladaFileLoader::readColladaInputs(io::IXMLReaderUTF8* reader, const cor
|
|||
void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader,
|
||||
const core::stringc& parentName)
|
||||
{
|
||||
Parameters.clear();
|
||||
ColladaParameters.clear();
|
||||
|
||||
const char* const paramNames[] = {"COLOR", "AMBIENT", "DIFFUSE",
|
||||
"SPECULAR", "SHININESS", "YFOV", "ZNEAR", "ZFAR", 0};
|
||||
|
@ -2241,7 +2273,7 @@ void CColladaFileLoader::readColladaParameters(io::IXMLReaderUTF8* reader,
|
|||
}
|
||||
|
||||
// add param
|
||||
Parameters.push_back(p);
|
||||
ColladaParameters.push_back(p);
|
||||
}
|
||||
else
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT_END)
|
||||
|
@ -2374,6 +2406,10 @@ video::SColorf CColladaFileLoader::readColorNode(io::IXMLReaderUTF8* reader)
|
|||
|
||||
f32 CColladaFileLoader::readFloatNode(io::IXMLReaderUTF8* reader)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA reading <float>");
|
||||
#endif
|
||||
|
||||
f32 result = 0.0f;
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT &&
|
||||
floatNodeName == reader->getNodeName())
|
||||
|
@ -2396,7 +2432,7 @@ void CColladaFileLoader::clearData()
|
|||
Prefabs.clear();
|
||||
|
||||
// clear all parameters
|
||||
Parameters.clear();
|
||||
ColladaParameters.clear();
|
||||
|
||||
// clear all materials
|
||||
Images.clear();
|
||||
|
@ -2432,6 +2468,114 @@ void CColladaFileLoader::uriToId(core::stringc& str)
|
|||
}
|
||||
|
||||
|
||||
//! read Collada Id, uses id or name if id is missing
|
||||
core::stringc CColladaFileLoader::readId(io::IXMLReaderUTF8* reader)
|
||||
{
|
||||
core::stringc id = reader->getAttributeValue("id");
|
||||
if (id.size()==0)
|
||||
id = reader->getAttributeValue("name");
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
//! create an Irrlicht texture from the reference
|
||||
video::ITexture* CColladaFileLoader::getTextureFromImage(core::stringc uri)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
uriToId(uri);
|
||||
for (u32 i=0; i<Images.size(); ++i)
|
||||
{
|
||||
if (uri == Images[i].Id)
|
||||
{
|
||||
if (Images[i].Source.size() && Images[i].SourceIsFilename)
|
||||
return Driver->getTexture(Images[i].Source.c_str());
|
||||
else
|
||||
if (Images[i].Source.size())
|
||||
{
|
||||
//const u32 size = Images[i].Dimension.getArea();
|
||||
const u32 size = Images[i].Dimension.Width * Images[i].Dimension.Height;;
|
||||
u32* data = new u32[size]; // we assume RGBA
|
||||
u32* ptrdest = data;
|
||||
const c8* ptrsrc = Images[i].Source.c_str();
|
||||
for (u32 j=0; j<size; ++j)
|
||||
{
|
||||
sscanf(ptrsrc, "%x", ptrdest);
|
||||
++ptrdest;
|
||||
ptrsrc += 4;
|
||||
}
|
||||
video::IImage* img = Driver->createImageFromData(video::ECF_A8R8G8B8, Images[i].Dimension, data, true, true);
|
||||
video::ITexture* tex = Driver->addTexture((CurrentlyLoadingMesh+"#"+Images[i].Id).c_str(), img);
|
||||
img->drop();
|
||||
return tex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Parameters.getAttributeType(uri.c_str())==io::EAT_STRING)
|
||||
uri = Parameters.getAttributeAsString(uri.c_str());
|
||||
else
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! read a parameter and value
|
||||
void CColladaFileLoader::readParameter(io::IXMLReaderUTF8* reader)
|
||||
{
|
||||
#ifdef COLLADA_READER_DEBUG
|
||||
os::Printer::log("COLLADA reading parameter");
|
||||
#endif
|
||||
|
||||
// if it's a new parameter
|
||||
if (newParamName == reader->getNodeName())
|
||||
{
|
||||
const core::stringc name = reader->getAttributeValue("sid");
|
||||
if (!reader->isEmptyElement())
|
||||
{
|
||||
while(reader->read())
|
||||
{
|
||||
if (reader->getNodeType() == io::EXN_ELEMENT)
|
||||
{
|
||||
if (floatNodeName == reader->getNodeName())
|
||||
{
|
||||
const f32 f = readFloatNode(reader);
|
||||
Parameters.addFloat(name.c_str(), f);
|
||||
}
|
||||
else
|
||||
if (float2NodeName == reader->getNodeName())
|
||||
{
|
||||
f32 f[2];
|
||||
readFloatsInsideElement(reader, f, 2);
|
||||
// Parameters.addVector2d(name.c_str(), core::vector2df(f[0],f[1]));
|
||||
}
|
||||
else
|
||||
if (float3NodeName == reader->getNodeName())
|
||||
{
|
||||
f32 f[3];
|
||||
readFloatsInsideElement(reader, f, 3);
|
||||
Parameters.addVector3d(name.c_str(), core::vector3df(f[0],f[1],f[2]));
|
||||
}
|
||||
else
|
||||
if ((initFromName == reader->getNodeName()) ||
|
||||
(sourceSectionName == reader->getNodeName()))
|
||||
{
|
||||
Parameters.addString(reader->getNodeData(), name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
if(reader->getNodeType() == io::EXN_ELEMENT_END)
|
||||
{
|
||||
if (newParamName == reader->getNodeName())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace scene
|
||||
} // end namespace irr
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "SMeshBuffer.h"
|
||||
#include "ISceneManager.h"
|
||||
#include "irrMap.h"
|
||||
#include "CAttributes.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
|
@ -83,19 +84,25 @@ enum ECOLLADA_INPUT_SEMANTIC
|
|||
struct SColladaInput
|
||||
{
|
||||
SColladaInput()
|
||||
: Semantic(ECIS_COUNT)
|
||||
: Semantic(ECIS_COUNT), Data(0), Offset(0), Set(0), Stride(1)
|
||||
{
|
||||
}
|
||||
|
||||
ECOLLADA_INPUT_SEMANTIC Semantic;
|
||||
core::stringc Source;
|
||||
f32* Data;
|
||||
u32 Offset;
|
||||
u32 Set;
|
||||
u32 Stride;
|
||||
};
|
||||
|
||||
//! Collada images
|
||||
struct SColladaImage
|
||||
{
|
||||
core::stringc Filename;
|
||||
core::stringc Id;
|
||||
core::stringc Source;
|
||||
core::dimension2di Dimension;
|
||||
bool SourceIsFilename;
|
||||
};
|
||||
|
||||
|
||||
|
@ -299,6 +306,9 @@ private:
|
|||
//! returns a collada input or none if not found
|
||||
SColladaInput* getColladaInput(ECOLLADA_INPUT_SEMANTIC input);
|
||||
|
||||
//! read Collada Id, uses id or name if id is missing
|
||||
core::stringc readId(io::IXMLReaderUTF8* reader);
|
||||
|
||||
//! changes the XML URI into an internal id
|
||||
void uriToId(core::stringc& str);
|
||||
|
||||
|
@ -313,6 +323,12 @@ private:
|
|||
//! reads and bind materials as given by the symbol->target bind mapping
|
||||
void readBindMaterialSection(io::IXMLReaderUTF8* reader, const core::stringc & id);
|
||||
|
||||
//! create an Irrlicht texture from the SColladaImage
|
||||
video::ITexture* getTextureFromImage(core::stringc uri);
|
||||
|
||||
//! read a parameter and value
|
||||
void readParameter(io::IXMLReaderUTF8* reader);
|
||||
|
||||
video::IVideoDriver* Driver;
|
||||
scene::ISceneManager* SceneManager;
|
||||
io::IFileSystem* FileSystem;
|
||||
|
@ -326,7 +342,7 @@ private:
|
|||
u32 Version;
|
||||
|
||||
core::array<IColladaPrefab*> Prefabs;
|
||||
core::array<SColladaParam> Parameters;
|
||||
core::array<SColladaParam> ColladaParameters;
|
||||
core::array<SColladaImage> Images;
|
||||
core::array<SColladaTexture> Textures;
|
||||
core::array<SColladaMaterial> Materials;
|
||||
|
@ -334,6 +350,7 @@ private:
|
|||
core::array<SColladaEffect> Effects;
|
||||
core::map<core::stringc,u32> MaterialsToBind;
|
||||
core::array< core::array<irr::scene::IMeshBuffer*> > MeshesToBind;
|
||||
io::CAttributes Parameters;
|
||||
|
||||
bool CreateInstances;
|
||||
};
|
||||
|
@ -351,7 +368,7 @@ public:
|
|||
scene::ISceneManager* mgr) = 0;
|
||||
|
||||
//! returns id of this prefab
|
||||
virtual const c8* getId() = 0;
|
||||
virtual const core::stringc& getId() = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue