diff --git a/converter/COLLADA2GLTF/COLLADA2GLTFWriter.cpp b/converter/COLLADA2GLTF/COLLADA2GLTFWriter.cpp index 392d4c1fac..f8bbd9625a 100644 --- a/converter/COLLADA2GLTF/COLLADA2GLTFWriter.cpp +++ b/converter/COLLADA2GLTF/COLLADA2GLTFWriter.cpp @@ -331,7 +331,7 @@ namespace GLTF const InstanceControllerPointerArray& instanceControllers = node->getInstanceControllers(); unsigned int count = (unsigned int)instanceControllers.getCount(); if (count > 0) { - shared_ptr skins = this->_asset->root()->createObjectIfNeeded("skins"); + shared_ptr skins = this->_asset->root()->createObjectIfNeeded(kSkins); for (unsigned int i = 0 ; i < count; i++) { InstanceController* instanceController = instanceControllers[i]; MaterialBindingArray &materialBindings = instanceController->getMaterialBindings(); @@ -1112,7 +1112,9 @@ namespace GLTF if ( weights.getType() == COLLADAFW::FloatOrDoubleArray::DATA_TYPE_FLOAT ) { const COLLADAFW::FloatArray* floatWeights = weights.getFloatValues(); - for (size_t j = 0; j < pairCount; ++j, ++index) { + + + for (size_t j = 0; j < pairCount; ++j, ++index) { if (j < bucketSize) { bonesIndices[(i * bucketSize) + j] = (float)jointIndices[index]; weightsPtr[(i * bucketSize) + j] = (*floatWeights)[weightIndices[index]]; @@ -1130,7 +1132,7 @@ namespace GLTF } } } - + //inverse bind matrice const Matrix4Array& matrices = skinControllerData->getInverseBindMatrices(); size_t matricesSize = sizeof(float) * 16 * skinControllerData->getJointsCount(); @@ -1170,8 +1172,9 @@ namespace GLTF jointsAttribute->setCount(vertexCount); glTFSkin->setJoints(jointsAttribute); - - shared_ptr skins = this->_asset->root()->createObjectIfNeeded("skins"); + glTFSkin->setJointsCount(skinControllerData->getJointsCount()); + + shared_ptr skins = this->_asset->root()->createObjectIfNeeded(kSkins); //Also we work around here what looks to be a bug in OpenCOLLADA with a fileId == 0 COLLADAFW::UniqueId uniqueId = skinControllerData->getUniqueId(); @@ -1218,7 +1221,7 @@ namespace GLTF COLLADAFW::SkinController* skinController = (COLLADAFW::SkinController*)controller; //Now we get the skin and the mesh, and - shared_ptr skins = this->_asset->root()->createObjectIfNeeded("skins"); + shared_ptr skins = this->_asset->root()->createObjectIfNeeded(kSkins); COLLADAFW::UniqueId uniqueId = skinController->getSkinControllerData().toAscii(); if (uniqueId.getFileId() == 0) { diff --git a/converter/COLLADA2GLTF/GLTF/GLTFAsset.cpp b/converter/COLLADA2GLTF/GLTF/GLTFAsset.cpp index 9124cafc13..272b839000 100644 --- a/converter/COLLADA2GLTF/GLTF/GLTFAsset.cpp +++ b/converter/COLLADA2GLTF/GLTF/GLTFAsset.cpp @@ -604,16 +604,22 @@ namespace GLTF } shared_ptr techniqueExtras(new JSONObject()); - if ((meshExtras != nullptr) && meshExtras->contains("double_sided")) { - techniqueExtras->setBool("double_sided", meshExtras->getBool("double_sided")); + if (meshExtras != nullptr) { + if (meshExtras->contains("double_sided")) { + techniqueExtras->setBool("double_sided", meshExtras->getBool("double_sided")); + } + if (meshExtras->contains("jointsCount")) { + unsigned int jointsCount = meshExtras->getUnsignedInt32("jointsCount"); + techniqueExtras->setUnsignedInt32("jointsCount", jointsCount); + } } + if ((effectExtras != nullptr) && effectExtras->contains("double_sided")) { techniqueExtras->setBool("double_sided", effectExtras->getBool("double_sided")); } //generate shaders if needed shared_ptr attributeSemantics = serializeAttributeSemanticsForPrimitiveAtIndex(mesh.get(), (unsigned int)j); - shared_ptr techniqueGenerator(new JSONObject()); techniqueGenerator->setString("lightingModel", effect->getLightingModel()); @@ -622,6 +628,7 @@ namespace GLTF techniqueGenerator->setValue("techniqueExtras", techniqueExtras); techniqueGenerator->setValue("texcoordBindings", texcoordBindings); + effect->setTechniqueGenerator(techniqueGenerator); effect->setName(materialName); primitive->setMaterialID(effect->getID()); @@ -660,6 +667,18 @@ namespace GLTF if (materialBindings == nullptr) return false; + size_t jointsCount = 0; + if (node->contains(kInstanceSkin)) { + shared_ptr instanceSkin = node->getObject(kInstanceSkin); + if (instanceSkin->contains(kSkin)) { + std::string skinOriginalID = instanceSkin->getString(kSkin); + shared_ptr skins = this->_root->createObjectIfNeeded(kSkins); + std::vector skinUIDs = skins->getAllKeys(); + shared_ptr skin = static_pointer_cast(skins->getObject(skinOriginalID) ); + jointsCount = skin->getJointsCount(); + } + } + shared_ptr meshesArray = nullptr; MaterialBindingsForMeshUID::const_iterator materialBindingsIterator; @@ -691,11 +710,16 @@ namespace GLTF } assert(meshesInSkinning || meshesInNode); - + shared_ptr materialBindingsPrimitiveMap = (*materialBindingsIterator).second; - shared_ptr meshExtras = this->_extras->contains(meshUID) ? this->_extras->getObject(meshUID) : nullptr; + if (jointsCount > 0) { + if (meshExtras == nullptr) + meshExtras = shared_ptr (new JSONObject()); + meshExtras->setUnsignedInt32("jointsCount", jointsCount); + } + shared_ptr mesh = static_pointer_cast(this->getValueForUniqueId(meshUID)); this->_applyMaterialBindings(mesh, materialBindingsPrimitiveMap, meshesArray, meshExtras); @@ -783,6 +807,17 @@ namespace GLTF } } + // ---- + shared_ptr skins = this->_root->createObjectIfNeeded(kSkins); + std::vector skinsUIDs = skins->getAllKeys(); + for (size_t skinIndex = 0 ; skinIndex < skinsUIDs.size() ; skinIndex++) { + shared_ptr skin = static_pointer_cast(skins->getObject(skinsUIDs[skinIndex])); + skins->setValue(skin->getId(), skin); + skins->removeValue(skinsUIDs[skinIndex]); + } + //we change the keys... + skinsUIDs = skins->getAllKeys(); + //Handle late binding of material in node //So we go through all nodes and if a mesh got different bindings than the ones needed we clone the "reference" mesh and assign the binding //we delay this operation to now, so that we get the reference mesh splitted. @@ -932,11 +967,7 @@ namespace GLTF } // ---- - shared_ptr skins = this->_root->createObjectIfNeeded("skins"); - std::vector skinsUIDs = skins->getAllKeys(); - for (size_t skinIndex = 0 ; skinIndex < skinsUIDs.size() ; skinIndex++) { - shared_ptr skin = static_pointer_cast(skins->getObject(skinsUIDs[skinIndex])); shared_ptr joints = skin->getJointsIds(); shared_ptr jointsWithOriginalSids(new JSONArray()); @@ -954,8 +985,6 @@ namespace GLTF shared_ptr inverseBindMatrices = static_pointer_cast(skin->extras()->getValue(kInverseBindMatrices)); inverseBindMatrices->setString(kBufferView, genericBufferView->getID()); skin->setValue(kInverseBindMatrices, inverseBindMatrices); - skins->setValue(skin->getId(), skin); - skins->removeValue(skinsUIDs[skinIndex]); } // ---- diff --git a/converter/COLLADA2GLTF/GLTF/GLTFSkin.cpp b/converter/COLLADA2GLTF/GLTF/GLTFSkin.cpp index 16093d292e..bbc1322d12 100644 --- a/converter/COLLADA2GLTF/GLTF/GLTFSkin.cpp +++ b/converter/COLLADA2GLTF/GLTF/GLTFSkin.cpp @@ -46,11 +46,11 @@ namespace GLTF //--- Skin - GLTFSkin::GLTFSkin() : GLTFController() { + GLTFSkin::GLTFSkin() : GLTFController(), _jointsCount(0) { this->_id = GLTFUtils::generateIDForType(kSkin.c_str()); } - GLTFSkin::GLTFSkin(std::string id) : GLTFController() { + GLTFSkin::GLTFSkin(std::string id) : GLTFController(), _jointsCount(0) { this->_id = id; } @@ -114,4 +114,12 @@ namespace GLTF return this->_inverseBindMatrices; } + void GLTFSkin::setJointsCount(size_t count) { + this->_jointsCount = count; + } + + size_t GLTFSkin::getJointsCount() { + return this->_jointsCount; + } + }; diff --git a/converter/COLLADA2GLTF/GLTF/GLTFSkin.h b/converter/COLLADA2GLTF/GLTF/GLTFSkin.h index 5bf3379d9a..eb121ea206 100644 --- a/converter/COLLADA2GLTF/GLTF/GLTFSkin.h +++ b/converter/COLLADA2GLTF/GLTF/GLTFSkin.h @@ -67,6 +67,9 @@ namespace GLTF //controller std::string getType(); + void setJointsCount(size_t count); + size_t getJointsCount(); + private: std::shared_ptr _inverseBindMatrices; @@ -75,6 +78,8 @@ namespace GLTF std::string _id; std::string _sourceUID; + + size_t _jointsCount; }; } diff --git a/converter/COLLADA2GLTF/GLTF/GLTFTypesAndConstants.h b/converter/COLLADA2GLTF/GLTF/GLTFTypesAndConstants.h index f802b2d5ba..b7f1637ea0 100644 --- a/converter/COLLADA2GLTF/GLTF/GLTFTypesAndConstants.h +++ b/converter/COLLADA2GLTF/GLTF/GLTFTypesAndConstants.h @@ -77,6 +77,7 @@ const std::string kChildren = "children"; const std::string kSources = "sources"; const std::string kSource = "source"; const std::string kSkin = "skin"; +const std::string kSkins = "skins"; const std::string kInstanceSkin = "instanceSkin"; const std::string kImages = "images"; const std::string kImage = "image"; diff --git a/converter/COLLADA2GLTF/shaders/commonProfileShaders.cpp b/converter/COLLADA2GLTF/shaders/commonProfileShaders.cpp index 7df4fc86f2..ef91e3d965 100644 --- a/converter/COLLADA2GLTF/shaders/commonProfileShaders.cpp +++ b/converter/COLLADA2GLTF/shaders/commonProfileShaders.cpp @@ -263,6 +263,8 @@ namespace GLTF */ static std::string buildTechniqueHash(shared_ptr parameters, shared_ptr techniqueExtras, GLTFAsset* asset) { std::string techniqueHash = ""; + bool doubleSided = false; + unsigned int jointsCount = 0; techniqueHash += buildSlotHash(parameters, "diffuse", asset); techniqueHash += buildSlotHash(parameters, "ambient", asset); @@ -271,8 +273,13 @@ namespace GLTF techniqueHash += buildSlotHash(parameters, "reflective", asset); //techniqueHash += buildLightsHash(parameters, techniqueExtras, context); - if (techniqueExtras) - techniqueHash += "double_sided:" + GLTFUtils::toString(techniqueExtras->getBool("double_sided")); + if (techniqueExtras) { + jointsCount = techniqueExtras->getUnsignedInt32("jointsCount"); + doubleSided = techniqueExtras->getBool("double_sided"); + } + + techniqueHash += "double_sided:" + GLTFUtils::toString(doubleSided); + techniqueHash += "jointsCount:" + GLTFUtils::toString(jointsCount); techniqueHash += "opaque:"+ GLTFUtils::toString(isOpaque(parameters, asset)); techniqueHash += "hasTransparency:"+ GLTFUtils::toString(hasTransparency(parameters, asset)); @@ -671,7 +678,14 @@ namespace GLTF bool useSimpleLambert = !(inputParameters->contains("specular") && inputParameters->contains("shininess")); - bool hasSkinning = attributeSemantics->contains("WEIGHT") && attributeSemantics->contains("JOINT"); + unsigned int jointsCount = 0; + bool hasSkinning = false; + if (techniqueExtras != nullptr) { + jointsCount = techniqueExtras->getUnsignedInt32("jointsCount"); + hasSkinning = attributeSemantics->contains("WEIGHT") && + attributeSemantics->contains("JOINT") && + (jointsCount > 0); + } std::vector allAttributes; std::vector allUniforms; @@ -695,13 +709,14 @@ namespace GLTF if (hasSkinning) { addSemantic("vs", "attribute", - "JOINT", "joint", 1, true); + "JOINT", "joint", 1, false); addSemantic("vs", "attribute", - "WEIGHT", "weight", 1, true); - //addValue("vs", "uniform", "FLOAT_MAT4", 60, "jointMat"); + "WEIGHT", "weight", 1, false); + + assert(techniqueExtras != nullptr); + addSemantic("vs", "uniform", - "JOINT_MATRIX", "jointMat", 60, false); - + "JOINT_MATRIX", "jointMat", jointsCount, false); } if (hasNormals) { @@ -709,6 +724,7 @@ namespace GLTF addSemantic("vs", "uniform", MODELVIEWINVERSETRANSPOSE, "normalMatrix" , 1, false); } + //modeliew matrix addSemantic("vs", "uniform", MODELVIEW, "modelViewMatrix" , 1, false); @@ -717,8 +733,7 @@ namespace GLTF addSemantic("vs", "uniform", PROJECTION, "projectionMatrix" , 1, false); - - /* + /* Handle hardware skinning, for now with a fixed limit of 4 influences */