v.sergeev Posted April 23, 2013 Share Posted April 23, 2013 Hello! I have some problems with animation tracks. In our project, we solved them. It would be desirable that the decision appeared and in UNiGiNE.When we remove animation layer (ObjectMeshSkinned::removeLayer / setNumLayers) bones don't recalculated. See void MeshSkinned::update_frames // single layer if(instance->layers.size() == 1) { const Layer &layer = instance->layers[0]; const char *bones_0 = layer.bones.get(); const Frame *frames_0 = layer.frames.get(); for(int i = 0; i < num_frames; i++) { if(bones_0 == 0) continue; frames.xyz = frames_0.xyz; frames.rot = frames_0.rot; bones = 1; } } This condition skeep inactive bonesif(bones_0 == 0) continue; We can activate bone by calingObjectMeshSkinned::setFrameBoneTransform or ObjectMeshSkinned::setFrame. Maybe it is worth proposing the standard solution? Link to comment
v.sergeev Posted April 23, 2013 Author Share Posted April 23, 2013 Our solution. Sorry, comments in russian :ph34r: //-------------------------------------------------------------------------- /// Удалить анимационный слой bool CObjectMeshSkinned::RemoveAnimationLayer(int idAnimation_) { TIdAnim2Layer::iterator itLayer = m_IdAnim2Layer.find(idAnimation_); if (itLayer == m_IdAnim2Layer.end() || itLayer->second < 0) return false; // такого слоя не существует ::ObjectMeshSkinned* pOMS = getOMS(); size_t nNumLayers = m_IdAnim2Layer.size() - 1; if (0 == nNumLayers) { pOMS->removeLayer(itLayer->second); itLayer->second = -1; updateBonesFromZeroLayer(); return true; } // сохраним информацию о настройках анимационных дорожек перед исключением слоя, // т.к потом в мапке m_IdAnim2Layer поплывут все индексы слоев struct SAnimContext { int idAnim, from, to; float frameTime, weight; TIdAnim2Layer::iterator itAnimMap; } animContext; bm::vector<SAnimContext> animsParams; animsParams.reserve(nNumLayers); TIdAnim2Layer::iterator it = m_IdAnim2Layer.begin(), iEnd = m_IdAnim2Layer.end(); do { if (it == itLayer || it->second < 0) continue; // слой для удаления или не активный его запоминатьне будем animContext.idAnim = it->first; pOMS->setLayer(it->second); assert(pOMS->getAnimationID() == animContext.idAnim); // есть синхронизация с движком animContext.from = pOMS->getFrameFrom(); animContext.to = pOMS->getFrameTo(); animContext.frameTime = pOMS->getFrameTime(); animContext.weight = pOMS->getWeight(); animContext.itAnimMap = it; animsParams.push_back(animContext); } while (++it != iEnd); itLayer->second = -1; // ребиндинг анимаций и слоев // Скорей всего потрем анимацию костей из 0 слоя выставленную кодом (xml каналами) pOMS->setNumLayers(animsParams.size() + 1); for (int i = 0, nCount = (int)animsParams.size(); i < nCount; ) { const SAnimContext& animContext = animsParams; int nLayer = ++i; pOMS->setLayer(nLayer); pOMS->setAnimationID(animContext.idAnim); pOMS->setWeight(animContext.weight); pOMS->setFrame(animContext.frameTime, animContext.from, animContext.to); animContext.itAnimMap->second = nLayer; assert(animContext.itAnimMap->first == animContext.idAnim); } updateBonesFromZeroLayer(); return true; } //-------------------------------------------------------------------------- /// Активизировать трансформацию костей из 0 анимационного слоя. /// Такие штуки нужны для того, чтобы восстановить исходное положение костей /// с учетом выставленных значений через программные интерфейс SetBoneTransform. /// Такой код нужен из-за логической кривизны UNiGiNE /// см. методы MeshSkinned::update_frames, MeshSkinned::setFrame, MeshSkinned::getFrame /// Если кость не активная, то трансформация с нее не читается. /// Активизировать кость можно вызовом метода MeshSkinned::setFrame/setFrameBoneTransform /// это приводит к записи 1 в layer.bones[bone] = 1; void CObjectMeshSkinned::updateBonesFromZeroLayer() { ::ObjectMeshSkinned* pOMS = getOMS(); pOMS->setLayer(0); const int numMaxBones = 128; int numBones = pOMS->getNumBones(); assert(numBones < numMaxBones); VectorStack<mat4, numMaxBones> bonesTransform; // Опрашиваем текущие трансформации костей for (int i = 0; i < numBones; ++i) bonesTransform.appendFast(pOMS->getFrameBoneTransform(i)); // Выставляем теже самые трансформации костей for (int i = 0; i < numBones; ++i) pOMS->setFrameBoneTransform(i, bonesTransform); // Возможно стоит скинуть еще Кеш углов Эйлера } Link to comment
frustum Posted June 23, 2013 Share Posted June 23, 2013 You can copy your layer transformations into the buffer and restore it after layer removing. Moreover setFrameBoneTransformEnabled/setBufferBoneTransformEnabled() function will be available in the next SDK. Link to comment
Recommended Posts