void GLTFAnimation::writeAnimationForTargetID(const std::string &targetID, GLTFAsset* asset) { shared_ptr <JSONObject> target = this->targets()->getObject(targetID); shared_ptr<GLTFAnimationFlattener> animationFlattener = this->animationFlattenerForTargetUID(targetID); size_t count = 0; float* rotations = 0; float* positions = 0; float* scales = 0; animationFlattener->allocAndFillAffineTransformsBuffers(&positions, &rotations, &scales, count); if (animationFlattener->hasAnimatedScale()) { //Scale setupAndWriteAnimationParameter(this, "scale", "FLOAT_VEC3", (unsigned char*)scales, count * sizeof(float) * 3, false, asset); __AddChannel(this, targetID, "scale"); free(scales); } if (animationFlattener->hasAnimatedTranslation()) { //Translation setupAndWriteAnimationParameter(this, "translation", "FLOAT_VEC3", (unsigned char*)positions, count * sizeof(float) * 3, false, asset); __AddChannel(this, targetID, "translation"); free(positions); } if (animationFlattener->hasAnimatedRotation()) { //Rotation setupAndWriteAnimationParameter(this, "rotation", "FLOAT_VEC4", (unsigned char*)rotations, count * sizeof(float) * 4, false, asset); __AddChannel(this, targetID, "rotation"); free(rotations); } }
bool writeAnimation(shared_ptr <GLTFAnimation> cvtAnimation, const COLLADAFW::AnimationList::AnimationClass animationClass, AnimatedTargetsSharedPtr animatedTargets, GLTF::GLTFConverterContext &converterContext) { shared_ptr<JSONObject> samplers = cvtAnimation->samplers(); shared_ptr<JSONArray> channels = cvtAnimation->channels(); GLTFAnimation::Parameter *timeParameter = cvtAnimation->getParameterNamed("TIME"); shared_ptr<GLTFBufferView> timeBufferView = timeParameter->getBufferView(); std::string name = "TIME"; std::string samplerID = cvtAnimation->getSamplerIDForName(name); cvtAnimation->removeParameterNamed("TIME"); setupAndWriteAnimationParameter(cvtAnimation, "TIME", "FLOAT", (unsigned char*)timeBufferView->getBufferDataByApplyingOffset(), timeBufferView->getByteLength(), converterContext); //timeParameter->setByteOffset(outputStream->length()); //outputStream->write(timeBufferView); //printf("time bufferLength: %d\n",(int)timeBufferView->getByteLength()); switch (animationClass) { case COLLADAFW::AnimationList::TIME: { //In Currrent OpenCOLLADA Implementation, this is never called, only cases mapping to OUTPUT are, so we handle INPUT (i.e time) when we enter this function. } break; case COLLADAFW::AnimationList::AXISANGLE: { GLTFAnimation::Parameter *parameter = cvtAnimation->getParameterNamed("OUTPUT"); if (parameter) { shared_ptr<GLTFBufferView> bufferView = parameter->getBufferView(); //the angles to radians necessary convertion is done within the animationFlattener //but it might be better to make it before... for (size_t animatedTargetIndex = 0 ; animatedTargetIndex < animatedTargets->size() ; animatedTargetIndex++) { shared_ptr<JSONObject> animatedTarget = (*animatedTargets)[animatedTargetIndex]; std::string targetID = animatedTarget->getString("target"); if (converterContext._uniqueIDToTrackedObject.count(targetID) != 0) { cvtAnimation->targets()->setValue(targetID, animatedTarget); shared_ptr<JSONObject> targetObject = converterContext._uniqueIDToTrackedObject[targetID]; std::string path = animatedTarget->getString("path"); if (path == "rotation") { std::string transformID = animatedTarget->getString("transformId"); shared_ptr<GLTFAnimationFlattener> animationFlattener = converterContext._uniqueIDToAnimationFlattener[targetID]; float* timeValues = (float*)timeBufferView->getBufferDataByApplyingOffset(); float* rotations = (float*)bufferView->getBufferDataByApplyingOffset(); for (size_t k = 0 ; k < cvtAnimation->getCount() ; k++) { size_t offset = k * 4; shared_ptr <COLLADAFW::Rotate> rotate(new COLLADAFW::Rotate(rotations[offset + 0], rotations[offset + 1], rotations[offset + 2], rotations[offset + 3])); animationFlattener->insertTransformAtTime(transformID, rotate, timeValues[k]); } } } } } cvtAnimation->removeParameterNamed("OUTPUT"); } break; case COLLADAFW::AnimationList::MATRIX4X4: { GLTFAnimation::Parameter *parameter = cvtAnimation->getParameterNamed("OUTPUT"); if (parameter) { std::vector< shared_ptr <GLTFBufferView> > TRSBufferViews; //FIXME: we assume float here, might be double shared_ptr<GLTFBufferView> bufferView = parameter->getBufferView(); float* matrices = (float*)bufferView->getBufferDataByApplyingOffset(); float* timeValues = (float*)timeBufferView->getBufferDataByApplyingOffset(); for (size_t animatedTargetIndex = 0 ; animatedTargetIndex < animatedTargets->size() ; animatedTargetIndex++) { shared_ptr<JSONObject> animatedTarget = (*animatedTargets)[animatedTargetIndex]; if (animatedTarget->getString("path") == "MATRIX") { std::string targetID = animatedTarget->getString("target"); if (converterContext._uniqueIDToTrackedObject.count(targetID) != 0) { cvtAnimation->targets()->setValue(targetID, animatedTarget); std::string transformID = animatedTarget->getString("transformId"); shared_ptr<GLTFAnimationFlattener> animationFlattener = converterContext._uniqueIDToAnimationFlattener[targetID]; for (size_t k = 0 ; k < cvtAnimation->getCount() ; k++) { size_t offset = k * 16; float *m = matrices + offset; COLLADABU::Math::Matrix4 mat; mat.setAllElements(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] ); shared_ptr <COLLADAFW::Matrix> matTr(new COLLADAFW::Matrix(mat)); animationFlattener->insertTransformAtTime(transformID, matTr, timeValues[k]); } } } } cvtAnimation->removeParameterNamed("OUTPUT"); } else { //FIXME: report error printf("WARNING: cannot find intermediate parameter named OUTPUT\n"); } } return true; break; case COLLADAFW::AnimationList::POSITION_XYZ: { GLTFAnimation::Parameter *parameter = cvtAnimation->getParameterNamed("OUTPUT"); if (parameter) { shared_ptr<GLTFBufferView> bufferView = parameter->getBufferView(); //the angles to radians necessary convertion is done within the animationFlattener //but it might be better to make it before... for (size_t animatedTargetIndex = 0 ; animatedTargetIndex < animatedTargets->size() ; animatedTargetIndex++) { shared_ptr<JSONObject> animatedTarget = (*animatedTargets)[animatedTargetIndex]; std::string targetID = animatedTarget->getString("target"); if (converterContext._uniqueIDToTrackedObject.count(targetID) != 0) { cvtAnimation->targets()->setValue(targetID, animatedTarget); shared_ptr<JSONObject> targetObject = converterContext._uniqueIDToTrackedObject[targetID]; std::string path = animatedTarget->getString("path"); if (path == "translation") { std::string transformID = animatedTarget->getString("transformId"); shared_ptr<GLTFAnimationFlattener> animationFlattener = converterContext._uniqueIDToAnimationFlattener[targetID]; float* timeValues = (float*)timeBufferView->getBufferDataByApplyingOffset(); float* translations = (float*)bufferView->getBufferDataByApplyingOffset(); for (size_t k = 0 ; k < cvtAnimation->getCount() ; k++) { size_t offset = k * 3; shared_ptr <COLLADAFW::Translate> translate(new COLLADAFW::Translate(translations[offset + 0], translations[offset + 1], translations[offset + 2])); animationFlattener->insertTransformAtTime(transformID, translate, timeValues[k]); } } else if (path == "scale") { std::string transformID = animatedTarget->getString("transformId"); shared_ptr<GLTFAnimationFlattener> animationFlattener = converterContext._uniqueIDToAnimationFlattener[targetID]; float* timeValues = (float*)timeBufferView->getBufferDataByApplyingOffset(); float* scales = (float*)bufferView->getBufferDataByApplyingOffset(); for (size_t k = 0 ; k < cvtAnimation->getCount() ; k++) { size_t offset = k * 3; shared_ptr <COLLADAFW::Scale> scale(new COLLADAFW::Scale(scales[offset + 0], scales[offset + 1], scales[offset + 2])); animationFlattener->insertTransformAtTime(transformID, scale, timeValues[k]); } } } } } cvtAnimation->removeParameterNamed("OUTPUT"); } return true; case COLLADAFW::AnimationList::ANGLE: { GLTFAnimation::Parameter *parameter = cvtAnimation->getParameterNamed("OUTPUT"); if (parameter) { shared_ptr<GLTFBufferView> bufferView = parameter->getBufferView(); //the angles to radians necessary convertion is done within the animationFlattener //but it might be better to make it before... for (size_t animatedTargetIndex = 0 ; animatedTargetIndex < animatedTargets->size() ; animatedTargetIndex++) { shared_ptr<JSONObject> animatedTarget = (*animatedTargets)[animatedTargetIndex]; std::string targetID = animatedTarget->getString("target"); if (converterContext._uniqueIDToTrackedObject.count(targetID) != 0) { cvtAnimation->targets()->setValue(targetID, animatedTarget); shared_ptr<JSONObject> targetObject = converterContext._uniqueIDToTrackedObject[targetID]; std::string path = animatedTarget->getString("path"); if (path == "rotation") { std::string transformID = animatedTarget->getString("transformId"); shared_ptr<GLTFAnimationFlattener> animationFlattener = converterContext._uniqueIDToAnimationFlattener[targetID]; float* timeValues = (float*)timeBufferView->getBufferDataByApplyingOffset(); float* rotations = (float*)bufferView->getBufferDataByApplyingOffset(); for (size_t k = 0 ; k < cvtAnimation->getCount() ; k++) { animationFlattener->insertValueAtTime(transformID, rotations[k], 3, timeValues[k]); } } } } } cvtAnimation->removeParameterNamed("OUTPUT"); } return true; case COLLADAFW::AnimationList::POSITION_X: case COLLADAFW::AnimationList::POSITION_Y: case COLLADAFW::AnimationList::POSITION_Z: { int index = animationClass - COLLADAFW::AnimationList::POSITION_X; GLTFAnimation::Parameter *parameter = cvtAnimation->getParameterNamed("OUTPUT"); if (parameter) { shared_ptr<GLTFBufferView> bufferView = parameter->getBufferView(); for (size_t animatedTargetIndex = 0 ; animatedTargetIndex < animatedTargets->size() ; animatedTargetIndex++) { shared_ptr<JSONObject> animatedTarget = (*animatedTargets)[animatedTargetIndex]; std::string targetID = animatedTarget->getString("target"); if (converterContext._uniqueIDToTrackedObject.count(targetID) != 0) { cvtAnimation->targets()->setValue(targetID, animatedTarget); shared_ptr<JSONObject> targetObject = converterContext._uniqueIDToTrackedObject[targetID]; std::string path = animatedTarget->getString("path"); if (path == "translation") { std::string transformID = animatedTarget->getString("transformId"); shared_ptr<GLTFAnimationFlattener> animationFlattener = converterContext._uniqueIDToAnimationFlattener[targetID]; float* timeValues = (float*)timeBufferView->getBufferDataByApplyingOffset(); float* translations = (float*)bufferView->getBufferDataByApplyingOffset(); for (size_t k = 0 ; k < cvtAnimation->getCount() ; k++) { animationFlattener->insertValueAtTime(transformID, translations[k], index, timeValues[k]); } } else if (path == "scale") { std::string transformID = animatedTarget->getString("transformId"); shared_ptr<GLTFAnimationFlattener> animationFlattener = converterContext._uniqueIDToAnimationFlattener[targetID]; float* timeValues = (float*)timeBufferView->getBufferDataByApplyingOffset(); float* scales = (float*)bufferView->getBufferDataByApplyingOffset(); for (size_t k = 0 ; k < cvtAnimation->getCount() ; k++) { animationFlattener->insertValueAtTime(transformID, scales[k], index, timeValues[k]); } } else { assert(0 && "unknown path name"); } } } } cvtAnimation->removeParameterNamed("OUTPUT"); } return true; case COLLADAFW::AnimationList::COLOR_RGB: case COLLADAFW::AnimationList::COLOR_RGBA: case COLLADAFW::AnimationList::COLOR_R: case COLLADAFW::AnimationList::COLOR_G: case COLLADAFW::AnimationList::COLOR_B: case COLLADAFW::AnimationList::COLOR_A: case COLLADAFW::AnimationList::ARRAY_ELEMENT_1D: case COLLADAFW::AnimationList::ARRAY_ELEMENT_2D: case COLLADAFW::AnimationList::FLOAT: default: static bool printedOnce = false; if (!printedOnce) { printf("WARNING: unhandled transform type\n"); printedOnce = true; } break; } return false; }