FUBoundingSphere FUBoundingSphere::Transform(const FMMatrix44& transform) const { if (!IsValid()) return (*this); FMVector3 transformedCenter = transform.TransformCoordinate(center); FUBoundingSphere transformedSphere(transformedCenter, 0.0f); // Calculate the transformed bounding sphere radius using three sample points. FMVector3 testPoints[3] = { FMVector3(radius, 0.0f, 0.0f), FMVector3(0.0f, radius, 0.0f), FMVector3(0.0f, 0.0f, radius) }; for (size_t i = 0; i < 6; ++i) { testPoints[i] = transform.TransformVector(testPoints[i]); float lengthSquared = testPoints[i].LengthSquared(); if (lengthSquared > transformedSphere.radius * transformedSphere.radius) { transformedSphere.radius = sqrtf(lengthSquared); } } return transformedSphere; }
/** * Applies world-space transform to vertex data and transforms Collada's right-handed * Y-up / Z-up coordinates to the game's left-handed Y-up coordinate system */ static void TransformStaticModel(float* position, float* normal, size_t vertexCount, const FMMatrix44& transform, bool yUp) { for (size_t i = 0; i < vertexCount; ++i) { FMVector3 pos (&position[i*3], 0); FMVector3 norm (&normal[i*3], 0); // Apply the scene-node transforms pos = transform.TransformCoordinate(pos); norm = FMVector3_Normalize(transform.TransformVector(norm)); // Convert from right-handed Y_UP or Z_UP to the game's coordinate system (left-handed Y-up) if (yUp) { pos.z = -pos.z; norm.z = -norm.z; } else { std::swap(pos.y, pos.z); std::swap(norm.y, norm.z); } // Copy back to array position[i*3] = pos.x; position[i*3+1] = pos.y; position[i*3+2] = pos.z; normal[i*3] = norm.x; normal[i*3+1] = norm.y; normal[i*3+2] = norm.z; } }
/** * Applies world-space transform to vertex data and transforms Collada's right-handed * Y-up / Z-up coordinates to the game's left-handed Y-up coordinate system */ static void TransformSkinnedModel(float* position, float* normal, size_t vertexCount, std::vector<BoneTransform>& bones, std::vector<PropPoint>& propPoints, const FMMatrix44& transform, const FMMatrix44& bindTransform, bool yUp, bool isXSI) { FMMatrix44 scaledTransform; // for vertexes FMMatrix44 scaleMatrix; // for bones // HACK: see comment in PSAConvert::TransformVertices if (isXSI) { scaleMatrix = DecomposeToScaleMatrix(transform); scaledTransform = DecomposeToScaleMatrix(bindTransform) * transform; } else { scaleMatrix = FMMatrix44_Identity; scaledTransform = bindTransform; } // Update the vertex positions and normals for (size_t i = 0; i < vertexCount; ++i) { FMVector3 pos (&position[i*3], 0); FMVector3 norm (&normal[i*3], 0); // Apply the scene-node transforms pos = scaledTransform.TransformCoordinate(pos); norm = FMVector3_Normalize(scaledTransform.TransformVector(norm)); // Convert from right-handed Y_UP or Z_UP to the game's coordinate system (left-handed Y-up) if (yUp) { pos.z = -pos.z; norm.z = -norm.z; } else { std::swap(pos.y, pos.z); std::swap(norm.y, norm.z); } // and copy back into the original array position[i*3] = pos.x; position[i*3+1] = pos.y; position[i*3+2] = pos.z; normal[i*3] = norm.x; normal[i*3+1] = norm.y; normal[i*3+2] = norm.z; } TransformBones(bones, scaleMatrix, yUp); // And do the same for prop points for (size_t i = 0; i < propPoints.size(); ++i) { if (yUp) { propPoints[i].translation[0] = -propPoints[i].translation[0]; propPoints[i].orientation[0] = -propPoints[i].orientation[0]; propPoints[i].orientation[3] = -propPoints[i].orientation[3]; } else { // Flip translation across the x-axis by swapping y and z std::swap(propPoints[i].translation[1], propPoints[i].translation[2]); // To convert the quaternions: imagine you're using the axis/angle // representation, then swap the y,z basis vectors and change the // direction of rotation by negating the angle ( => negating sin(angle) // => negating x,y,z => changing (x,y,z,w) to (-x,-z,-y,w) // but then (-x,-z,-y,w) == (x,z,y,-w) so do that instead) std::swap(propPoints[i].orientation[1], propPoints[i].orientation[2]); propPoints[i].orientation[3] = -propPoints[i].orientation[3]; } } }