/// <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> /// aseta haluttu animaatio /// </summary> /// <param name="animName"></param> public override void UseAnimation(string animName) { if (curAnim.animName != animName) { for (int q = 0; q < animations.Count; q++) { if (animations[q].animName == animName) { curAnim = animations[q]; break; } } } }
/// <summary> /// lasketaan frame /// </summary> /// <param name="anim"></param> /// <param name="dt"></param> void Animate(ref Animation anim, float dt) { int maxFrames = anim.numFrames - 1; anim.lastTime += dt; /* move to next frame */ if (anim.lastTime >= anim.maxTime) { anim.curFrame++; anim.nextFrame++; anim.lastTime = 0.0f; if (anim.curFrame > maxFrames) anim.curFrame = 0; if (anim.nextFrame > maxFrames) anim.nextFrame = 0; } }
/// <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); } }