/// <summary> /// käännä kuvakulma pos:iin /// </summary> /// <param name="pos"></param> public new void LookAt(Vector3 pos) { GL.LoadIdentity(); MathExt.LookAt(Position, pos, Up); }
/// <summary> /// luo luuranko. /// </summary> /// <param name="jointInfos"></param> /// <param name="baseFrame"></param> /// <param name="animFrameData"></param> /// <param name="frameIndex"></param> /// <param name="num_joints"></param> /// <param name="md5anim"></param> void BuildFrameSkeleton(ref MD5JointInfo[] jointInfos, ref MD5BaseFrameJoint[] baseFrame, ref float[] animFrameData, int frameIndex, int num_joints, ref Animation md5anim) { int i; for (i = 0; i < num_joints; ++i) { MD5BaseFrameJoint baseJoint = baseFrame[i]; Vector3 animatedPos; Quaternion animatedOrient; int j = 0; animatedPos = baseJoint.pos; animatedOrient = baseJoint.orient; if ((jointInfos[i].flags & 1) > 0) /* Tx */ { animatedPos.X = animFrameData[jointInfos[i].startIndex + j]; ++j; } if ((jointInfos[i].flags & 2) > 0) /* Ty */ { animatedPos.Y = animFrameData[jointInfos[i].startIndex + j]; ++j; } if ((jointInfos[i].flags & 4) > 0) /* Tz */ { animatedPos.Z = animFrameData[jointInfos[i].startIndex + j]; ++j; } if ((jointInfos[i].flags & 8) > 0) /* Qx */ { animatedOrient.X = animFrameData[jointInfos[i].startIndex + j]; ++j; } if ((jointInfos[i].flags & 16) > 0) /* Qy */ { animatedOrient.Y = animFrameData[jointInfos[i].startIndex + j]; ++j; } if ((jointInfos[i].flags & 32) > 0) /* Qz */ { animatedOrient.Z = animFrameData[jointInfos[i].startIndex + j]; ++j; } /* Compute orient quaternion's w value */ MathExt.ComputeW(ref animatedOrient); int parent = jointInfos[i].parent; md5anim.skelFrames[frameIndex, i].parent = parent; md5anim.skelFrames[frameIndex, i].name = jointInfos[i].name; /* Has parent? */ if (md5anim.skelFrames[frameIndex, i].parent < 0) { md5anim.skelFrames[frameIndex, i].pos = animatedPos; md5anim.skelFrames[frameIndex, i].orient = animatedOrient; } else { MD5Joint parentJoint = md5anim.skelFrames[frameIndex, parent]; Vector3 rpos; /* Rotated Position */ /* Add positions */ rpos = MathExt.RotatePoint(ref parentJoint.orient, ref animatedPos); md5anim.skelFrames[frameIndex, i].pos.X = rpos.X + parentJoint.pos.X; md5anim.skelFrames[frameIndex, i].pos.Y = rpos.Y + parentJoint.pos.Y; md5anim.skelFrames[frameIndex, i].pos.Z = rpos.Z + parentJoint.pos.Z; /* Concatenate rotations */ md5anim.skelFrames[frameIndex, i].orient = MathExt.Mult(ref parentJoint.orient, ref animatedOrient); md5anim.skelFrames[frameIndex, i].orient = MathExt.Normalize(ref md5anim.skelFrames[frameIndex, i].orient); } } }
/// <summary> /// lataa md5-animaatio. /// </summary> /// <param name="fileName"></param> /// <param name="anim"></param> public override void LoadAnim(string animName, string fileName) { if (fileName == null || fileName == "") { return; } Animation anim = new Animation(); anim.animName = animName; Buffer t = new Buffer(); MD5JointInfo[] jointInfos = null; MD5BaseFrameJoint[] baseFrame = null; float[] animFrameData = null; int numAnimatedComponents = 0; int frame_index; int i; using (System.IO.StreamReader file = new System.IO.StreamReader(Settings.DataDir + fileName)) { string line; while ((line = file.ReadLine()) != null) { if (line == "") { continue; } // Read number of joints if (ParseLine(ref t, line, "numFrames %d")) { /* Allocate memory for skeleton frames and bounding boxes */ anim.numFrames = t.ibuffer[0]; if (anim.numFrames > 0) { anim.bboxes = new MD5BoundingBox[anim.numFrames]; } } if (ParseLine(ref t, line, "numJoints %d")) { /* Allocate memory for joints of each frame */ anim.numJoints = t.ibuffer[0]; if (anim.numJoints > 0) { /* Allocate temporary memory for building skeleton frames */ jointInfos = new MD5JointInfo[anim.numJoints]; baseFrame = new MD5BaseFrameJoint[anim.numJoints]; } anim.skelFrames = new MD5Joint[anim.numFrames, anim.numJoints]; } if (ParseLine(ref t, line, "frameRate %d")) { anim.frameRate = t.ibuffer[0]; } if (ParseLine(ref t, line, "numAnimatedComponents %d")) { numAnimatedComponents = t.ibuffer[0]; if (numAnimatedComponents > 0) { /* Allocate memory for animation frame data */ animFrameData = new float[numAnimatedComponents]; } } if (line.Equals("hierarchy {")) { for (i = 0; i < anim.numJoints; ++i) { /* Read whole line */ line = file.ReadLine(); Cleanstring(ref line); /* Read joint info */ ParseLine(ref t, line, "%s %d %d %d"); jointInfos[i].name = t.sbuffer; jointInfos[i].parent = t.ibuffer[0]; jointInfos[i].flags = t.ibuffer[1]; jointInfos[i].startIndex = t.ibuffer[2]; } } if (line.Equals("bounds {")) { for (i = 0; i < anim.numFrames; ++i) { /* Read whole line */ line = file.ReadLine(); Cleanstring(ref line); /* Read bounding box */ ParseLine(ref t, line, "( %f %f %f ) ( %f %f %f )"); anim.bboxes[i].min.X = t.fbuffer[0]; anim.bboxes[i].min.Y = t.fbuffer[1]; anim.bboxes[i].min.Z = t.fbuffer[2]; anim.bboxes[i].max.X = t.fbuffer[3]; anim.bboxes[i].max.Y = t.fbuffer[4]; anim.bboxes[i].max.Z = t.fbuffer[5]; } } if (line.Equals("baseframe {")) { for (i = 0; i < anim.numJoints; ++i) { /* Read whole line */ line = file.ReadLine(); Cleanstring(ref line); /* Read base frame joint */ ParseLine(ref t, line, "( %f %f %f ) ( %f %f %f )"); if (t.fbuffer.Length == 6) { baseFrame[i].pos.X = t.fbuffer[0]; baseFrame[i].pos.Y = t.fbuffer[1]; baseFrame[i].pos.Z = t.fbuffer[2]; baseFrame[i].orient.X = t.fbuffer[3]; baseFrame[i].orient.Y = t.fbuffer[4]; baseFrame[i].orient.Z = t.fbuffer[5]; /* Compute the w component */ MathExt.ComputeW(ref baseFrame[i].orient); } } } if (ParseLine(ref t, line, "frame %d")) { frame_index = t.ibuffer[0]; /* Read frame data */ for (i = 0; i < numAnimatedComponents;) { line = file.ReadLine(); if (line[0] == '}') { break; } Cleanstring(ref line); string[] splt = line.Split(' '); for (int ww = 0; ww < splt.Length; ww++) { animFrameData[i++] = float.Parse(splt[ww]); } } /* Build frame skeleton from the collected data */ BuildFrameSkeleton(ref jointInfos, ref baseFrame, ref animFrameData, frame_index, anim.numJoints, ref anim); } } anim.curFrame = 0; anim.nextFrame = 1; anim.lastTime = 0; anim.maxTime = 1.0f / anim.frameRate; /* Allocate memory for animated skeleton */ skeleton = new MD5Joint[anim.numJoints]; animated = true; Vector3 min = new Vector3(9999, 9999, 9999); Vector3 max = new Vector3(-9999, -9999, -9999); // laske bboxit for (int q = 0; q < anim.numFrames; q++) { if (anim.bboxes[q].min.X < min.X) { min.X = anim.bboxes[q].min.X; } if (anim.bboxes[q].min.Y < min.Y) { min.Y = anim.bboxes[q].min.Y; } if (anim.bboxes[q].min.Z < min.Z) { min.Z = anim.bboxes[q].min.Z; } if (anim.bboxes[q].max.X > max.X) { max.X = anim.bboxes[q].max.X; } if (anim.bboxes[q].max.Y > max.Y) { max.Y = anim.bboxes[q].max.Y; } if (anim.bboxes[q].max.Z > max.Z) { max.Z = anim.bboxes[q].max.Z; } } Boundings = new BoundingVolume(); Boundings.CreateBoundingVolume(this, min, max); Update(0); animations.Add(anim); Log.WriteDebugLine("Animation: " + fileName); UseAnimation(animName); } }
/// <summary> /// lataa md5 model /// </summary> /// <param name="fileName"></param> public void Load(string fileName) { // Initialize everything string line, textureName = ""; int i; Buffer t = new Buffer(); meshCount = 0; using (System.IO.StreamReader file = new System.IO.StreamReader(Settings.DataDir + fileName)) { { while ((line = file.ReadLine()) != null) { Cleanstring(ref line); // Read number of joints if (ParseLine(ref t, line, "numJoints %d")) { numJoints = t.ibuffer[0]; baseSkel = new MD5Joint[numJoints]; } // Read number os meshes if (ParseLine(ref t, line, "numMeshes %d")) { numMesh = t.ibuffer[0]; model = new MD5Mesh[numMesh]; meshes = new List <Vertex[]>(numMesh); } // Parse model joints if (line.Equals("joints {")) { for (i = 0; i < numJoints; i++) { line = file.ReadLine(); Cleanstring(ref line); ParseLine(ref t, line, "%s %d ( %f %f %f ) ( %f %f %f )"); baseSkel[i].name = t.sbuffer; baseSkel[i].parent = t.ibuffer[0]; baseSkel[i].pos.X = t.fbuffer[0]; baseSkel[i].pos.Y = t.fbuffer[1]; baseSkel[i].pos.Z = t.fbuffer[2]; baseSkel[i].orient = new Quaternion(t.fbuffer[3], t.fbuffer[4], t.fbuffer[5], 1); /* * jotain tosi outoa.. * toi orient homma ei skulaa.. * vaik varaa tilaa new:llä, ei toimi.. * eikä orient.X = 1; eikä mikään. miks?? */ MathExt.ComputeW(ref baseSkel[i].orient); } } // Parse model meshes if (line.Equals("mesh {")) { while (!line.Equals("}")) { line = file.ReadLine(); Cleanstring(ref line); // Read texture name if (line.StartsWith("shader")) { string str = line.Substring(7); int lp = str.LastIndexOf("/"); textureName = str.Substring(lp + 1); // texturen nimi lp = fileName.LastIndexOf("/"); string dir = fileName.Substring(0, lp + 1); // md5 tiedoston hakemisto textureName = Settings.DataDir + dir + textureName; textureName = textureName.Replace(",", "."); } // Read mesh data if (ParseLine(ref t, line, "numverts %d")) { model[meshCount].numVert = t.ibuffer[0]; model[meshCount].verts = new MD5Vertex[model[meshCount].numVert]; model[meshCount].texture = Texture.Load(textureName, false); for (i = 0; i < model[meshCount].numVert; i++) { line = file.ReadLine(); ParseLine(ref t, line, "vert %d ( %f %f ) %d %d"); model[meshCount].verts[t.ibuffer[0]].uv.X = t.fbuffer[0]; model[meshCount].verts[t.ibuffer[0]].uv.Y = 1 - t.fbuffer[1]; model[meshCount].verts[t.ibuffer[0]].startw = t.ibuffer[1]; model[meshCount].verts[t.ibuffer[0]].countw = t.ibuffer[2]; } } if (ParseLine(ref t, line, "numtris %d")) { model[meshCount].numTris = t.ibuffer[0]; model[meshCount].faces = new int[model[meshCount].numTris][]; for (i = 0; i < model[meshCount].numTris; i++) { line = file.ReadLine(); ParseLine(ref t, line, "tri %d %d %d %d"); model[meshCount].faces[t.ibuffer[0]] = new int[3]; model[meshCount].faces[t.ibuffer[0]][0] = t.ibuffer[3]; // poly toisin päin model[meshCount].faces[t.ibuffer[0]][1] = t.ibuffer[2]; model[meshCount].faces[t.ibuffer[0]][2] = t.ibuffer[1]; } } if (ParseLine(ref t, line, "numweights %d")) { model[meshCount].numWeights = t.ibuffer[0]; model[meshCount].weights = new MD5Weight[model[meshCount].numWeights]; for (i = 0; i < model[meshCount].numWeights; i++) { line = file.ReadLine(); ParseLine(ref t, line, "weight %d %d %f ( %f %f %f )"); model[meshCount].weights[t.ibuffer[0]].joint = t.ibuffer[1]; model[meshCount].weights[t.ibuffer[0]].bias = t.fbuffer[0]; model[meshCount].weights[t.ibuffer[0]].pos.X = t.fbuffer[1]; model[meshCount].weights[t.ibuffer[0]].pos.Y = t.fbuffer[2]; model[meshCount].weights[t.ibuffer[0]].pos.Z = t.fbuffer[3]; } } } meshCount++; } } } } int maxvert = 0; for (int k = 0; k < numMesh; k++) { if (model[k].numVert > maxvert) { maxvert = model[k].numVert; } } for (int k = 0; k < numMesh; k++) { finalVert = new Vector3[maxvert]; normals = new Vector3[maxvert]; } skeleton = baseSkel; updateAnimCount = FramesBetweenAnimUpdate; updateNormalsCount = FramesBetweenNormalsUpdate; // prepare model for rendering PrepareMesh(); for (int q = 0; q < numMesh; q++) { Vertex[] v = meshes[q]; int[] ind = new int[v.Length]; for (int w = 0; w < ind.Length; w++) { ind[w] = w; } // luo vbo ja datat sinne model[q].vbo = new VBO(BufferUsageHint.DynamicDraw); model[q].vbo.DataToVBO(v, ind); } material = new Material("default"); MaterialName = "default"; Log.WriteDebugLine("Model: " + Name); }