private void CalculateBounds(idJointMatrix[] entityJoints) { _bounds.Clear(); foreach(idMD5Mesh mesh in _meshes) { _bounds.AddBounds(mesh.CalculateBounds(entityJoints)); } }
/// <summary> /// Compare, with epsilon. /// </summary> /// <param name="m"></param> /// <param name="epsilon"></param> /// <returns></returns> public bool Equals(idJointMatrix m, float epsilon) { for (int i = 0; i < 12; i++) { if (idMath.Abs(_m[i] - m._m[i]) > epsilon) { return(false); } } return(true); }
/// <summary> /// Exact compare, no epsilon. /// </summary> /// <param name="obj"></param> /// <returns></returns> public bool Equals(idJointMatrix m) { for (int i = 0; i < 12; i++) { if (_m[i] != m._m[i]) { return(false); } } return(true); }
public static idJointMatrix Transform(idJointMatrix x, idJointMatrix y) { float[] m = (float[])x._m.Clone(); float[] dst = new float[3]; dst[0] = m[0 * 4 + 0] * y._m[0 * 4 + 0] + m[1 * 4 + 0] * y._m[0 * 4 + 1] + m[2 * 4 + 0] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 0] * y._m[1 * 4 + 0] + m[1 * 4 + 0] * y._m[1 * 4 + 1] + m[2 * 4 + 0] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 0] * y._m[2 * 4 + 0] + m[1 * 4 + 0] * y._m[2 * 4 + 1] + m[2 * 4 + 0] * y._m[2 * 4 + 2]; m[0 * 4 + 0] = dst[0]; m[1 * 4 + 0] = dst[1]; m[2 * 4 + 0] = dst[2]; dst[0] = m[0 * 4 + 1] * y._m[0 * 4 + 0] + m[1 * 4 + 1] * y._m[0 * 4 + 1] + m[2 * 4 + 1] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 1] * y._m[1 * 4 + 0] + m[1 * 4 + 1] * y._m[1 * 4 + 1] + m[2 * 4 + 1] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 1] * y._m[2 * 4 + 0] + m[1 * 4 + 1] * y._m[2 * 4 + 1] + m[2 * 4 + 1] * y._m[2 * 4 + 2]; m[0 * 4 + 1] = dst[0]; m[1 * 4 + 1] = dst[1]; m[2 * 4 + 1] = dst[2]; dst[0] = m[0 * 4 + 2] * y._m[0 * 4 + 0] + m[1 * 4 + 2] * y._m[0 * 4 + 1] + m[2 * 4 + 2] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 2] * y._m[1 * 4 + 0] + m[1 * 4 + 2] * y._m[1 * 4 + 1] + m[2 * 4 + 2] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 2] * y._m[2 * 4 + 0] + m[1 * 4 + 2] * y._m[2 * 4 + 1] + m[2 * 4 + 2] * y._m[2 * 4 + 2]; m[0 * 4 + 2] = dst[0]; m[1 * 4 + 2] = dst[1]; m[2 * 4 + 2] = dst[2]; dst[0] = m[0 * 4 + 3] * y._m[0 * 4 + 0] + m[1 * 4 + 3] * y._m[0 * 4 + 1] + m[2 * 4 + 3] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 3] * y._m[1 * 4 + 0] + m[1 * 4 + 3] * y._m[1 * 4 + 1] + m[2 * 4 + 3] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 3] * y._m[2 * 4 + 0] + m[1 * 4 + 3] * y._m[2 * 4 + 1] + m[2 * 4 + 3] * y._m[2 * 4 + 2]; m[0 * 4 + 3] = dst[0]; m[1 * 4 + 3] = dst[1]; m[2 * 4 + 3] = dst[2]; m[0 * 4 + 3] += y._m[0 * 4 + 3]; m[1 * 4 + 3] += y._m[1 * 4 + 3]; m[2 * 4 + 3] += y._m[2 * 4 + 3]; return(new idJointMatrix(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11])); }
/// <summary> /// Compare, with epsilon. /// </summary> /// <param name="m"></param> /// <param name="epsilon"></param> /// <returns></returns> public bool Equals(idJointMatrix m, float epsilon) { for(int i = 0; i < 12; i++) { if(idMath.Abs(_m[i] - m._m[i]) > epsilon) { return false; } } return true; }
/// <summary> /// Exact compare, no epsilon. /// </summary> /// <param name="obj"></param> /// <returns></returns> public bool Equals(idJointMatrix m) { for(int i = 0; i < 12; i++) { if(_m[i] != m._m[i]) { return false; } } return true; }
public static idJointMatrix Transform(idJointMatrix x, idJointMatrix y) { float[] m = (float[]) x._m.Clone(); float[] dst = new float[3]; dst[0] = m[0 * 4 + 0] * y._m[0 * 4 + 0] + m[1 * 4 + 0] * y._m[0 * 4 + 1] + m[2 * 4 + 0] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 0] * y._m[1 * 4 + 0] + m[1 * 4 + 0] * y._m[1 * 4 + 1] + m[2 * 4 + 0] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 0] * y._m[2 * 4 + 0] + m[1 * 4 + 0] * y._m[2 * 4 + 1] + m[2 * 4 + 0] * y._m[2 * 4 + 2]; m[0 * 4 + 0] = dst[0]; m[1 * 4 + 0] = dst[1]; m[2 * 4 + 0] = dst[2]; dst[0] = m[0 * 4 + 1] * y._m[0 * 4 + 0] + m[1 * 4 + 1] * y._m[0 * 4 + 1] + m[2 * 4 + 1] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 1] * y._m[1 * 4 + 0] + m[1 * 4 + 1] * y._m[1 * 4 + 1] + m[2 * 4 + 1] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 1] * y._m[2 * 4 + 0] + m[1 * 4 + 1] * y._m[2 * 4 + 1] + m[2 * 4 + 1] * y._m[2 * 4 + 2]; m[0 * 4 + 1] = dst[0]; m[1 * 4 + 1] = dst[1]; m[2 * 4 + 1] = dst[2]; dst[0] = m[0 * 4 + 2] * y._m[0 * 4 + 0] + m[1 * 4 + 2] * y._m[0 * 4 + 1] + m[2 * 4 + 2] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 2] * y._m[1 * 4 + 0] + m[1 * 4 + 2] * y._m[1 * 4 + 1] + m[2 * 4 + 2] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 2] * y._m[2 * 4 + 0] + m[1 * 4 + 2] * y._m[2 * 4 + 1] + m[2 * 4 + 2] * y._m[2 * 4 + 2]; m[0 * 4 + 2] = dst[0]; m[1 * 4 + 2] = dst[1]; m[2 * 4 + 2] = dst[2]; dst[0] = m[0 * 4 + 3] * y._m[0 * 4 + 0] + m[1 * 4 + 3] * y._m[0 * 4 + 1] + m[2 * 4 + 3] * y._m[0 * 4 + 2]; dst[1] = m[0 * 4 + 3] * y._m[1 * 4 + 0] + m[1 * 4 + 3] * y._m[1 * 4 + 1] + m[2 * 4 + 3] * y._m[1 * 4 + 2]; dst[2] = m[0 * 4 + 3] * y._m[2 * 4 + 0] + m[1 * 4 + 3] * y._m[2 * 4 + 1] + m[2 * 4 + 3] * y._m[2 * 4 + 2]; m[0 * 4 + 3] = dst[0]; m[1 * 4 + 3] = dst[1]; m[2 * 4 + 3] = dst[2]; m[0 * 4 + 3] += y._m[0 * 4 + 3]; m[1 * 4 + 3] += y._m[1 * 4 + 3]; m[2 * 4 + 3] += y._m[2 * 4 + 3]; return new idJointMatrix(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11]); }
private void TransformVertices(Vertex[] verts, idJointMatrix[] entityJoints) { int j, i; int vertCount = verts.Length; for(j = i = 0; i < vertCount; i++) { Vector3 w = new Vector3(_scaledWeights[j].X, _scaledWeights[j].Y, _scaledWeights[j].Z); Vector3 v = entityJoints[_weightIndex[j * 2 + 0]].ToVector3() * w; while(_weightIndex[j * 2 + 1] == 0) { j++; v += entityJoints[_weightIndex[j * 2 + 0]].ToVector3() * w; } j++; verts[i].Position = v; } }
public void Parse(idLexer lexer, idJointMatrix[] joints) { lexer.ExpectTokenString("{"); // // parse name // if(lexer.CheckTokenString("name") == true) { lexer.ReadToken(); } // // parse shader // lexer.ExpectTokenString("shader"); idToken token = lexer.ReadToken(); string materialName = token.ToString(); _material = idE.DeclManager.FindMaterial(materialName); // // parse texture coordinates // lexer.ExpectTokenString("numverts"); int count = lexer.ParseInt(); if(count < 0) { lexer.Error("Invalid size: {0}", token.ToString()); } _texCoords = new Vector2[count]; int[] firstWeightForVertex = new int[count]; int[] weightCountForVertex = new int[count]; int maxWeight = 0; int coordCount = _texCoords.Length; _weightCount = 0; for(int i = 0; i < coordCount; i++) { lexer.ExpectTokenString("vert"); lexer.ParseInt(); float[] tmp = lexer.Parse1DMatrix(2); _texCoords[i] = new Vector2(tmp[0], tmp[1]); firstWeightForVertex[i] = lexer.ParseInt(); weightCountForVertex[i] = lexer.ParseInt(); if(weightCountForVertex[i] == 0) { lexer.Error("Vertex without any joint weights."); } _weightCount += weightCountForVertex[i]; if((weightCountForVertex[i] + firstWeightForVertex[i]) > maxWeight) { maxWeight = weightCountForVertex[i] + firstWeightForVertex[i]; } } // // parse tris // lexer.ExpectTokenString("numtris"); _triangleCount = lexer.ParseInt(); if(_triangleCount < 0) { lexer.Error("Invalid size: {0}", _triangleCount); } int[] tris = new int[_triangleCount * 3]; for(int i = 0; i < _triangleCount; i++) { lexer.ExpectTokenString("tri"); lexer.ParseInt(); tris[i * 3 + 0] = lexer.ParseInt(); tris[i * 3 + 1] = lexer.ParseInt(); tris[i * 3 + 2] = lexer.ParseInt(); } // // parse weights // lexer.ExpectTokenString("numweights"); count = lexer.ParseInt(); if(count < 0) { lexer.Error("Invalid size: {0}", count); } if(maxWeight > count) { lexer.Warning("Vertices reference out of range weights in model ({0} of {1} weights).", maxWeight, count); } VertexWeight[] tempWeights = new VertexWeight[count]; for(int i = 0; i < count; i++) { lexer.ExpectTokenString("weight"); lexer.ParseInt(); int jointIndex = lexer.ParseInt(); if((jointIndex < 0) || (jointIndex >= joints.Length)) { lexer.Error("Joint index out of range({0}): {1}", joints.Length, jointIndex); } tempWeights[i].JointIndex = jointIndex; tempWeights[i].JointWeight = lexer.ParseFloat(); float[] tmp = lexer.Parse1DMatrix(3); tempWeights[i].Offset = new Vector3(tmp[0], tmp[1], tmp[2]); } // create pre-scaled weights and an index for the vertex/joint lookup _scaledWeights = new Vector4[_weightCount]; _weightIndex = new int[_weightCount * 2]; count = 0; coordCount = _texCoords.Length; for(int i = 0; i < coordCount; i++) { int num = firstWeightForVertex[i]; int weightCount = weightCountForVertex[i]; for(int j = 0; j < weightCount; j++, num++, count++) { Vector3 tmp = tempWeights[num].Offset * tempWeights[num].JointWeight; _scaledWeights[count].X = tmp.X; _scaledWeights[count].Y = tmp.Y; _scaledWeights[count].Z = tmp.Z; _scaledWeights[count].W = tempWeights[num].JointWeight; _weightIndex[count * 2 + 0] = tempWeights[num].JointIndex; } _weightIndex[count * 2 - 1] = 1; } lexer.ExpectTokenString("}"); // update counters idConsole.Warning("TODO: idRenderModel_MD5 update counters"); /*c_numVerts += texCoords.Num(); c_numWeights += numWeights; c_numWeightJoints++; for ( i = 0; i < numWeights; i++ ) { c_numWeightJoints += weightIndex[i*2+1]; }*/ // // build the information that will be common to all animations of this mesh: // silhouette edge connectivity and normal / tangent generation information // Vertex[] verts = new Vertex[_texCoords.Length]; int vertCount = verts.Length; for(int i = 0; i < vertCount; i++) { verts[i].TextureCoordinates = _texCoords[i]; } TransformVertices(verts, joints); idConsole.Warning("TODO: idMD5Mesh Deform"); //_deformInfo = idE.RenderSystem.BuildDeformInformation(verts, tris, _material.UseUnsmoothedTangents); }
public idBounds CalculateBounds(idJointMatrix[] joints) { Vertex[] verts = new Vertex[_texCoords.Length]; idBounds bounds = idBounds.Zero; TransformVertices(verts, joints); idHelper.MinMax(ref bounds.Min, ref bounds.Max, verts, _texCoords.Length); return bounds; }
/// <summary> /// Used for initial loads, reloadModel, and reloading the data of purged models. /// </summary> /// <remarks> /// Upon exit, the model will absolutely be valid, but possibly as a default model. /// </remarks> public override void Load() { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } if(_purged == false) { Purge(); } _purged = false; idLexer lexer = new idLexer(LexerOptions.AllowPathNames | LexerOptions.NoStringEscapeCharacters); if(lexer.LoadFile(Name) == false) { MakeDefault(); return; } lexer.ExpectTokenString(VersionString); int version = lexer.ParseInt(); int count = 0; idToken token; if(version != Version) { lexer.Error("Invalid version {0}. Should be version {1}", version, Version); } // // skip commandline // lexer.ExpectTokenString("commandline"); lexer.ReadToken(); // parse num joints lexer.ExpectTokenString("numJoints"); count = lexer.ParseInt(); _joints = new idMD5Joint[count]; _defaultPose = new idJointQuaternion[count]; idJointMatrix[] poseMat3 = new idJointMatrix[count]; // parse num meshes lexer.ExpectTokenString("numMeshes"); count = lexer.ParseInt(); if(count < 0) { lexer.Error("Invalid size: {0}", count); } _meshes = new idMD5Mesh[count]; // // parse joints // lexer.ExpectTokenString("joints"); lexer.ExpectTokenString("{"); int jointCount = _joints.Length; for(int i = 0; i < jointCount; i++) { idMD5Joint joint = _joints[i] = new idMD5Joint(); idJointQuaternion pose = new idJointQuaternion(); ParseJoint(lexer, joint, ref pose); poseMat3[i] = idJointMatrix.Zero; poseMat3[i].Rotation = Matrix.CreateFromQuaternion(pose.Quaternion); poseMat3[i].Translation = pose.Translation; if(joint.Parent != null) { int parentIndex = GetJointIndex(joint.Parent); pose.Quaternion = Quaternion.CreateFromRotationMatrix(poseMat3[i].ToMatrix() * Matrix.Transpose(poseMat3[parentIndex].ToMatrix())); pose.Translation = Vector3.Transform(poseMat3[i].ToVector3() - poseMat3[parentIndex].ToVector3(), Matrix.Transpose(poseMat3[parentIndex].ToMatrix())); } _defaultPose[i] = pose; } lexer.ExpectTokenString("}"); int meshCount = _meshes.Length; for(int i = 0; i < meshCount; i++) { lexer.ExpectTokenString("mesh"); _meshes[i] = new idMD5Mesh(); _meshes[i].Parse(lexer, poseMat3); } // // calculate the bounds of the model // CalculateBounds(poseMat3); // set the timestamp for reloadmodels idConsole.Warning("TODO: fileSystem->ReadFile( name, NULL, &timeStamp );"); }
public void SetupJoints(idJointMatrix[] joints, ref idBounds frameBounds, bool removeOriginOffset) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } if((_model == null) || (_model.IsDefault == true)) { joints = null; frameBounds.Clear(); } // get the number of joints int count = _model.JointCount; if(count == 0) { idConsole.Error("model '{0}' has no joints", _model.Name); } // set up initial pose for model (with no pose, model is just a jumbled mess) joints = new idJointMatrix[count]; idJointQuaternion[] pose = this.DefaultPose; // convert the joint quaternions to joint matrices idHelper.ConvertJointQuaternionsToJointMatrices(joints, pose); // check if we offset the model by the origin joint if(removeOriginOffset == true) { #if VELOCITY_MOVE joints[0].Translation(new Vector3(_offset.X, _offset.Y + pose[0].Translation.Y, _offset.Z + pose[0].Translation.Z)); #else joints[0].Translation = _offset; #endif } else { joints[0].Translation = pose[0].Translation + _offset; } // transform the joint hierarchy idHelper.TransformJoints(joints, _jointParents, 1, joints.Length - 1); // get the bounds of the default pose frameBounds = _model.GetBounds(null); }