void buildBoneTree(akSkeleton* skel, btAlignedObjectArray<akMatrix4>& bind, Blender::Bone* bone, UTuint8 parent) { //if(!(bone->flag & BONE_NO_DEFORM) || parent == AK_JOINT_NO_PARENT) { utHashedString jname = bone->name; float* bmat = (float*)bone->arm_mat; akMatrix4 mat(akVector4(bmat[4*0+0], bmat[4*0+1], bmat[4*0+2], bmat[4*0+3]), akVector4(bmat[4*1+0], bmat[4*1+1], bmat[4*1+2], bmat[4*1+3]), akVector4(bmat[4*2+0], bmat[4*2+1], bmat[4*2+2], bmat[4*2+3]), akVector4(bmat[4*3+0], bmat[4*3+1], bmat[4*3+2], bmat[4*3+3])); bind.push_back(mat); parent = skel->addJoint(jname, parent); if(bone->flag & BONE_NO_SCALE) skel->getJoint(parent)->m_inheritScale = false; } Blender::Bone* chi = static_cast<Blender::Bone*>(bone->childbase.first); while (chi) { // recurse buildBoneTree(skel, bind, chi, parent); chi = chi->next; } }
void akGeometryDeformer::LBSkinningUniformScale( const btAlignedObjectArray<akMatrix4>* mpalette, const UTsize vtxCount, const float* weights, const UTsize weightsStride, const UTuint8* indices, const UTsize indicesStride, const akVector3* vtxSrc, const UTsize vtxSrcStride, akVector3* vtxDst, const UTsize vtxDstStride, const akVector3* normSrc, const UTsize normSrcStride, akVector3* normDst, const UTsize normDstStride) { const btAlignedObjectArray<akMatrix4>& matrices = *mpalette; for(unsigned int i=0; i<vtxCount; i++) { akMatrix4 mat(matrices[indices[0]] * weights[0]); if (weights[1]) mat += matrices[indices[1]] * weights[1]; if (weights[2]) mat += matrices[indices[2]] * weights[2]; if (weights[3]) mat += matrices[indices[3]] * weights[3]; // position *vtxDst = (mat * akVector4(*vtxSrc, 1.f)).getXYZ(); // normal *normDst = (mat * akVector4(*normSrc, 0.0f)).getXYZ(); *normDst = normalize(*normDst); akAdvancePointer(normSrc, normSrcStride); akAdvancePointer(normDst, normDstStride); akAdvancePointer(weights, weightsStride); akAdvancePointer(indices, indicesStride); akAdvancePointer(vtxSrc, vtxSrcStride); akAdvancePointer(vtxDst, vtxDstStride); } }
void akGeometryDeformer::DLBSkinning( const btAlignedObjectArray<akMatrix4>* mpalette, const btAlignedObjectArray<akDualQuat>* dqpalette, const UTsize vtxCount, const float* weights, const UTsize weightsStride, const UTuint8* indices, const UTsize indicesStride, const akVector3* vtxSrc, const UTsize vtxSrcStride, akVector3* vtxDst, const UTsize vtxDstStride, const akVector3* normSrc, const UTsize normSrcStride, akVector3* normDst, const UTsize normDstStride) { const btAlignedObjectArray<akMatrix4>& matrices = *mpalette; const btAlignedObjectArray<akDualQuat>& dquats = *dqpalette; for(unsigned int i=0; i<vtxCount; i++) { // position 1st pass for non rigid part of the transformation using matrices akMatrix4 mat(matrices[indices[0]] * weights[0]); if (weights[1]) mat += matrices[indices[1]] * weights[1]; if (weights[2]) mat += matrices[indices[2]] * weights[2]; if (weights[3]) mat += matrices[indices[3]] * weights[3]; akVector3 tmpPos = (mat * akVector4(*vtxSrc, 1.f)).getXYZ(); // position 2nd pass for rigid transformation (rotaion & location) using dual quats akDualQuat dq = dquats[indices[0]] * weights[0]; if (weights[1]) dq += dquats[indices[1]] * weights[1]; if (weights[2]) dq += dquats[indices[2]] * weights[2]; if (weights[3]) dq += dquats[indices[3]] * weights[3]; dq /= length(dq.n); akVector3 ndxyz(dq.n.getXYZ()); akVector3 dxyz(dq.d.getXYZ()); *vtxDst = tmpPos + 2.0 * cross( ndxyz, cross(ndxyz, tmpPos) + dq.n.getW() * tmpPos ) + 2.0 * ( dq.n.getW() * dxyz - dq.d.getW() * ndxyz + cross(ndxyz, dxyz) ); // normal 1st pass inverseTranspose(mat); akVector3 tmpNorm = (mat * akVector4(*normSrc, 0.0f)).getXYZ(); // normal 2nd pass *normDst = tmpNorm + 2.0 * cross( ndxyz, cross(ndxyz, tmpNorm) + dq.n.getW() * tmpNorm ); *normDst = normalize(*normDst); akAdvancePointer(normSrc, normSrcStride); akAdvancePointer(normDst, normDstStride); akAdvancePointer(weights, weightsStride); akAdvancePointer(indices, indicesStride); akAdvancePointer(vtxSrc, vtxSrcStride); akAdvancePointer(vtxDst, vtxDstStride); } }
void akBLoader::convertObjectMesh(Blender::Object *bobj) { if(!bobj->data) return; akEntity* entity = new akEntity(); m_demo->addEntity(AKB_IDNAME(bobj), entity); float* bmat = (float*)bobj->obmat; akMatrix4 mat(akVector4(bmat[4*0+0], bmat[4*0+1], bmat[4*0+2], bmat[4*0+3]), akVector4(bmat[4*1+0], bmat[4*1+1], bmat[4*1+2], bmat[4*1+3]), akVector4(bmat[4*2+0], bmat[4*2+1], bmat[4*2+2], bmat[4*2+3]), akVector4(bmat[4*3+0], bmat[4*3+1], bmat[4*3+2], bmat[4*3+3])); akTransformState trans; akMathUtils::extractTransform(mat, trans.loc, trans.rot,trans.scale ); entity->setTransformState(trans); Blender::Mesh* bmesh = (Blender::Mesh*)bobj->data; if (!m_demo->getMesh(AKB_IDNAME(bmesh))) { akMesh* mesh = new akMesh(); akMeshLoader meconv(m_demo, mesh, bobj, bmesh); meconv.convert(false, true); m_demo->addMesh(AKB_IDNAME(bmesh), mesh); } akMesh* mesh = m_demo->getMesh(AKB_IDNAME(bmesh)); entity->setMesh(mesh); if(mesh && bobj->parent != 0 && bobj->parent->type == OB_ARMATURE) { Blender::bArmature* bskel = (Blender::bArmature*)bobj->parent->data; if(!m_demo->getSkeleton(AKB_IDNAME(bskel))) convertSkeleton(bskel); akSkeleton* skel = m_demo->getSkeleton(AKB_IDNAME(bskel)); entity->setSkeleton(skel); if(bskel->deformflag & BLENDER_ARM_DEF_QUATERNION) entity->setUseDualQuatSkinning(true); mesh->generateBoneWeightsFromVertexGroups(skel, true); } }
void akBLoader::convertCameraObject(Blender::Object *bobj) { if(!bobj || !bobj->data) return; Blender::Camera* bcam = (Blender::Camera*)bobj->data; akCamera* camera = m_demo->getCamera(); float* bmat = (float*)bobj->obmat; akMatrix4 mat(akVector4(bmat[4*0+0], bmat[4*0+1], bmat[4*0+2], bmat[4*0+3]), akVector4(bmat[4*1+0], bmat[4*1+1], bmat[4*1+2], bmat[4*1+3]), akVector4(bmat[4*2+0], bmat[4*2+1], bmat[4*2+2], bmat[4*2+3]), akVector4(bmat[4*3+0], bmat[4*3+1], bmat[4*3+2], bmat[4*3+3])); akTransformState trans; akMathUtils::extractTransform(mat, trans.loc, trans.rot,trans.scale ); camera->m_transform = trans; camera->m_clipStart = bcam->clipsta; camera->m_clipEnd = bcam->clipend; camera->m_fov = 360.0f * atanf(16.0f / bcam->lens) / akPi; //TODO fovx to fovy }
void akGeometryDeformer::DLBAntipodalitySkinningUniformScale( const btAlignedObjectArray<akMatrix4>* mpalette, const btAlignedObjectArray<akDualQuat>* dqpalette, const UTsize vtxCount, const float* weights, const UTsize weightsStride, const UTuint8* indices, const UTsize indicesStride, const akVector3* vtxSrc, const UTsize vtxSrcStride, akVector3* vtxDst, const UTsize vtxDstStride, const akVector3* normSrc, const UTsize normSrcStride, akVector3* normDst, const UTsize normDstStride) { const btAlignedObjectArray<akMatrix4>& matrices = *mpalette; const btAlignedObjectArray<akDualQuat>& dquats = *dqpalette; for(unsigned int i=0; i<vtxCount; i++) { // positions 1st pass for non rigid part of the transformation using matrices akMatrix4 mat(matrices[indices[0]] * weights[0]); if (weights[1]) mat += matrices[indices[1]] * weights[1]; if (weights[2]) mat += matrices[indices[2]] * weights[2]; if (weights[3]) mat += matrices[indices[3]] * weights[3]; akVector3 tmpPos = (mat * akVector4(*vtxSrc, 1.f)).getXYZ(); akDualQuat dq0 = dquats[indices[0]]; akDualQuat dq1 = dquats[indices[1]]; akDualQuat dq2 = dquats[indices[2]]; akDualQuat dq3 = dquats[indices[3]]; if( dot(dq0.n, dq1.n) < 0.0) dq1 *= -1.0; if( dot(dq0.n, dq2.n) < 0.0) dq2 *= -1.0; if( dot(dq0.n, dq3.n) < 0.0) dq3 *= -1.0; akDualQuat dq = dq0 * weights[0]; if (weights[1]) dq += dq1 * weights[1]; if (weights[2]) dq += dq2 * weights[2]; if (weights[3]) dq += dq3 * weights[3]; dq /= length(dq.n); akVector3 ndxyz(dq.n.getXYZ()); akVector3 dxyz(dq.d.getXYZ()); //position 2nd pass *vtxDst = tmpPos + 2.0 * cross( ndxyz, cross(ndxyz, tmpPos) + dq.n.getW() * tmpPos ) + 2.0 * ( dq.n.getW() * dxyz - dq.d.getW() * ndxyz + cross(ndxyz, dxyz) ); // normal 1rst pass akVector3 tmpNor = (mat * akVector4(*normSrc, 1.f)).getXYZ(); // normal 2nd pass *normDst = tmpNor + 2.0 * cross( ndxyz, cross(ndxyz, tmpNor) + dq.n.getW() * tmpNor ); *normDst = normalize(*normDst); akAdvancePointer(normSrc, normSrcStride); akAdvancePointer(normDst, normDstStride); akAdvancePointer(weights, weightsStride); akAdvancePointer(indices, indicesStride); akAdvancePointer(vtxSrc, vtxSrcStride); akAdvancePointer(vtxDst, vtxDstStride); } }