Beispiel #1
0
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);
}
Beispiel #2
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();
}