void CAssParser::LoadPieceTransformations( SAssPiece* piece, const S3DModel* model, const aiNode* pieceNode, const LuaTable& pieceTable ) { aiVector3D aiScaleVec, aiTransVec; aiQuaternion aiRotateQuat; // process transforms pieceNode->mTransformation.Decompose(aiScaleVec, aiRotateQuat, aiTransVec); // metadata-scaling piece->scales = pieceTable.GetFloat3("scale", aiVectorToFloat3(aiScaleVec)); piece->scales.x = pieceTable.GetFloat("scalex", piece->scales.x); piece->scales.y = pieceTable.GetFloat("scaley", piece->scales.y); piece->scales.z = pieceTable.GetFloat("scalez", piece->scales.z); if (piece->scales.x != piece->scales.y || piece->scales.y != piece->scales.z) { // LOG_SL(LOG_SECTION_MODEL, L_WARNING, "Spring doesn't support non-uniform scaling"); piece->scales.y = piece->scales.x; piece->scales.z = piece->scales.x; } // metadata-translation piece->offset = pieceTable.GetFloat3("offset", aiVectorToFloat3(aiTransVec)); piece->offset.x = pieceTable.GetFloat("offsetx", piece->offset.x); piece->offset.y = pieceTable.GetFloat("offsety", piece->offset.y); piece->offset.z = pieceTable.GetFloat("offsetz", piece->offset.z); // metadata-rotation // NOTE: // these rotations are "pre-scripting" but "post-modelling" // together with the (baked) aiRotateQuad they determine the // model's pose *before* any animations execute // // float3 rotAngles = pieceTable.GetFloat3("rotate", aiQuaternionToRadianAngles(aiRotateQuat) * RADTODEG); float3 pieceRotAngles = pieceTable.GetFloat3("rotate", ZeroVector); pieceRotAngles.x = pieceTable.GetFloat("rotatex", pieceRotAngles.x); pieceRotAngles.y = pieceTable.GetFloat("rotatey", pieceRotAngles.y); pieceRotAngles.z = pieceTable.GetFloat("rotatez", pieceRotAngles.z); pieceRotAngles *= DEGTORAD; LOG_SL(LOG_SECTION_PIECE, L_INFO, "(%d:%s) Assimp offset (%f,%f,%f), rotate (%f,%f,%f,%f), scale (%f,%f,%f)", model->numPieces, piece->name.c_str(), aiTransVec.x, aiTransVec.y, aiTransVec.z, aiRotateQuat.w, aiRotateQuat.x, aiRotateQuat.y, aiRotateQuat.z, aiScaleVec.x, aiScaleVec.y, aiScaleVec.z ); LOG_SL(LOG_SECTION_PIECE, L_INFO, "(%d:%s) Relative offset (%f,%f,%f), rotate (%f,%f,%f), scale (%f,%f,%f)", model->numPieces, piece->name.c_str(), piece->offset.x, piece->offset.y, piece->offset.z, pieceRotAngles.x, pieceRotAngles.y, pieceRotAngles.z, piece->scales.x, piece->scales.y, piece->scales.z ); // NOTE: // at least collada (.dae) files generated by Blender represent // a coordinate-system that differs from the "standard" formats // (3DO, S3O, ...) for which existing tools at least have prior // knowledge of Spring's expectations --> let the user override // the ROOT rotational transform and the rotation-axis mapping // used by animation scripts (but re-modelling/re-exporting is // always preferred!) even though AssImp should convert models // to its own system which matches that of Spring // // .dae : x=Rgt, y=-Fwd, z= Up, as=(-1, -1, 1), am=AXIS_XZY (if Z_UP) // .dae : x=Rgt, y=-Fwd, z= Up, as=(-1, -1, 1), am=AXIS_XZY (if Y_UP) [!?] // .blend: ???? piece->bakedRotMatrix = aiMatrixToMatrix(aiMatrix4x4t<float>(aiRotateQuat.GetMatrix())); if (piece == model->GetRootPiece()) { const float3 xaxis = pieceTable.GetFloat3("xaxis", piece->bakedRotMatrix.GetX()); const float3 yaxis = pieceTable.GetFloat3("yaxis", piece->bakedRotMatrix.GetY()); const float3 zaxis = pieceTable.GetFloat3("zaxis", piece->bakedRotMatrix.GetZ()); if (math::fabs(xaxis.SqLength() - yaxis.SqLength()) < 0.01f && math::fabs(yaxis.SqLength() - zaxis.SqLength()) < 0.01f) { piece->bakedRotMatrix = CMatrix44f(ZeroVector, xaxis, yaxis, zaxis); } } piece->rotAxisSigns = pieceTable.GetFloat3("rotAxisSigns", float3(-OnesVector)); piece->axisMapType = AxisMappingType(pieceTable.GetInt("rotAxisMap", AXIS_MAPPING_XYZ)); // construct 'baked' part of the piece-space matrix // AssImp order is translate * rotate * scale * v; // we leave the translation and scale parts out and // put those in <offset> and <scales> --> transform // is just R instead of T * R * S // // note: for all non-AssImp models this is identity! // piece->ComposeRotation(piece->bakedRotMatrix, pieceRotAngles); piece->SetHasIdentityRotation(piece->bakedRotMatrix.IsIdentity() == 0); assert(piece->bakedRotMatrix.IsOrthoNormal() == 0); }
void CAssParser::LoadPieceTransformations(const S3DModel* model, SAssPiece* piece, const LuaTable& pieceMetaTable) { // Process transforms float3 rotate, offset; float3 scale(1.0,1.0,1.0); aiVector3D _scale, _offset; aiQuaternion _rotate; piece->node->mTransformation.Decompose(_scale,_rotate,_offset); const aiMatrix4x4t<float> aiRotMatrix = aiMatrix4x4t<float>(_rotate.GetMatrix()); LOG_S(LOG_SECTION_PIECE, "(%d:%s) Assimp offset (%f,%f,%f), rotate (%f,%f,%f,%f), scale (%f,%f,%f)", model->numPieces, piece->name.c_str(), _offset.x, _offset.y, _offset.z, _rotate.w, _rotate.x, _rotate.y, _rotate.z, _scale.x, _scale.y, _scale.z ); // Scale scale = pieceMetaTable.GetFloat3("scale", float3(_scale.x, _scale.z, _scale.y)); scale.x = pieceMetaTable.GetFloat("scalex", scale.x); scale.y = pieceMetaTable.GetFloat("scaley", scale.y); scale.z = pieceMetaTable.GetFloat("scalez", scale.z); if (scale.x != scale.y || scale.y != scale.z) { //LOG_SL(LOG_SECTION_MODEL, L_WARNING, "Spring doesn't support non-uniform scaling"); scale.y = scale.x; scale.z = scale.x; } // Rotate // Note these rotations are put into the `Spring rotations` and are not baked into the Assimp matrix! rotate = pieceMetaTable.GetFloat3("rotate", float3(0,0,0)); rotate.x = pieceMetaTable.GetFloat("rotatex", rotate.x); rotate.y = pieceMetaTable.GetFloat("rotatey", rotate.y); rotate.z = pieceMetaTable.GetFloat("rotatez", rotate.z); rotate *= DEGTORAD; // Translate offset = pieceMetaTable.GetFloat3("offset", float3(_offset.x, _offset.y, _offset.z)); offset.x = pieceMetaTable.GetFloat("offsetx", offset.x); offset.y = pieceMetaTable.GetFloat("offsety", offset.y); offset.z = pieceMetaTable.GetFloat("offsetz", offset.z); LOG_S(LOG_SECTION_PIECE, "(%d:%s) Relative offset (%f,%f,%f), rotate (%f,%f,%f), scale (%f,%f,%f)", model->numPieces, piece->name.c_str(), offset.x, offset.y, offset.z, rotate.x, rotate.y, rotate.z, scale.x, scale.y, scale.z ); // construct 'baked' part of the modelpiece matrix // Assimp order is: translate * rotate * scale * v piece->scaleRotMatrix.LoadIdentity(); piece->scaleRotMatrix.Scale(scale); piece->scaleRotMatrix *= aiMatrixToMatrix(aiRotMatrix); // piece->scaleRotMatrix.Translate(offset); piece->offset = offset; piece->rot = rotate; piece->mIsIdentity = (scale.x == 1.0f) && aiRotMatrix.IsIdentity(); }