public static List<TRAnimationClip> AttachAnimation(Tr2Moveable tr2movable, Parser.Tr2Level leveldata) { List<TRAnimationClip> clips = CreateAnimationWithID(tr2movable,tr2movable.TransformsTree, leveldata); //tr2movable.UnityObject.AddComponent<AnimationPlayer>(); //m_DynamicPrefabs[i].AnimClips = new List<TRAnimationClip>(); //add these clips to Tr2Moveable tr2movable.UnityAnimation for(int ci = 0; ci < clips.Count; ci++) { #if UNITY_4_0 clips[ci].clip.legacy = true; #elif UNITY_4_0_1 clips[ci].clip.legacy = true; #elif UNITY_4_1 clips[ci].clip.legacy = true; #elif UNITY_4_2 clips[ci].clip.legacy = true; #elif UNITY_4_3 clips[ci].clip.legacy = true; #elif UNITY_4_5 clips[ci].clip.legacy = true; #elif UNITY_4_6 clips[ci].clip.legacy = true; #elif UNITY_5_0 clips[ci].clip.legacy = true; #endif tr2movable.UnityAnimation.AddClip(clips[ci].clip, "" + ci); tr2movable.AnimClips.Add(clips[ci]); } return clips; }
public static List <TRAnimationClip> AttachAnimation(Tr2Moveable tr2movable, Parser.Tr2Level leveldata) { List <TRAnimationClip> clips = CreateAnimationWithID(tr2movable, tr2movable.TransformsTree, leveldata); //tr2movable.UnityObject.AddComponent<AnimationPlayer>(); //m_DynamicPrefabs[i].AnimClips = new List<TRAnimationClip>(); //add these clips to Tr2Moveable tr2movable.UnityAnimation for (int ci = 0; ci < clips.Count; ci++) { tr2movable.UnityAnimation.AddClip(clips[ci].clip, "" + ci); } tr2movable.AnimClips = clips; return(clips); }
GameObject[] CreateMultiPartObject(Tr2Moveable tr2movable) { GameObject[] parts = new GameObject[tr2movable.NumMeshes]; // run through all the meshes init transforms for (int i = 0; i < tr2movable.NumMeshes; i++) { int itemMeshIdx = (int)(tr2movable.StartingMesh + i); // mesh id in tr2 mesh table if (itemMeshIdx > m_leveldata.NumMeshes - 1) { itemMeshIdx = (int)(m_leveldata.NumMeshes - 1); } parts[i] = CreateObjectWithID(itemMeshIdx, Vector3.zero, Quaternion.identity, "objPart:" + itemMeshIdx); parts[i].transform.parent = null; } return(parts); }
GameObject[] CreateMultiPartObject(Tr2Moveable tr2movable) { GameObject[] parts = new GameObject[tr2movable.NumMeshes]; // run through all the meshes init transforms for (int i = 0; i < tr2movable.NumMeshes; i++) { int itemMeshIdx = (int)(tr2movable.StartingMesh + i); // mesh id in tr2 mesh table if(itemMeshIdx > m_leveldata.NumMeshes-1) { itemMeshIdx = (int)(m_leveldata.NumMeshes-1); } parts[i] = CreateObjectWithID(itemMeshIdx, Vector3.zero, Quaternion.identity, "objPart:" + itemMeshIdx); parts[i].transform.parent = null; } return parts; }
//param transformtree: number of transform used in animation clip //param startclipid : first animation clip index into Parser.Tr2Animation array //keyframeinfo: holds tr2 keyframes related info for an animation public static List <TRAnimationClip> CreateAnimationWithID(Tr2Moveable tr2movable, Transform[] transformtree, Parser.Tr2Level leveldata) { List <TRAnimationClip> tranimclips = new List <TRAnimationClip>(); int ntransform = transformtree.Length; int trclipoffset = tr2movable.AnimationStartOffset; Parser.TR2VersionType enginetype = leveldata.EngineVersion; //each tr anim actually information that reffer a chunk of animation frames contained in frames[] //each frame chunk contain sequential data [key] for all of the transform of this object //Now question is how many animation clips there are ? //KeyFrameData keyframeinfo = CalculateAnimationKeyFrameData(trclipoffset, leveldata); /*bool shortanimation = false; * if (keyframeinfo.numkeyframe < 15) * { * shortanimation = true; * } * * int nclip = 1; * if (tr2movable.ObjectID == 0) * { * nclip = 261; * * Debug.Log(" lara trclipoffset: " + trclipoffset); * } * * //Debug.Log("ID: " + tr2movable.ObjectID + " trclipoffset: " + trclipoffset); */ for (int clipid = 0; clipid < tr2movable.NumClips; clipid++) { //if(shortanimation && clipid > 5) break; KeyFrameData keyframeinfo = CalculateAnimationKeyFrameData(trclipoffset, leveldata); Parser.Tr2Animation tr2animation = leveldata.Animations[trclipoffset]; AnimationCurve curvRelX = null; AnimationCurve curvRelY = null; AnimationCurve curvRelZ = null; AnimationCurve[] curvRelRotX = new AnimationCurve[ntransform]; AnimationCurve[] curvRelRotY = new AnimationCurve[ntransform]; AnimationCurve[] curvRelRotZ = new AnimationCurve[ntransform]; AnimationCurve[] curvRelRotW = new AnimationCurve[ntransform]; //prepare curves for animation for (int transformId = 0; transformId < ntransform; transformId++) { //create curves curvRelRotX[transformId] = new AnimationCurve(null); curvRelRotY[transformId] = new AnimationCurve(null); curvRelRotZ[transformId] = new AnimationCurve(null); curvRelRotW[transformId] = new AnimationCurve(null); if (transformId == 0) { curvRelX = new AnimationCurve(null); curvRelY = new AnimationCurve(null); curvRelZ = new AnimationCurve(null); } } int numkeyframe = keyframeinfo.numkeyframe; for (int keyFrameCount = 0; keyFrameCount < numkeyframe; ++keyFrameCount) { int frameoffset = keyframeinfo.startoffset + (keyframeinfo.framesize * keyFrameCount); //extract key frme rotation int l = 9; //first angle offset in this Frame for (int transformId = 0; transformId < ntransform; transformId++) { ushort itmp = keyframeinfo.data[frameoffset + l]; ushort itmp2; double angle; float rotx = 0; float roty = 0; float rotz = 0; l = l + 1; if (enginetype == Parser.TR2VersionType.TombRaider_1) { // all angles are three-axis angle = (itmp >> 4) & 0x03ff; angle *= 360.0 / 1024.0; rotx = (float)angle; //keyframe rotx value itmp2 = (ushort)((itmp << 6) & 0x03c0); itmp = keyframeinfo.data[frameoffset + l]; // get Z rotation l = l + 1; itmp2 |= (ushort)((itmp >> 10) & 0x003f); angle = itmp2; angle *= 360.0 / 1024.0; roty = (float)angle; //keyframe roty value angle = itmp & 0x3ff; angle *= 360.0 / 1024.0; rotz = (float)angle; //keyframe rotz value } else if ((itmp & 0xc000) > 0) // TR2, TR3, TR4 - single axis of rotation { if (enginetype == Parser.TR2VersionType.TombRaider_4) { angle = itmp & 0x0fff; angle /= 4096.0; angle *= 360.0; } else { angle = itmp & 0x3ff; angle /= 1024.0; angle *= 360.0; } switch (itmp & 0xc000) { case 0x4000: rotx = (float)angle; break; case 0x8000: roty = (float)angle; break; case 0xc000: rotz = (float)angle; break; } } else // TR2, TR3, TR4 - three axes { angle = (itmp >> 4) & 0x03ff; angle *= 360.0 / 1024.0; rotx = (float)angle; itmp2 = (ushort)((itmp << 6) & 0x03c0); itmp = keyframeinfo.data[frameoffset + l]; // get Z rotation l = l + 1; itmp2 |= (ushort)((itmp >> 10) & 0x003f); angle = itmp2; angle *= 360.0 / 1024.0; roty = (float)angle; angle = itmp & 0x3ff; angle *= 360.0 / 1024.0; rotz = (float)angle; } //if(rotx > 180) //{ rotx = Mathf.Abs(360 - rotx); //} //if(rotz > 180) //{ rotz = Mathf.Abs(360 - rotz);; //} //if(roty > 180) //{ //roty= Mathf.Abs(360 - roty) ;; //} if (transformId == 0) { float ItemAnimX = (short)keyframeinfo.data[frameoffset + 6] * Settings.SceneScaling; float ItemAnimY = (short)keyframeinfo.data[frameoffset + 7] * Settings.SceneScaling; float ItemAnimZ = (short)keyframeinfo.data[frameoffset + 8] * Settings.SceneScaling; if (numkeyframe == 1) //addition key after last key { curvRelX.AddKey(0, ItemAnimX); curvRelY.AddKey(0, -ItemAnimY); curvRelZ.AddKey(0, ItemAnimZ); curvRelX.AddKey(1 * keyframeinfo.time_per_frame, ItemAnimX); curvRelY.AddKey(1 * keyframeinfo.time_per_frame, -ItemAnimY); curvRelZ.AddKey(1 * keyframeinfo.time_per_frame, ItemAnimZ); } else { int keylength = curvRelX.length; if (keylength > 0) { Keyframe kx = new Keyframe(keylength * keyframeinfo.time_per_frame, ItemAnimX, Mathf.Infinity, Mathf.Infinity); Keyframe ky = new Keyframe(keylength * keyframeinfo.time_per_frame, -ItemAnimY, Mathf.Infinity, Mathf.Infinity); Keyframe kz = new Keyframe(keylength * keyframeinfo.time_per_frame, ItemAnimZ, Mathf.Infinity, Mathf.Infinity); curvRelX.AddKey(kx); curvRelY.AddKey(ky); curvRelZ.AddKey(kz); } else { curvRelX.AddKey(0, ItemAnimX); curvRelY.AddKey(0, -ItemAnimY); curvRelZ.AddKey(0, ItemAnimZ); } } } //TODO: //multiply transform with reltive rotation and translation data //relative translation of animation. allready provided? //problem: animation transform works in local space.Thats mean it does not work on root?Am I working in root? Quaternion finalrot = Quaternion.AngleAxis(roty, Vector3.up) * Quaternion.AngleAxis(rotx, Vector3.right) * Quaternion.AngleAxis(rotz, Vector3.forward); if (numkeyframe == 1) //addition key after last key { curvRelRotX[transformId].AddKey(0, finalrot.x); curvRelRotY[transformId].AddKey(0, finalrot.y); curvRelRotZ[transformId].AddKey(0, finalrot.z); curvRelRotW[transformId].AddKey(0, finalrot.w); curvRelRotX[transformId].AddKey(keyframeinfo.time_per_frame, finalrot.x); curvRelRotY[transformId].AddKey(keyframeinfo.time_per_frame, finalrot.y); curvRelRotZ[transformId].AddKey(keyframeinfo.time_per_frame, finalrot.z); curvRelRotW[transformId].AddKey(keyframeinfo.time_per_frame, finalrot.w); } else { int keylength = curvRelRotX[transformId].length; if (keylength > 0) { //FIX: set outTangent and inTangent to Mathf.Infinity Keyframe kfrotx = new Keyframe(keylength * keyframeinfo.time_per_frame, finalrot.x, Mathf.Infinity, Mathf.Infinity); Keyframe kfroty = new Keyframe(keylength * keyframeinfo.time_per_frame, finalrot.y, Mathf.Infinity, Mathf.Infinity); Keyframe kfrotz = new Keyframe(keylength * keyframeinfo.time_per_frame, finalrot.z, Mathf.Infinity, Mathf.Infinity); Keyframe kfrotw = new Keyframe(keylength * keyframeinfo.time_per_frame, finalrot.w, Mathf.Infinity, Mathf.Infinity); curvRelRotX[transformId].AddKey(kfrotx); curvRelRotY[transformId].AddKey(kfroty); curvRelRotZ[transformId].AddKey(kfrotz); curvRelRotW[transformId].AddKey(kfrotw); } else { curvRelRotX[transformId].AddKey(0, finalrot.x); curvRelRotY[transformId].AddKey(0, finalrot.y); curvRelRotZ[transformId].AddKey(0, finalrot.z); curvRelRotW[transformId].AddKey(0, finalrot.w); } } } } AnimationClip animClip = new AnimationClip(); //if animClip is not set to legacy set curve will not workt on vesion 4 or higher #if UNITY_4_0 animClip.legacy = true; #elif UNITY_4_0_1 animClip.legacy = true; #elif UNITY_4_1 animClip.legacy = true; #elif UNITY_4_2 animClip.legacy = true; #elif UNITY_4_3 animClip.legacy = true; #elif UNITY_4_5 animClip.legacy = true; #elif UNITY_4_6 animClip.legacy = true; #elif UNITY_5_0 animClip.legacy = true; #endif #if (UNITY_5_3_OR_NEWER || UNITY_5_3) animClip.legacy = true; #endif for (int transformId = 0; transformId < ntransform; transformId++) { System.String relCurvePath = CalculateCurveRelativePath(transformtree[transformId]); //print("relCurvePath:"+relCurvePath); if (transformId != 0) { animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.x", curvRelRotX[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.y", curvRelRotY[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.z", curvRelRotZ[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.w", curvRelRotW[transformId]); } else { animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.x", curvRelRotX[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.y", curvRelRotY[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.z", curvRelRotZ[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.w", curvRelRotW[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localPosition.x", curvRelX); animClip.SetCurve(relCurvePath, typeof(Transform), "localPosition.y", curvRelY); animClip.SetCurve(relCurvePath, typeof(Transform), "localPosition.z", curvRelZ); } } TRAnimationClip tranimclip = new TRAnimationClip(animClip, leveldata.Animations[clipid].StateID); tranimclip.time_per_frame = keyframeinfo.time_per_frame; tranimclip.starttime = 0.0f; tranimclip.endtime = keyframeinfo.numkeyframe * tranimclip.time_per_frame; tranimclip.framerate = 7 - tr2animation.FrameRate;// 1f / tranimclip.time_per_frame ; tranimclip.index = clipid; tranimclip.start_animation_frame_index = keyframeinfo.start_animation_frame_index; tranimclips.Add(tranimclip); //goto next clip trclipoffset++; } return(tranimclips); }
//Raw structure data casting is problematice in C#. So break down a structure to it's fields and read them individually. This looks //ugly but works : ) static object Cast2Struct(byte[] buffer, System.Type type) { object retval = null; if(type == typeof(Tr2RoomInfo)) { Tr2RoomInfo t = new Tr2RoomInfo(); t.x = System.BitConverter.ToInt32(buffer,0); t.z = System.BitConverter.ToInt32(buffer,4); t.yBottom = System.BitConverter.ToInt32(buffer,8); t.yTop = System.BitConverter.ToInt32(buffer,8); retval = t; } else if(type== typeof(Tr2VertexRoom)) { Tr2VertexRoom t = new Tr2VertexRoom(); t.Vertex.x = System.BitConverter.ToInt16(buffer,0); t.Vertex.y = System.BitConverter.ToInt16(buffer,2); t.Vertex.z = System.BitConverter.ToInt16(buffer,4); t.Lighting1 = System.BitConverter.ToInt16(buffer,6); // values range from 0 to 32767, 0=total darkness. (TR3) // I think the values ranged from 0 to 8192 in TR1/2, 0=total brightness t.Attributes = System.BitConverter.ToUInt16(buffer,8); // 0x8000 something to do with water surface // 0x4000 under water lighting modulation and movement if viewed from above water surface // 0x2000 water/quicksand surface movement // 0x1fef nothing? // 0x0010 everything? t.Lighting2 = System.BitConverter.ToInt16(buffer,10); // seems to be the same as lighting1 retval = t; } else if(type == typeof(Tr2Vertex)) { Tr2Vertex t = new Tr2Vertex(); t.x = System.BitConverter.ToInt16(buffer,0); t.y = System.BitConverter.ToInt16(buffer,2); t.z = System.BitConverter.ToInt16(buffer,4); retval = t; } else if(type == typeof(Tr2RoomSector)) { Tr2RoomSector t = new Tr2RoomSector(); t.FDindex = System.BitConverter.ToUInt16(buffer,0); t.BoxIndex = System.BitConverter.ToUInt16(buffer,2); t.RoomBelow = buffer[4]; // 255 if none t.Floor =(sbyte) buffer[5]; //char ==2 byte in c# here; chaqnge it to byte t.RoomAbove = buffer[6]; // 255 if none t.Ceiling = (sbyte) buffer[7]; retval = t; } else if(type == typeof(Tr2RoomLight)) { Tr2RoomLight t = new Tr2RoomLight(); t.x = System.BitConverter.ToInt32(buffer,0); t.y = System.BitConverter.ToInt32(buffer,4); t.z = System.BitConverter.ToInt32(buffer,8); t.Intensity1 = System.BitConverter.ToUInt16(buffer,12); t.Intensity2 = System.BitConverter.ToUInt16(buffer,14); t.Fade1 = System.BitConverter.ToUInt32(buffer,16); t.Fade2 = System.BitConverter.ToUInt32(buffer,20); retval = t; } else if(type == typeof(Tr2RoomStaticMesh)) { Tr2RoomStaticMesh t = new Tr2RoomStaticMesh(); t.x = System.BitConverter.ToInt32(buffer,0); // absolute position in world coordinates t.y = System.BitConverter.ToInt32(buffer,4); t.z = System.BitConverter.ToInt32(buffer,8); t.Rotation = System.BitConverter.ToUInt16(buffer,12); // high two bits (0xc000) indicate steps of 90 degrees t.Intensity1 = System.BitConverter.ToUInt16(buffer,14); t.Intensity2 = System.BitConverter.ToUInt16(buffer,16); t.ObjectID = System.BitConverter.ToUInt16(buffer,18); // which StaticMesh item to draw retval = t; } else if(type == typeof(Tr2RoomSprite)) { Tr2RoomSprite t = new Tr2RoomSprite(); t.Vertex = System.BitConverter.ToInt16(buffer,0); // offset into vertex list t.Texture = System.BitConverter.ToInt16(buffer,2); // offset into texture list retval = t; } else if(type == typeof(Tr2Face4)) { Tr2Face4 t = new Tr2Face4(); t.Vertices0 = System.BitConverter.ToUInt16(buffer,0); t.Vertices1 = System.BitConverter.ToUInt16(buffer,2); t.Vertices2 = System.BitConverter.ToUInt16(buffer,4); t.Vertices3 = System.BitConverter.ToUInt16(buffer,6); t.Texture = System.BitConverter.ToUInt16(buffer,8); retval = t; } else if(type== typeof(Tr2Face3)) { Tr2Face3 t = new Tr2Face3(); t.Vertices0 = System.BitConverter.ToUInt16(buffer,0); t.Vertices1 = System.BitConverter.ToUInt16(buffer,2); t.Vertices2 = System.BitConverter.ToUInt16(buffer,4); t.Texture = System.BitConverter.ToUInt16(buffer,6); retval = t; } else if(type == typeof(Tr2Animation)) { Tr2Animation t = new Tr2Animation(); t.FrameOffset = System.BitConverter.ToUInt32(buffer,0); // byte offset into Frames[] (divide by 2 for Frames[i]) t.FrameRate = buffer[4]; // "ticks" per frame t.FrameSize = buffer[5]; // number of words in Frames[] used by this animation t.StateID = System.BitConverter.ToInt16(buffer,6); t.Unknown1 = System.BitConverter.ToInt16(buffer,8); t.Unknown2 = System.BitConverter.ToInt16(buffer,10); t.Unknown3 = System.BitConverter.ToInt16(buffer,12); t.Unknown4 = System.BitConverter.ToInt16(buffer,14); t.FrameStart = System.BitConverter.ToUInt16(buffer,16); // first frame in this animation t.FrameEnd = System.BitConverter.ToUInt16(buffer,18); // last frame in this animation (numframes = (End - Start) + 1) t.NextAnimation = System.BitConverter.ToUInt16(buffer,20); t.NextFram = System.BitConverter.ToUInt16(buffer,22); t.NumStateChanges = System.BitConverter.ToUInt16(buffer,24); t.StateChangeOffset = System.BitConverter.ToUInt16(buffer,26); // offset into StateChanges[] t.NumAnimCommands = System.BitConverter.ToUInt16(buffer,28); t.AnimCommand = System.BitConverter.ToUInt16(buffer,30); // offset into AnimCommands[] retval = t; } else if(type == typeof(Tr2StateChange)) { Tr2StateChange t = new Tr2StateChange(); t.StateID = System.BitConverter.ToUInt16(buffer,0); ; t.NumAnimDispatches = System.BitConverter.ToUInt16(buffer,2); ; // number of dispatches (seems to always be 1..5) t.AnimDispatch = System.BitConverter.ToUInt16(buffer,4); ; // Offset into AnimDispatches[] retval = t; } else if(type == typeof(Tr2AnimDispatch)) { Tr2AnimDispatch t = new Tr2AnimDispatch(); t.Low = System.BitConverter.ToInt16(buffer,0); t.High = System.BitConverter.ToInt16(buffer,2);; t.NextAnimation = System.BitConverter.ToInt16(buffer,4);; t.NextFrame = System.BitConverter.ToInt16(buffer,6);; retval = t; } else if(type == typeof(Tr2AnimCommand)) { Tr2AnimCommand t = new Tr2AnimCommand(); t.Value = System.BitConverter.ToInt16(buffer,0);; retval = t; } else if(type == typeof(Tr2Moveable)) { Tr2Moveable t = new Tr2Moveable(); t.ObjectID = System.BitConverter.ToUInt32(buffer,0); // Item Identifier t.NumMeshes = System.BitConverter.ToUInt16(buffer,4); // number of meshes in this object t.StartingMesh = System.BitConverter.ToUInt16(buffer,6); // first mesh t.MeshTree = System.BitConverter.ToUInt32(buffer,8); // offset into MeshTree[] t.FrameOffset = System.BitConverter.ToUInt32(buffer,12); // byte offset into Frames[] (divide by 2 for Frames[i]) t.Animation = System.BitConverter.ToUInt16(buffer,16); // offset into Animations[] retval = t; } else if(type == typeof(Tr2ObjectTextureVertex)) { Tr2ObjectTextureVertex t = new Tr2ObjectTextureVertex(); t.Xcoordinate = buffer[0]; t.Xpixel = buffer[1]; t.Ycoordinate = buffer[2]; t.Ypixel = buffer[3]; retval = t; } else if(type == typeof(Tr2SpriteTexture)) { Tr2SpriteTexture t = new Tr2SpriteTexture(); t.Tile = System.BitConverter.ToUInt16(buffer,0); t.x = buffer[2]; t.y = buffer[3]; t.Width = System.BitConverter.ToUInt16(buffer,4); // actually, (width * 256) + 255 t.Height = System.BitConverter.ToUInt16(buffer,6); // actually, (height * 256) + 255 t.LeftSide = System.BitConverter.ToInt16(buffer,8); t.TopSide = System.BitConverter.ToInt16(buffer,10); t.RightSide = System.BitConverter.ToInt16(buffer,12); t.Bottomside = System.BitConverter.ToInt16(buffer,14); retval = t; } else if(type == typeof(Tr2SpriteSequence)) { Tr2SpriteSequence t = new Tr2SpriteSequence(); t.ObjectID = System.BitConverter.ToInt32(buffer,0); // Item identifier (same numbering as in tr2_moveable) t.NegativeLength = System.BitConverter.ToInt16(buffer,4); // negative of "how many sprites are in this sequence" t.Offset = System.BitConverter.ToInt16(buffer,6); // where (in sprite texture list) this sequence starts retval = t; } else if(type == typeof(Tr2Camera)) { Tr2Camera t = new Tr2Camera(); t.x = System.BitConverter.ToInt32(buffer,0); t.y = System.BitConverter.ToInt32(buffer,4); t.z = System.BitConverter.ToInt32(buffer,8); t.Room = System.BitConverter.ToInt16(buffer,12); t.Unknown1 = System.BitConverter.ToUInt16(buffer,14); // correlates to Boxes[]? retval = t; } else if(type == typeof(Tr2SoundSource)) { Tr2SoundSource t =new Tr2SoundSource(); t.x = System.BitConverter.ToInt32(buffer,0);; // position of sound source t.y = System.BitConverter.ToInt32(buffer,4);; t.z = System.BitConverter.ToInt32(buffer,8);; t.SoundID = System.BitConverter.ToUInt16(buffer,12);; // internal sound index t.Flags = System.BitConverter.ToUInt16(buffer,14);; ; // 0x40, 0x80, or 0xc0 retval = t; } else if(type == typeof(Tr2BBox)) { Tr2BBox t = new Tr2BBox(); t.Zmin = buffer[0]; // sectors (* 1024 units) t.Zmax = buffer[1]; t.Xmin = buffer[2]; t.Xmax = buffer[3]; t.TrueFloor = System.BitConverter.ToInt16(buffer,4); // Y value (no scaling) t.OverlapIndex = System.BitConverter.ToInt16(buffer,6); // index into Overlaps[] retval = t; } else if(type == typeof(Tr2Item)) { Tr2Item t = new Tr2Item(); t.ObjectID = System.BitConverter.ToInt16(buffer,0); ; t.Room = System.BitConverter.ToInt16(buffer,2); ; t.x = System.BitConverter.ToInt32(buffer,4); ; t.y = System.BitConverter.ToInt32(buffer,8); ; t.z = System.BitConverter.ToInt32(buffer,12); ; t.Angle = System.BitConverter.ToInt16(buffer,16); ; t.Intensity1 = System.BitConverter.ToInt16(buffer,18); ; t.Intensity2 = System.BitConverter.ToInt16(buffer,20); ; t.Flags = System.BitConverter.ToInt16(buffer,22); ; // 0x0100 indicates "inactive" or "invisible" retval = t; } else if(type == typeof(Tr2CinematicFrame)) { Tr2CinematicFrame t = new Tr2CinematicFrame(); t.rotY = System.BitConverter.ToInt16(buffer,2); t.rotZ = System.BitConverter.ToInt16(buffer,2); t.rotZ2 = System.BitConverter.ToInt16(buffer,2); t.posZ = System.BitConverter.ToInt16(buffer,2); t.posY = System.BitConverter.ToInt16(buffer,2); t.posX = System.BitConverter.ToInt16(buffer,2); t.Unknown1 = System.BitConverter.ToInt16(buffer,2); t.rotX= System.BitConverter.ToInt16(buffer,2); } return retval; }
//param transformtree: number of transform used in animation clip //param startclipid : first animation clip index into Parser.Tr2Animation array //keyframeinfo: holds tr2 keyframes related info for an animation public static List<TRAnimationClip> CreateAnimationWithID(Tr2Moveable tr2movable, Transform[] transformtree, Parser.Tr2Level leveldata) { List<TRAnimationClip> tranimclips = new List<TRAnimationClip>(); int ntransform = transformtree.Length; int trclipoffset = tr2movable.AnimationStartOffset; Parser.TR2VersionType enginetype = leveldata.EngineVersion; //each tr anim actually information that reffer a chunk of animation frames contained in frames[] //each frame chunk contain sequential data [key] for all of the transform of this object //Now question is how many animation clips there are ? KeyFrameData keyframeinfo = CalculateAnimationKeyFrameData(trclipoffset, leveldata); bool shortanimation = false; if(keyframeinfo.numkeyframe < 15) { shortanimation = true; } int nclip = 1; if(tr2movable.ObjectID == 0) { nclip = 261; Debug.Log(" lara trclipoffset: " + trclipoffset); } //Debug.Log("ID: " + tr2movable.ObjectID + " trclipoffset: " + trclipoffset); //[0][0][0][0][0][0][0][0][0][0] for(int clipid = 0; clipid < tr2movable.NumClips; clipid++) { //if(shortanimation && clipid > 5) break; keyframeinfo = CalculateAnimationKeyFrameData(trclipoffset, leveldata); Parser.Tr2Animation tr2animation = leveldata.Animations[trclipoffset]; AnimationCurve curvRelX = null; AnimationCurve curvRelY = null; AnimationCurve curvRelZ = null; AnimationCurve[] curvRelRotX = new AnimationCurve[ntransform]; AnimationCurve[] curvRelRotY = new AnimationCurve[ntransform]; AnimationCurve[] curvRelRotZ = new AnimationCurve[ntransform]; AnimationCurve[] curvRelRotW = new AnimationCurve[ntransform]; //prepare curves for animation for(int transformId = 0; transformId < ntransform; transformId++) { //create curves curvRelRotX[transformId] = new AnimationCurve(null); curvRelRotY[transformId] = new AnimationCurve(null); curvRelRotZ[transformId] = new AnimationCurve(null); curvRelRotW[transformId] = new AnimationCurve(null); if (transformId == 0) { curvRelX = new AnimationCurve(null); curvRelY = new AnimationCurve(null); curvRelZ = new AnimationCurve(null); } } int numkeyframe = keyframeinfo.numkeyframe; for(int keyFrameCount = 0 ; keyFrameCount < numkeyframe; ++keyFrameCount) { int frameoffset = keyframeinfo.startoffset + (keyframeinfo.framesize * keyFrameCount); //extract key frme rotation int l = 9; //first angle offset in this Frame for(int transformId = 0; transformId < ntransform; transformId++) { ushort itmp = keyframeinfo.data[frameoffset + l]; ushort itmp2; double angle; float rotx = 0; float roty = 0; float rotz = 0; l = l + 1; if (enginetype == Parser.TR2VersionType.TombRaider_1) { // all angles are three-axis angle = (itmp >> 4) & 0x03ff; angle *= 360.0 / 1024.0; rotx = (float)angle; //keyframe rotx value itmp2 = (ushort)((itmp << 6) & 0x03c0); itmp = keyframeinfo.data[frameoffset + l]; // get Z rotation l = l + 1; itmp2 |= (ushort)((itmp >> 10) & 0x003f); angle = itmp2; angle *= 360.0 / 1024.0; roty = (float)angle; //keyframe roty value angle = itmp & 0x3ff; angle *= 360.0 / 1024.0; rotz= (float)angle; //keyframe rotz value } else if ((itmp & 0xc000) > 0) // TR2, TR3, TR4 - single axis of rotation { if (enginetype == Parser.TR2VersionType.TombRaider_4) { angle = itmp & 0x0fff; angle /= 4096.0; angle *= 360.0; } else { angle = itmp & 0x3ff; angle /= 1024.0; angle *= 360.0; } switch (itmp & 0xc000) { case 0x4000 : rotx = (float)angle; break; case 0x8000 : roty = (float)angle; break; case 0xc000 : rotz = (float)angle; break; } } else // TR2, TR3, TR4 - three axes { angle = (itmp >> 4) & 0x03ff; angle *= 360.0 / 1024.0; rotx = (float)angle; itmp2 = (ushort)((itmp << 6) & 0x03c0); itmp = keyframeinfo.data[frameoffset + l]; // get Z rotation l = l + 1; itmp2 |=(ushort)( (itmp >> 10) & 0x003f); angle = itmp2; angle *= 360.0 / 1024.0; roty = (float)angle; angle = itmp & 0x3ff; angle *= 360.0 / 1024.0; rotz = (float)angle; } //if(rotx > 180) //{ rotx = Mathf.Abs(360 - rotx); //} //if(rotz > 180) //{ rotz= Mathf.Abs(360 - rotz) ;; //} //if(roty > 180) //{ //roty= Mathf.Abs(360 - roty) ;; //} if (transformId == 0) { float ItemAnimX = (short)keyframeinfo.data[frameoffset + 6]; float ItemAnimY = (short)keyframeinfo.data[frameoffset + 7]; float ItemAnimZ = (short)keyframeinfo.data[frameoffset + 8]; if(numkeyframe == 1) //addition key after last key { curvRelX.AddKey(0, ItemAnimX); curvRelY.AddKey(0, -ItemAnimY); curvRelZ.AddKey(0, ItemAnimZ); curvRelX.AddKey(1 * keyframeinfo.framerate, ItemAnimX); curvRelY.AddKey(1 * keyframeinfo.framerate, -ItemAnimY); curvRelZ.AddKey(1 * keyframeinfo.framerate, ItemAnimZ); } else { int keylength = curvRelX.length; if(keylength > 0) { Keyframe kx = new Keyframe(keylength * keyframeinfo.framerate, ItemAnimX,Mathf.Infinity,Mathf.Infinity); Keyframe ky = new Keyframe(keylength * keyframeinfo.framerate, -ItemAnimY,Mathf.Infinity,Mathf.Infinity); Keyframe kz = new Keyframe(keylength * keyframeinfo.framerate, ItemAnimZ,Mathf.Infinity,Mathf.Infinity); curvRelX.AddKey(kx); curvRelY.AddKey(ky); curvRelZ.AddKey(kz); } else { curvRelX.AddKey(0, ItemAnimX); curvRelY.AddKey(0, -ItemAnimY); curvRelZ.AddKey(0, ItemAnimZ); } } } //TODO: //multiply transform with reltive rotation and translation data //relative translation of animation. allready provided? //problem: animation transform works in local space.Thats mean it does not work on root?Am I working in root? Quaternion finalrot = Quaternion.AngleAxis(roty, Vector3.up) * Quaternion.AngleAxis(rotx, Vector3.right) * Quaternion.AngleAxis(rotz, Vector3.forward); if(numkeyframe == 1) //addition key after last key { curvRelRotX[transformId].AddKey(0, finalrot.x); curvRelRotY[transformId].AddKey(0, finalrot.y); curvRelRotZ[transformId].AddKey(0, finalrot.z); curvRelRotW[transformId].AddKey(0, finalrot.w); curvRelRotX[transformId].AddKey(keyframeinfo.framerate, finalrot.x); curvRelRotY[transformId].AddKey(keyframeinfo.framerate, finalrot.y); curvRelRotZ[transformId].AddKey(keyframeinfo.framerate, finalrot.z); curvRelRotW[transformId].AddKey(keyframeinfo.framerate, finalrot.w); } else { int keylength = curvRelRotX[transformId].length; if(keylength > 0) { //FIX: set outTangent and inTangent to Mathf.Infinity Keyframe kfrotx = new Keyframe(keylength * keyframeinfo.framerate, finalrot.x,Mathf.Infinity,Mathf.Infinity); Keyframe kfroty = new Keyframe(keylength * keyframeinfo.framerate, finalrot.y,Mathf.Infinity,Mathf.Infinity); Keyframe kfrotz = new Keyframe(keylength * keyframeinfo.framerate, finalrot.z,Mathf.Infinity,Mathf.Infinity); Keyframe kfrotw = new Keyframe(keylength * keyframeinfo.framerate, finalrot.w,Mathf.Infinity,Mathf.Infinity); curvRelRotX[transformId].AddKey(kfrotx); curvRelRotY[transformId].AddKey(kfroty); curvRelRotZ[transformId].AddKey(kfrotz); curvRelRotW[transformId].AddKey(kfrotw); } else { curvRelRotX[transformId].AddKey(0, finalrot.x); curvRelRotY[transformId].AddKey(0, finalrot.y); curvRelRotZ[transformId].AddKey(0, finalrot.z); curvRelRotW[transformId].AddKey(0, finalrot.w); } } } } AnimationClip animClip = new AnimationClip(); for(int transformId = 0; transformId < ntransform; transformId++) { System.String relCurvePath = CalculateCurveRelativePath(transformtree[transformId]); //print("relCurvePath:"+relCurvePath); if(transformId !=0) { animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.x", curvRelRotX[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.y", curvRelRotY[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.z", curvRelRotZ[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.w", curvRelRotW[transformId]); } else { animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.x", curvRelRotX[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.y", curvRelRotY[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.z", curvRelRotZ[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localRotation.w", curvRelRotW[transformId]); animClip.SetCurve(relCurvePath, typeof(Transform), "localPosition.x", curvRelX); animClip.SetCurve(relCurvePath, typeof(Transform), "localPosition.y", curvRelY); animClip.SetCurve(relCurvePath, typeof(Transform), "localPosition.z", curvRelZ); } } TRAnimationClip tranimclip = new TRAnimationClip(animClip,leveldata.Animations[clipid].StateID); tranimclip.starttime = 0.0f; tranimclip.endtime = keyframeinfo.numkeyframe * keyframeinfo.framerate; tranimclip.framerate = (7.0f - tr2animation.FrameRate); tranimclips.Add(tranimclip); //goto next clip trclipoffset++; } return tranimclips; }
List <Tr2Moveable> BuildDynamicPrefabObjects(Transform container) { List <Tr2Moveable> objects = new List <Tr2Moveable>(); for (int MovableObjectIdx = 0; MovableObjectIdx < m_leveldata.Moveables.Length; MovableObjectIdx++) { Tr2Moveable tr2movable = m_leveldata.Moveables[MovableObjectIdx]; int startclipid = tr2movable.Animation; if (startclipid > m_leveldata.Animations.Length) { continue; } GameObject[] parts = CreateMultiPartObject(tr2movable); Transform[] transformtree = new Transform[parts.Length]; for (int i = 0; i < parts.Length; i++) { transformtree[i] = parts[i].transform; if (tr2movable.ObjectID != 0) { MeshCollider mf = parts[i].AddComponent <MeshCollider>(); } } //creat a place holder gameObject and make it root transform ; tr2movable.UnityObject = new GameObject("prefab type:" + MovableObjectIdx); GameObject objRoot = tr2movable.UnityObject; objRoot.transform.parent = container; objRoot.transform.Translate(Vector3.zero); objRoot.transform.Rotate(Vector3.zero); //add unity animation components tr2movable.UnityAnimation = objRoot.AddComponent <Animation>(); tr2movable.UnityAnimation.wrapMode = WrapMode.Loop; tr2movable.TransformsTree = transformtree; tr2movable.AnimationStartOffset = startclipid; tr2movable.AnimClips = new List <TRAnimationClip>(); objects.Add(tr2movable); //build mesh tree with stack ComputionModel.StackInit(); //setup parent transform Transform Parent = transformtree[0]; Parent.Translate(Vector3.zero); Parent.Rotate(Vector3.zero); Parent.parent = objRoot.transform; int animRootId = 0; for (int i = 0; i < tr2movable.NumMeshes; i++) { if (i != 0) // first mesh - position to world coordinates, set rotation { Vector3 meshPos = Vector3.zero; // tr2movable.MeshTree is a byte offset into MeshTrees[], // so we have to do a little converting here... int offsetMeshTree = (int)tr2movable.MeshTree; int Idx = (i - 1) * 4 + offsetMeshTree; meshPos.x = (float)m_leveldata.MeshTrees[Idx + 1]; meshPos.y = -(float)m_leveldata.MeshTrees[Idx + 2]; meshPos.z = (float)m_leveldata.MeshTrees[Idx + 3]; int flagVal1 = (int)((m_leveldata.MeshTrees[Idx + 0]) & 0x01); int flagVal2 = (int)((m_leveldata.MeshTrees[Idx + 0]) & 0x02); if (flagVal1 > 0 && flagVal2 > 0) { //print("poping - pushing "); animRootId = ComputionModel.Pop(); Parent = transformtree[animRootId]; animRootId = ComputionModel.Push(animRootId); } else { if (flagVal1 > 0) // pop last saved anchor { //print("poping "+i); animRootId = ComputionModel.Pop(); Parent = transformtree[animRootId]; } else { Parent = transformtree[i - 1]; } if (flagVal2 > 0) // push new anchor save { //print("pushing "+i); animRootId = ComputionModel.Push(i - 1); //prevParent = transformtree[animRootId]; } } transformtree[i].parent = Parent; transformtree[i].localPosition = meshPos * Settings.SceneScaling; //transformtree[i].localRotation = relRot; } } AICondition.SetActive(objRoot, false); } return(objects); }