diff --git a/changes.txt b/changes.txt index 81a8ea97..27f4b6cf 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,15 @@ Changes in 1.8 (??.??.2011) + - Colladawriter now exports materials per node when those are used in Irrlicht + + - Colladawriter now writing matrices for node transformations as old solution did not work with CDummyTransformationSceneNode's. + + - Colladawriter no longer create an extra node for the scenemanger as has that job in Collada. + + - Colladwriter no longer makes all Scenenodes children of ambient-light as that can be parallel on the same layer instead. + + - Colladareader now creates the ambient-light correct instead of creating a point-light for it. + - Add IAnimatedMeshSceneNode::getLoopMode (asked for by JLouisB) - CSceneNodeAnimatorCameraFPS now resets the key-input when it was disabled (thx @ gerdb for reporting and patch-proposal) diff --git a/source/Irrlicht/CColladaFileLoader.cpp b/source/Irrlicht/CColladaFileLoader.cpp index d1a3a365..0e2e334a 100644 --- a/source/Irrlicht/CColladaFileLoader.cpp +++ b/source/Irrlicht/CColladaFileLoader.cpp @@ -123,6 +123,9 @@ namespace const char* const inputSemanticNames[] = {"POSITION", "VERTEX", "NORMAL", "TEXCOORD", "UV", "TANGENT", "IMAGE", "TEXTURE", 0}; + + // We have to read ambient lights like other light types here, so we need a type for it + const video::E_LIGHT_TYPE ELT_AMBIENT = video::E_LIGHT_TYPE(video::ELT_COUNT+1); } //! following class is for holding and creating instances of library @@ -177,6 +180,12 @@ namespace os::Printer::log("COLLADA: Constructing light instance", Id.c_str(), ELL_DEBUG); #endif + if ( LightData.Type == ELT_AMBIENT ) + { + mgr->setAmbientLight( LightData.DiffuseColor ); + return 0; + } + scene::ILightSceneNode* l = mgr->addLightSceneNode(parent); if (l) { @@ -287,6 +296,7 @@ namespace { s->setName(getId()); s->getRelativeTransformationMatrix() = Transformation; + s->updateAbsolutePosition(); core::stringc t; for (u32 i=0; i<16; ++i) { @@ -2392,7 +2402,7 @@ void CColladaFileLoader::readLightPrefab(io::IXMLReaderUTF8* reader) prefab->LightData.Type=video::ELT_SPOT; else if (ambientSectionName == reader->getNodeName()) - prefab->LightData.Type=video::ELT_POINT; // TODO: This needs some change + prefab->LightData.Type=ELT_AMBIENT; else if (colorNodeName == reader->getNodeName()) prefab->LightData.DiffuseColor=readColorNode(reader); diff --git a/source/Irrlicht/CColladaMeshWriter.cpp b/source/Irrlicht/CColladaMeshWriter.cpp index ae7f6263..9531b093 100644 --- a/source/Irrlicht/CColladaMeshWriter.cpp +++ b/source/Irrlicht/CColladaMeshWriter.cpp @@ -253,18 +253,36 @@ bool CColladaMeshWriter::writeScene(io::IWriteFile* file, scene::ISceneNode* roo Writer->writeElement(L"visual_scene", false, L"id", L"default_scene"); Writer->writeLineBreak(); - // ambient light + // ambient light (instance_light also needs a node as parent so we have to create one) Writer->writeElement(L"node", false); Writer->writeLineBreak(); Writer->writeElement(L"instance_light", true, L"url", L"#ambientlight"); Writer->writeLineBreak(); - - // scenegraph - writeSceneNode(root); - Writer->writeClosingTag(L"node"); Writer->writeLineBreak(); + // Write the scenegraph. + if ( root->getType() != ESNT_SCENE_MANAGER ) + { + // TODO: Not certain if we should really write the root or if we should just always only write the children. + // For now writing root to keep backward compatibility for this case, but if anyone needs to _not_ write + // that root-node we can add a parameter for this later on in writeScene. + writeSceneNode(root); + } + else + { + // The visual_scene element is identical to our scenemanager and acts as root, + // so we do not write the root itself if it points to the scenemanager. + const core::list& rootChildren = root->getChildren(); + for ( core::list::ConstIterator it = rootChildren.begin(); + it != rootChildren.end(); + ++ it ) + { + writeSceneNode(*it); + } + } + + Writer->writeClosingTag(L"visual_scene"); Writer->writeLineBreak(); Writer->writeClosingTag(L"library_visual_scenes"); @@ -321,11 +339,29 @@ void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) IMesh* mesh = getProperties()->getMesh(node); if ( mesh ) { - MeshNode * n = Meshes.find(mesh); - if ( n && !n->getValue().MaterialWritten ) + if ( node->getType() == ESNT_MESH + && static_cast(node)->isReadOnlyMaterials() ) { - writeMeshMaterials(n->getValue().Name, mesh); - n->getValue().MaterialWritten = true; + // no material overrides - write mesh materials + MeshNode * n = Meshes.find(mesh); + if ( n && !n->getValue().MaterialWritten ) + { + writeMeshMaterials(n->getValue().Name, mesh); + n->getValue().MaterialWritten = true; + } + } + else + { + // write node materials + irr::core::stringw nodename(nameForNode(node)); + for (u32 i=0; igetMaterialCount(); ++i) + { + core::stringw strMat = "mat"; + strMat += nodename; + strMat += i; + + writeMaterial(strMat); + } } } @@ -336,6 +372,25 @@ void CColladaMeshWriter::writeNodeMaterials(irr::scene::ISceneNode * node) } } +void CColladaMeshWriter::writeMaterial(const irr::core::stringw& materialname) +{ + Writer->writeElement(L"material", false, + L"id", materialname.c_str(), + L"name", materialname.c_str()); + Writer->writeLineBreak(); + + // We don't make a difference between material and effect on export. + // Every material is just using an instance of an effect. + core::stringw strFx(materialname); + strFx += L"-fx"; + Writer->writeElement(L"instance_effect", true, + L"url", (core::stringw(L"#") + strFx).c_str()); + Writer->writeLineBreak(); + + Writer->writeClosingTag(L"material"); + Writer->writeLineBreak(); +} + void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node) { if ( !node || !getProperties() || !getProperties()->isExportable(node) ) @@ -344,21 +399,33 @@ void CColladaMeshWriter::writeNodeEffects(irr::scene::ISceneNode * node) IMesh* mesh = getProperties()->getMesh(node); if ( mesh ) { - MeshNode * n = Meshes.find(mesh); - if ( n && !n->getValue().EffectWritten ) + if ( node->getType() == ESNT_MESH + && static_cast(node)->isReadOnlyMaterials() ) { - irr::core::stringw meshname(n->getValue().Name); + // no material overrides - write mesh materials + MeshNode * n = Meshes.find(mesh); + if ( n && !n->getValue().EffectWritten ) + { + irr::core::stringw meshname(n->getValue().Name); + writeMeshEffects(meshname, mesh); + n->getValue().EffectWritten = true; + } + } + else + { + irr::core::stringw nodename(nameForNode(node)); + irr::core::stringw meshname(nameForMesh(mesh)); // still need meshname for textures + // write node materials for (u32 i=0; igetMaterialCount(); ++i) { core::stringw strMat = "mat"; - strMat += meshname; + strMat += nodename; strMat += i; strMat += L"-fx"; video::SMaterial & material = node->getMaterial(i); writeMaterialEffect(meshname, strMat, material); } - n->getValue().EffectWritten = true; } } @@ -505,12 +572,7 @@ void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node ) Writer->writeElement(L"node", false, L"id", nameId.c_str()); Writer->writeLineBreak(); - irr::core::vector3df rot(node->getRotation()); - writeTranslateElement( node->getPosition() ); - writeRotateElement( irr::core::vector3df(1.f, 0.f, 0.f), rot.X ); - writeRotateElement( irr::core::vector3df(0.f, 1.f, 0.f), rot.Y ); - writeRotateElement( irr::core::vector3df(0.f, 0.f, 1.f), rot.Z ); - writeScaleElement( node->getScale() ); + writeMatrixElement(node->getRelativeTransformation()); // instance geometry IMesh* mesh = getProperties()->getMesh(node); @@ -518,7 +580,7 @@ void CColladaMeshWriter::writeSceneNode(irr::scene::ISceneNode * node ) { MeshNode * n = Meshes.find(mesh); if ( n ) - writeMeshInstanceGeometry(n->getValue().Name, mesh); + writeMeshInstanceGeometry(n->getValue().Name, mesh, node); } // instance light @@ -648,8 +710,19 @@ bool CColladaMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 return true; } -void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh) +void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node) { + core::stringw materialOwner; + if ( !node || ( node->getType() == ESNT_MESH ) + && static_cast(node)->isReadOnlyMaterials() ) + { + materialOwner = meshname; + } + else + { + materialOwner = nameForNode(node); + } + // core::stringw meshId(meshname); Writer->writeElement(L"instance_geometry", false, L"url", toRef(meshId).c_str()); @@ -665,12 +738,13 @@ void CColladaMeshWriter::writeMeshInstanceGeometry(const irr::core::stringw& mes // for (u32 i=0; igetMeshBufferCount(); ++i) { - core::stringw strMat = "mat"; - strMat += meshname; - strMat += i; - core::stringw strMatInst(L"#"); - strMatInst += strMat; - Writer->writeElement(L"instance_material", false, L"symbol", strMat.c_str(), L"target", strMatInst.c_str()); + core::stringw strMatSymbol = "mat"; + strMatSymbol += meshname; + strMatSymbol += i; + core::stringw strMatTarget = "#mat"; + strMatTarget += materialOwner; + strMatTarget += i; + Writer->writeElement(L"instance_material", false, L"symbol", strMatSymbol.c_str(), L"target", strMatTarget.c_str()); Writer->writeLineBreak(); // @@ -960,18 +1034,7 @@ void CColladaMeshWriter::writeMeshMaterials(const irr::core::stringw& meshname, strMat += meshname; strMat += i; - Writer->writeElement(L"material", false, - L"id", strMat.c_str(), - L"name", strMat.c_str()); - Writer->writeLineBreak(); - - strMat += L"-fx"; - Writer->writeElement(L"instance_effect", true, - L"url", (core::stringw(L"#") + strMat).c_str()); - Writer->writeLineBreak(); - - Writer->writeClosingTag(L"material"); - Writer->writeLineBreak(); + writeMaterial(strMat); } } @@ -1922,6 +1985,29 @@ void CColladaMeshWriter::writeTranslateElement(const irr::core::vector3df& trans Writer->writeLineBreak(); } +void CColladaMeshWriter::writeMatrixElement(const irr::core::matrix4& matrix) +{ + Writer->writeElement(L"matrix", false); + Writer->writeLineBreak(); + + for ( int a=0; a<4; ++a ) + { + irr::core::stringw txt; + for ( int b=0; b<4; ++b ) + { + if ( b > 0 ) + txt += " "; + // row-column switched compared to Irrlicht + txt += irr::core::stringw(matrix[b*4+a]); + } + Writer->writeText(txt.c_str()); + Writer->writeLineBreak(); + } + + Writer->writeClosingTag(L"matrix"); + Writer->writeLineBreak(); +} + } // end namespace } // end namespace diff --git a/source/Irrlicht/CColladaMeshWriter.h b/source/Irrlicht/CColladaMeshWriter.h index 16b78a85..831667c0 100644 --- a/source/Irrlicht/CColladaMeshWriter.h +++ b/source/Irrlicht/CColladaMeshWriter.h @@ -111,7 +111,8 @@ protected: void writeMeshEffects(const irr::core::stringw& meshname, scene::IMesh* mesh); void writeMaterialEffect(const irr::core::stringw& meshname, const irr::core::stringw& materialname, const video::SMaterial & material); void writeMeshGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh); - void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh); + void writeMeshInstanceGeometry(const irr::core::stringw& meshname, scene::IMesh* mesh, scene::ISceneNode* node=0); + void writeMaterial(const irr::core::stringw& materialname); void writeLightInstance(const irr::core::stringw& lightName); void writeLibraryImages(); void writeColorFx(const irr::core::stringw& meshname, const video::SMaterial & material, const wchar_t * colorname, E_COLLADA_COLOR_SAMPLER cs, const wchar_t* attr1Name=0, const wchar_t* attr1Value=0); @@ -124,6 +125,7 @@ protected: void writeRotateElement(const irr::core::vector3df& axis, irr::f32 angle); void writeScaleElement(const irr::core::vector3df& scale); void writeTranslateElement(const irr::core::vector3df& translate); + void writeMatrixElement(const irr::core::matrix4& matrix); struct SComponentGlobalStartPos {