/** * SetToTransformFunction is essentially a giant switch statement that fans * out to many smaller helper functions. */ void nsStyleTransformMatrix::SetToTransformFunction(const nsCSSValue::Array * aData, nsStyleContext* aContext, nsPresContext* aPresContext, PRBool& aCanStoreInRuleTree) { NS_PRECONDITION(aData, "Why did you want to get data from a null array?"); NS_PRECONDITION(aContext, "Need a context for unit conversion!"); NS_PRECONDITION(aPresContext, "Need a context for unit conversion!"); /* Reset the matrix to the identity so that each subfunction can just * worry about its own components. */ SetToIdentity(); /* Get the keyword for the transform. */ nsAutoString keyword; aData->Item(0).GetStringValue(keyword); switch (nsCSSKeywords::LookupKeyword(keyword)) { case eCSSKeyword_translatex: ProcessTranslateX(mDelta, mX, aData, aContext, aPresContext, aCanStoreInRuleTree); break; case eCSSKeyword_translatey: ProcessTranslateY(mDelta, mY, aData, aContext, aPresContext, aCanStoreInRuleTree); break; case eCSSKeyword_translate: ProcessTranslate(mDelta, mX, mY, aData, aContext, aPresContext, aCanStoreInRuleTree); break; case eCSSKeyword_scalex: ProcessScaleX(mMain, aData); break; case eCSSKeyword_scaley: ProcessScaleY(mMain, aData); break; case eCSSKeyword_scale: ProcessScale(mMain, aData); break; case eCSSKeyword_skewx: ProcessSkewX(mMain, aData); break; case eCSSKeyword_skewy: ProcessSkewY(mMain, aData); break; case eCSSKeyword_skew: ProcessSkew(mMain, aData); break; case eCSSKeyword_rotate: ProcessRotate(mMain, aData); break; case eCSSKeyword_matrix: ProcessMatrix(mMain, mDelta, mX, mY, aData, aContext, aPresContext, aCanStoreInRuleTree); break; default: NS_NOTREACHED("Unknown transform function!"); } }
/// <summary> /// Resets this matrix to a scaling matrix. /// </summary> /// <param name="scaleX">Factor to scale by in the X direction.</param> /// <param name="scaleY">Factor to scale by in the Y direction.</param> /// <param name="scaleZ">Factor to scale by in the Z direction.</param> void Matrix3D::SetToScaling(double scaleX, double scaleY, double scaleZ) { SetToIdentity(); m00 = scaleX; m11 = scaleY; m22 = scaleZ; }
/// <summary> /// Resets this matrix to a translation matrix. /// </summary> /// <param name="transX">Distance to translate in the X direction.</param> /// <param name="transY">Distance to translate in the Y direction.</param> /// <param name="transZ">Distance to translate in the Z direction.</param> void Matrix3D::SetToTranslation(double transX, double transY, double transZ) { SetToIdentity(); m03 = transX; m13 = transY; m23 = transZ; }
void LoadAnimationDataFromCollada( const char* fileName, ArmatureKeyFrame* keyframe, Armature* armature ) { tinyxml2::XMLDocument colladaDoc; colladaDoc.LoadFile( fileName ); tinyxml2::XMLNode* animationNode = colladaDoc.FirstChildElement( "COLLADA" )->FirstChildElement( "library_animations" )->FirstChild(); while( animationNode != NULL ) { //Desired data: what bone, and what local transform to it occurs Mat4 boneLocalTransform; Bone* targetBone = NULL; //Parse the target attribute from the XMLElement for channel, and get the bone it corresponds to const char* transformName = animationNode->FirstChildElement( "channel" )->Attribute( "target" ); size_t nameLen = strlen( transformName ); char* transformNameCopy = (char*)alloca( nameLen ); strcpy( transformNameCopy, transformName ); char* nameEnd = transformNameCopy; while( *nameEnd != '/' && *nameEnd != 0 ) { nameEnd++; } memset( transformNameCopy, 0, nameLen ); nameLen = nameEnd - transformNameCopy; memcpy( transformNameCopy, transformName, nameLen ); for( uint8 boneIndex = 0; boneIndex < armature->boneCount; boneIndex++ ) { if( strcmp( armature->bones[ boneIndex ].name, transformNameCopy ) == 0 ) { targetBone = &armature->bones[ boneIndex ]; break; } } //Parse matrix data, and extract first keyframe data tinyxml2::XMLNode* transformMatrixElement = animationNode->FirstChild()->NextSibling(); const char* matrixTransformData = transformMatrixElement->FirstChild()->FirstChild()->Value(); size_t transformDataLen = strlen( matrixTransformData ) + 1; char* transformDataCopy = (char*)alloca( transformDataLen * sizeof( char ) ); memset( transformDataCopy, 0, transformDataLen ); memcpy( transformDataCopy, matrixTransformData, transformDataLen ); int count = 0; transformMatrixElement->FirstChildElement()->QueryAttribute( "count", &count ); float* rawTransformData = (float*)alloca( count * sizeof(float) ); memset( rawTransformData, 0, count * sizeof(float) ); TextToNumberConversion( transformDataCopy, rawTransformData ); memcpy( &boneLocalTransform.m[0][0], &rawTransformData[0], 16 * sizeof(float) ); //Save data in BoneKeyFrame struct boneLocalTransform = TransposeMatrix( boneLocalTransform ); if( targetBone == armature->rootBone ) { Mat4 correction; correction.m[0][0] = 1.0f; correction.m[0][1] = 0.0f; correction.m[0][2] = 0.0f; correction.m[0][3] = 0.0f; correction.m[1][0] = 0.0f; correction.m[1][1] = 0.0f; correction.m[1][2] = -1.0f; correction.m[1][3] = 0.0f; correction.m[2][0] = 0.0f; correction.m[2][1] = 1.0f; correction.m[2][2] = 0.0f; correction.m[2][3] = 0.0f; correction.m[3][0] = 0.0f; correction.m[3][1] = 0.0f; correction.m[3][2] = 0.0f; correction.m[3][3] = 1.0f; boneLocalTransform = MultMatrix( boneLocalTransform, correction ); } BoneKeyFrame* key = &keyframe->targetBoneTransforms[ targetBone->boneIndex ]; key->combinedMatrix = boneLocalTransform; DecomposeMat4( boneLocalTransform, &key->scale, &key->rotation, &key->translation ); Mat4 m = Mat4FromComponents( key->scale, key->rotation, key->translation ); animationNode = animationNode->NextSibling(); } //Pre multiply bones with parents to save doing it during runtime struct { ArmatureKeyFrame* keyframe; void PremultiplyKeyFrame( Bone* target, Mat4 parentTransform ) { BoneKeyFrame* boneKey = &keyframe->targetBoneTransforms[ target->boneIndex ]; Mat4 netMatrix = MultMatrix( boneKey->combinedMatrix, parentTransform ); for( uint8 boneIndex = 0; boneIndex < target->childCount; boneIndex++ ) { PremultiplyKeyFrame( target->children[ boneIndex ], netMatrix ); } boneKey->combinedMatrix = netMatrix; DecomposeMat4( boneKey->combinedMatrix, &boneKey->scale, &boneKey->rotation, &boneKey->translation ); } }LocalRecursiveScope; LocalRecursiveScope.keyframe = keyframe; Mat4 i; SetToIdentity( &i ); LocalRecursiveScope.PremultiplyKeyFrame( armature->rootBone, i ); }
void LoadMeshDataFromDisk( const char* fileName, SlabSubsection_Stack* allocater, MeshGeometryData* storage, Armature* armature ) { tinyxml2::XMLDocument colladaDoc; colladaDoc.LoadFile( fileName ); //if( colladaDoc == NULL ) { //printf( "Could not load mesh: %s\n", fileName ); //return; //} tinyxml2::XMLElement* meshNode = colladaDoc.FirstChildElement( "COLLADA" )->FirstChildElement( "library_geometries" ) ->FirstChildElement( "geometry" )->FirstChildElement( "mesh" ); char* colladaTextBuffer = NULL; size_t textBufferLen = 0; uint16 vCount = 0; uint16 nCount = 0; uint16 uvCount = 0; uint16 indexCount = 0; float* rawColladaVertexData; float* rawColladaNormalData; float* rawColladaUVData; float* rawIndexData; ///Basic Mesh Geometry Data { tinyxml2::XMLNode* colladaVertexArray = meshNode->FirstChildElement( "source" ); tinyxml2::XMLElement* vertexFloatArray = colladaVertexArray->FirstChildElement( "float_array" ); tinyxml2::XMLNode* colladaNormalArray = colladaVertexArray->NextSibling(); tinyxml2::XMLElement* normalFloatArray = colladaNormalArray->FirstChildElement( "float_array" ); tinyxml2::XMLNode* colladaUVMapArray = colladaNormalArray->NextSibling(); tinyxml2::XMLElement* uvMapFloatArray = colladaUVMapArray->FirstChildElement( "float_array" ); tinyxml2::XMLElement* meshSrc = meshNode->FirstChildElement( "polylist" ); tinyxml2::XMLElement* colladaIndexArray = meshSrc->FirstChildElement( "p" ); int count; const char* colladaVertArrayVal = vertexFloatArray->FirstChild()->Value(); vertexFloatArray->QueryAttribute( "count", &count ); vCount = count; const char* colladaNormArrayVal = normalFloatArray->FirstChild()->Value(); normalFloatArray->QueryAttribute( "count", &count ); nCount = count; const char* colladaUVMapArrayVal = uvMapFloatArray->FirstChild()->Value(); uvMapFloatArray->QueryAttribute( "count", &count ); uvCount = count; const char* colladaIndexArrayVal = colladaIndexArray->FirstChild()->Value(); meshSrc->QueryAttribute( "count", &count ); //Assume this is already triangulated indexCount = count * 3 * 3; ///TODO: replace this with fmaxf? std::function< size_t (size_t, size_t) > sizeComparison = []( size_t size1, size_t size2 ) -> size_t { if( size1 >= size2 ) return size1; return size2; }; textBufferLen = strlen( colladaVertArrayVal ); textBufferLen = sizeComparison( strlen( colladaNormArrayVal ), textBufferLen ); textBufferLen = sizeComparison( strlen( colladaUVMapArrayVal ), textBufferLen ); textBufferLen = sizeComparison( strlen( colladaIndexArrayVal ), textBufferLen ); colladaTextBuffer = (char*)alloca( textBufferLen ); memset( colladaTextBuffer, 0, textBufferLen ); rawColladaVertexData = (float*)alloca( sizeof(float) * vCount ); rawColladaNormalData = (float*)alloca( sizeof(float) * nCount ); rawColladaUVData = (float*)alloca( sizeof(float) * uvCount ); rawIndexData = (float*)alloca( sizeof(float) * indexCount ); memset( rawColladaVertexData, 0, sizeof(float) * vCount ); memset( rawColladaNormalData, 0, sizeof(float) * nCount ); memset( rawColladaUVData, 0, sizeof(float) * uvCount ); memset( rawIndexData, 0, sizeof(float) * indexCount ); //Reading Vertex position data strcpy( colladaTextBuffer, colladaVertArrayVal ); TextToNumberConversion( colladaTextBuffer, rawColladaVertexData ); //Reading Normals data memset( colladaTextBuffer, 0, textBufferLen ); strcpy( colladaTextBuffer, colladaNormArrayVal ); TextToNumberConversion( colladaTextBuffer, rawColladaNormalData ); //Reading UV map data memset( colladaTextBuffer, 0, textBufferLen ); strcpy( colladaTextBuffer, colladaUVMapArrayVal ); TextToNumberConversion( colladaTextBuffer, rawColladaUVData ); //Reading index data memset( colladaTextBuffer, 0, textBufferLen ); strcpy( colladaTextBuffer, colladaIndexArrayVal ); TextToNumberConversion( colladaTextBuffer, rawIndexData ); } float* rawBoneWeightData = NULL; float* rawBoneIndexData = NULL; //Skinning Data { tinyxml2::XMLElement* libControllers = colladaDoc.FirstChildElement( "COLLADA" )->FirstChildElement( "library_controllers" ); if( libControllers == NULL ) goto skinningExit; tinyxml2::XMLElement* controllerElement = libControllers->FirstChildElement( "controller" ); if( controllerElement == NULL ) goto skinningExit; tinyxml2::XMLNode* vertexWeightDataArray = controllerElement->FirstChild()->FirstChild()->NextSibling()->NextSibling()->NextSibling(); tinyxml2::XMLNode* vertexBoneIndexDataArray = vertexWeightDataArray->NextSibling()->NextSibling(); tinyxml2::XMLNode* vCountArray = vertexBoneIndexDataArray->FirstChildElement( "vcount" ); tinyxml2::XMLNode* vArray = vertexBoneIndexDataArray->FirstChildElement( "v" ); const char* boneWeightsData = vertexWeightDataArray->FirstChild()->FirstChild()->Value(); const char* vCountArrayData = vCountArray->FirstChild()->Value(); const char* vArrayData = vArray->FirstChild()->Value(); float* colladaBoneWeightData = NULL; float* colladaBoneIndexData = NULL; float* colladaBoneInfluenceCounts = NULL; ///This is overkill, Collada stores ways less data usually, plus this still doesn't account for very complex models ///(e.g, lots of verts with more than MAXBONESPERVERT influencing position ) colladaBoneWeightData = (float*)alloca( sizeof(float) * MAXBONESPERVERT * vCount ); colladaBoneIndexData = (float*)alloca( sizeof(float) * MAXBONESPERVERT * vCount ); colladaBoneInfluenceCounts = (float*)alloca( sizeof(float) * MAXBONESPERVERT * vCount ); //Read bone weights data memset( colladaTextBuffer, 0, textBufferLen ); strcpy( colladaTextBuffer, boneWeightsData ); TextToNumberConversion( colladaTextBuffer, colladaBoneWeightData ); //Read bone index data memset( colladaTextBuffer, 0, textBufferLen ); strcpy( colladaTextBuffer, vArrayData ); TextToNumberConversion( colladaTextBuffer, colladaBoneIndexData ); //Read bone influence counts memset( colladaTextBuffer, 0, textBufferLen ); strcpy( colladaTextBuffer, vCountArrayData ); TextToNumberConversion( colladaTextBuffer, colladaBoneInfluenceCounts ); rawBoneWeightData = (float*)alloca( sizeof(float) * MAXBONESPERVERT * vCount ); rawBoneIndexData = (float*)alloca( sizeof(float) * MAXBONESPERVERT * vCount ); memset( rawBoneWeightData, 0, sizeof(float) * MAXBONESPERVERT * vCount ); memset( rawBoneIndexData, 0, sizeof(float) * MAXBONESPERVERT * vCount ); int colladaIndexIndirection = 0; int verticiesInfluenced = 0; vCountArray->Parent()->ToElement()->QueryAttribute( "count", &verticiesInfluenced ); for( uint16 i = 0; i < verticiesInfluenced; i++ ) { uint8 influenceCount = colladaBoneInfluenceCounts[i]; for( uint16 j = 0; j < influenceCount; j++ ) { uint16 boneIndex = colladaBoneIndexData[ colladaIndexIndirection++ ]; uint16 weightIndex = colladaBoneIndexData[ colladaIndexIndirection++ ]; rawBoneWeightData[ i * MAXBONESPERVERT + j ] = colladaBoneWeightData[ weightIndex ]; rawBoneIndexData[ i * MAXBONESPERVERT + j ] = boneIndex; } } } skinningExit: //Armature if( armature != NULL ) { tinyxml2::XMLElement* visualScenesNode = colladaDoc.FirstChildElement( "COLLADA" )->FirstChildElement( "library_visual_scenes" ) ->FirstChildElement( "visual_scene" )->FirstChildElement( "node" ); tinyxml2::XMLElement* armatureNode = NULL; //Step through scene heirarchy until start of armature is found while( visualScenesNode != NULL ) { if( visualScenesNode->FirstChildElement( "node" ) != NULL && visualScenesNode->FirstChildElement( "node" )->Attribute( "type", "JOINT" ) != NULL ) { armatureNode = visualScenesNode; break; } else { visualScenesNode = visualScenesNode->NextSibling()->ToElement(); } } if( armatureNode == NULL ) return; //Parsing basic bone data from XML std::function< Bone* ( tinyxml2::XMLElement*, Armature*, Bone* ) > ParseColladaBoneData = [&]( tinyxml2::XMLElement* boneElement, Armature* armature, Bone* parentBone ) -> Bone* { Bone* bone = &armature->bones[ armature->boneCount ]; bone->parent = parentBone; bone->currentTransform = &armature->boneTransforms[ armature->boneCount ]; SetToIdentity( bone->currentTransform ); bone->boneIndex = armature->boneCount; armature->boneCount++; strcpy( &bone->name[0], boneElement->Attribute( "sid" ) ); float matrixData[16]; char matrixTextData [512]; tinyxml2::XMLNode* matrixElement = boneElement->FirstChildElement("matrix"); strcpy( &matrixTextData[0], matrixElement->FirstChild()->ToText()->Value() ); TextToNumberConversion( matrixTextData, matrixData ); //Note: this is only local transform data, but its being saved in bind matrix for now Mat4 m; memcpy( &m.m[0][0], &matrixData[0], sizeof(float) * 16 ); bone->bindPose = TransposeMatrix( m ); if( parentBone == NULL ) { armature->rootBone = bone; } else { bone->bindPose = MultMatrix( parentBone->bindPose, bone->bindPose ); } bone->childCount = 0; tinyxml2::XMLElement* childBoneElement = boneElement->FirstChildElement( "node" ); while( childBoneElement != NULL ) { Bone* childBone = ParseColladaBoneData( childBoneElement, armature, bone ); bone->children[ bone->childCount++ ] = childBone; tinyxml2::XMLNode* siblingNode = childBoneElement->NextSibling(); if( siblingNode != NULL ) { childBoneElement = siblingNode->ToElement(); } else { childBoneElement = NULL; } }; return bone; }; armature->boneCount = 0; tinyxml2::XMLElement* boneElement = armatureNode->FirstChildElement( "node" ); ParseColladaBoneData( boneElement, armature, NULL ); //Parse inverse bind pose data from skinning section of XML { tinyxml2::XMLElement* boneNamesSource = colladaDoc.FirstChildElement( "COLLADA" )->FirstChildElement( "library_controllers" ) ->FirstChildElement( "controller" )->FirstChildElement( "skin" )->FirstChildElement( "source" ); tinyxml2::XMLElement* boneBindPoseSource = boneNamesSource->NextSibling()->ToElement(); char* boneNamesLocalCopy = NULL; float* boneMatriciesData = (float*)alloca( sizeof(float) * 16 * armature->boneCount ); const char* boneNameArrayData = boneNamesSource->FirstChild()->FirstChild()->Value(); const char* boneMatrixTextData = boneBindPoseSource->FirstChild()->FirstChild()->Value(); size_t nameDataLen = strlen( boneNameArrayData ); size_t matrixDataLen = strlen( boneMatrixTextData ); boneNamesLocalCopy = (char*)alloca( nameDataLen + 1 ); memset( boneNamesLocalCopy, 0, nameDataLen + 1 ); assert( textBufferLen > matrixDataLen ); memcpy( boneNamesLocalCopy, boneNameArrayData, nameDataLen ); memcpy( colladaTextBuffer, boneMatrixTextData, matrixDataLen ); TextToNumberConversion( colladaTextBuffer, boneMatriciesData ); char* nextBoneName = &boneNamesLocalCopy[0]; for( uint8 matrixIndex = 0; matrixIndex < armature->boneCount; matrixIndex++ ) { Mat4 matrix; memcpy( &matrix.m[0], &boneMatriciesData[matrixIndex * 16], sizeof(float) * 16 ); char boneName [32]; char* boneNameEnd = nextBoneName; do { boneNameEnd++; } while( *boneNameEnd != ' ' && *boneNameEnd != 0 ); size_t charCount = boneNameEnd - nextBoneName; memset( boneName, 0, sizeof( char ) * 32 ); memcpy( boneName, nextBoneName, charCount ); nextBoneName = boneNameEnd + 1; Bone* targetBone = NULL; for( uint8 boneIndex = 0; boneIndex < armature->boneCount; boneIndex++ ) { Bone* bone = &armature->bones[ boneIndex ]; if( strcmp( bone->name, boneName ) == 0 ) { targetBone = bone; break; } } Mat4 correction; correction.m[0][0] = 1.0f; correction.m[0][1] = 0.0f; correction.m[0][2] = 0.0f; correction.m[0][3] = 0.0f; correction.m[1][0] = 0.0f; correction.m[1][1] = 0.0f; correction.m[1][2] = 1.0f; correction.m[1][3] = 0.0f; correction.m[2][0] = 0.0f; correction.m[2][1] = -1.0f; correction.m[2][2] = 0.0f; correction.m[2][3] = 0.0f; correction.m[3][0] = 0.0f; correction.m[3][1] = 0.0f; correction.m[3][2] = 0.0f; correction.m[3][3] = 1.0f; targetBone->invBindPose = TransposeMatrix( matrix ); targetBone->invBindPose = MultMatrix( correction, targetBone->invBindPose ); } } } //output to my version of storage storage->dataCount = 0; uint16 counter = 0; const uint32 vertCount = indexCount / 3; storage->vData = (Vec3*)AllocOnSubStack_Aligned( allocater, vertCount * sizeof( Vec3 ), 16 ); storage->uvData = (float*)AllocOnSubStack_Aligned( allocater, vertCount * 2 * sizeof( float ), 4 ); storage->normalData = (Vec3*)AllocOnSubStack_Aligned( allocater, vertCount * sizeof( Vec3 ), 4 ); storage->iData = (uint32*)AllocOnSubStack_Aligned( allocater, vertCount * sizeof( uint32 ), 4 ); if( rawBoneWeightData != NULL ) { storage->boneWeightData = (float*)AllocOnSubStack_Aligned( allocater, sizeof(float) * vertCount * MAXBONESPERVERT, 4 ); storage->boneIndexData = (uint32*)AllocOnSubStack_Aligned( allocater, sizeof(uint32) * vertCount * MAXBONESPERVERT, 4 ); } else { storage->boneWeightData = NULL; storage->boneIndexData = NULL; } while( counter < indexCount ) { Vec3 v, n; float uv_x, uv_y; uint16 vertIndex = rawIndexData[ counter++ ]; uint16 normalIndex = rawIndexData[ counter++ ]; uint16 uvIndex = rawIndexData[ counter++ ]; v.x = rawColladaVertexData[ vertIndex * 3 + 0 ]; v.z = -rawColladaVertexData[ vertIndex * 3 + 1 ]; v.y = rawColladaVertexData[ vertIndex * 3 + 2 ]; n.x = rawColladaNormalData[ normalIndex * 3 + 0 ]; n.z = -rawColladaNormalData[ normalIndex * 3 + 1 ]; n.y = rawColladaNormalData[ normalIndex * 3 + 2 ]; uv_x = rawColladaUVData[ uvIndex * 2 ]; uv_y = rawColladaUVData[ uvIndex * 2 + 1 ]; ///TODO: check for exact copies of data, use to index to first instance instead uint32 storageIndex = storage->dataCount; storage->vData[ storageIndex ] = v; storage->normalData[ storageIndex ] = n; storage->uvData[ storageIndex * 2 ] = uv_x; storage->uvData[ storageIndex * 2 + 1 ] = uv_y; if( rawBoneWeightData != NULL ) { uint16 boneDataIndex = storage->dataCount * MAXBONESPERVERT; uint16 boneVertexIndex = vertIndex * MAXBONESPERVERT; for( uint8 i = 0; i < MAXBONESPERVERT; i++ ) { storage->boneWeightData[ boneDataIndex + i ] = rawBoneWeightData[ boneVertexIndex + i ]; storage->boneIndexData[ boneDataIndex + i ] = rawBoneIndexData[ boneVertexIndex + i ]; } } storage->iData[ storageIndex ] = storageIndex; storage->dataCount++; }; }
/* Constructor sets the data to the identity matrix. */ nsStyleTransformMatrix::nsStyleTransformMatrix() { SetToIdentity(); }
/// <summary> /// Initializes a new instance of the Matrix3D class to /// the identity matrix. /// </summary> Matrix3D::Matrix3D() { SetToIdentity(); }
void Mtx44::SetToTranslation(float tx, float ty, float tz) { SetToIdentity(); a[12] = tx; a[13] = ty; a[14] = tz; }
void Mtx44::SetToScale(float sx, float sy, float sz) { SetToIdentity(); a[0] = sx; a[5] = sy; a[10] = sz; }