public void InitGameObjects() { for (uint i = 0; i < num_subblocks; i++) { if (subblocks[i] != null) { if (subblocks[i] is MeshElement) { GameObject child = ((MeshElement)subblocks[i]).Gao; child.transform.SetParent(gao.transform); child.transform.localPosition = Vector3.zero; } else if (subblocks[i] is DeformSet) { DeformSet ds = ((DeformSet)subblocks[i]); for (int j = 0; j < ds.num_bones; j++) { Transform b = ds.bones[j]; b.transform.SetParent(gao.transform); } } else if (subblocks[i] is SpriteElement) { GameObject child = ((SpriteElement)subblocks[i]).Gao; child.transform.SetParent(gao.transform); child.transform.localPosition = Vector3.zero; } } } }
void UpdateAnimation() { if (loaded && a3d != null && channelObjects != null & subObjects != null) { if (currentFrame >= a3d.num_onlyFrames) { currentFrame %= a3d.num_onlyFrames; } // First pass: reset TRS for all sub objects for (int i = 0; i < channelParents.Length; i++) { channelParents[i] = false; } AnimOnlyFrame of = a3d.onlyFrames[a3d.start_onlyFrames + currentFrame]; // Create hierarchy for this frame for (int i = of.start_hierarchies_for_frame; i < of.start_hierarchies_for_frame + of.num_hierarchies_for_frame; i++) { AnimHierarchy h = a3d.hierarchies[i]; if (Controller.Settings.engineVersion <= Settings.EngineVersion.TT) { channelObjects[h.childChannelID].transform.SetParent(channelObjects[h.parentChannelID].transform); channelParents[h.childChannelID] = true; } else { if (!channelIDDictionary.ContainsKey(h.childChannelID) || !channelIDDictionary.ContainsKey(h.parentChannelID)) { continue; } List <int> ch_child_list = GetChannelByID(h.childChannelID); List <int> ch_parent_list = GetChannelByID(h.parentChannelID); foreach (int ch_child in ch_child_list) { foreach (int ch_parent in ch_parent_list) { channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform); channelParents[ch_child] = true; } } } //channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform); } // Final pass for (int i = 0; i < a3d.num_channels; i++) { AnimChannel ch = a3d.channels[a3d.start_channels + i]; AnimFramesKFIndex kfi = a3d.framesKFIndex[currentFrame + ch.framesKF]; AnimKeyframe kf = a3d.keyframes[kfi.kf]; AnimVector pos = a3d.vectors[kf.positionVector]; AnimQuaternion qua = a3d.quaternions[kf.quaternion]; AnimVector scl = a3d.vectors[kf.scaleVector]; AnimNumOfNTTO numOfNTTO = a3d.numOfNTTO[ch.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto = a3d.ntto[numOfNTTO.numOfNTTO]; //if (ntto.IsBoneNTTO) continue; int poNum = numOfNTTO.numOfNTTO - a3d.start_NTTO; PhysicalObject physicalObject = subObjects[i][poNum]; Vector3 vector = pos.vector; Quaternion quaternion = qua.quaternion; Vector3 scale = scl.vector; int framesSinceKF = (int)currentFrame - (int)kf.frame; AnimKeyframe nextKF = null; int framesDifference; float interpolation; if (kf.IsEndKeyframe) { AnimFramesKFIndex next_kfi = a3d.framesKFIndex[0 + ch.framesKF]; nextKF = a3d.keyframes[next_kfi.kf]; framesDifference = a3d.num_onlyFrames - 1 + (int)nextKF.frame - (int)kf.frame; if (framesDifference == 0) { interpolation = 0; } else { //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor); interpolation = framesSinceKF / (float)framesDifference; } } else { nextKF = a3d.keyframes[kfi.kf + 1]; framesDifference = (int)nextKF.frame - (int)kf.frame; //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor); interpolation = framesSinceKF / (float)framesDifference; } //print(interpolation); //print(a3d.vectors.Length + " - " + nextKF.positionVector); AnimVector pos2 = a3d.vectors[nextKF.positionVector]; AnimQuaternion qua2 = a3d.quaternions[nextKF.quaternion]; AnimVector scl2 = a3d.vectors[nextKF.scaleVector]; vector = Vector3.Lerp(pos.vector, pos2.vector, interpolation); quaternion = Quaternion.Lerp(qua.quaternion, qua2.quaternion, interpolation); scale = Vector3.Lerp(scl.vector, scl2.vector, interpolation); float positionMultiplier = Mathf.Lerp(kf.positionMultiplier, nextKF.positionMultiplier, interpolation); if (poNum != currentActivePO[i]) { if (currentActivePO[i] == -2 && fullMorphPOs != null && fullMorphPOs[i] != null) { foreach (PhysicalObject morphPO in fullMorphPOs[i].Values) { if (morphPO.Gao.activeSelf) { morphPO.Gao.SetActive(false); } } } if (currentActivePO[i] >= 0 && subObjects[i][currentActivePO[i]] != null) { subObjects[i][currentActivePO[i]].Gao.SetActive(false); } currentActivePO[i] = poNum; if (physicalObject != null) { physicalObject.Gao.SetActive(true); } } if (!channelParents[i]) { channelObjects[i].transform.SetParent(perso.gameObject.transform); } channelObjects[i].transform.localPosition = vector * positionMultiplier; channelObjects[i].transform.localRotation = quaternion; channelObjects[i].transform.localScale = scale; if (physicalObject != null && a3d.num_morphData > 0 && morphDataArray != null && i < morphDataArray.GetLength(0) && currentFrame < morphDataArray.GetLength(1)) { AnimMorphData morphData = morphDataArray[i, currentFrame]; if (morphData != null && morphData.morphProgress != 0 && morphData.morphProgress != 100) { PhysicalObject morphToPO = perso.Perso3dData.ObjectList.entries[morphData.objectIndexTo].po; Vector3[] morphVerts = null; for (int j = 0; j < physicalObject.visualSet.Length; j++) { IGeometricObject obj = physicalObject.visualSet[j].obj; if (obj == null || obj as MeshObject == null) { continue; } MeshObject fromM = obj as MeshObject; MeshObject toM = morphToPO.visualSet[j].obj as MeshObject; if (toM == null) { continue; } if (fromM.vertices.Length != toM.vertices.Length) { // For those special cases like the mistake in the Clark cinematic continue; } int numVertices = fromM.vertices.Length; morphVerts = new Vector3[numVertices]; for (int vi = 0; vi < numVertices; vi++) { morphVerts[vi] = Vector3.Lerp(fromM.vertices[vi], toM.vertices[vi], morphData.morphProgressFloat); } for (int k = 0; k < fromM.num_subblocks; k++) { if (fromM.subblocks[k] == null || fromM.subblock_types[k] != 1) { continue; } MeshElement el = (MeshElement)fromM.subblocks[k]; if (el != null) { el.UpdateMeshVertices(morphVerts); } } } } else if (morphData != null && morphData.morphProgress == 100) { physicalObject.Gao.SetActive(false); PhysicalObject c = fullMorphPOs[i][morphData.objectIndexTo]; c.Gao.transform.localScale = c.scaleMultiplier.HasValue ? c.scaleMultiplier.Value : Vector3.one; c.Gao.transform.localPosition = Vector3.zero; c.Gao.transform.localRotation = Quaternion.identity; c.Gao.SetActive(true); currentActivePO[i] = -2; } else { for (int j = 0; j < physicalObject.visualSet.Length; j++) { IGeometricObject obj = physicalObject.visualSet[j].obj; if (obj == null || obj as MeshObject == null) { continue; } MeshObject fromM = obj as MeshObject; for (int k = 0; k < fromM.num_subblocks; k++) { if (fromM.subblocks[k] == null || fromM.subblock_types[k] != 1) { continue; } MeshElement el = (MeshElement)fromM.subblocks[k]; if (el != null) { el.ResetVertices(); } } } } } } if (hasBones) { for (int i = 0; i < a3d.num_channels; i++) { AnimChannel ch = a3d.channels[a3d.start_channels + i]; Transform baseChannelTransform = channelObjects[i].transform; Vector3 invertedScale = new Vector3(1f / baseChannelTransform.localScale.x, 1f / baseChannelTransform.localScale.y, 1f / baseChannelTransform.localScale.z); AnimNumOfNTTO numOfNTTO = a3d.numOfNTTO[ch.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto = a3d.ntto[numOfNTTO.numOfNTTO]; PhysicalObject physicalObject = subObjects[i][numOfNTTO.numOfNTTO - a3d.start_NTTO]; if (physicalObject == null) { continue; } DeformSet bones = physicalObject.Bones; // Deformations if (bones != null) { for (int j = 0; j < a3d.num_deformations; j++) { AnimDeformation d = a3d.deformations[a3d.start_deformations + j]; if (d.channel < ch.id) { continue; } if (d.channel > ch.id) { break; } if (!channelIDDictionary.ContainsKey(d.linkChannel)) { continue; } List <int> ind_linkChannel_list = GetChannelByID(d.linkChannel); foreach (int ind_linkChannel in ind_linkChannel_list) { AnimChannel ch_link = a3d.channels[a3d.start_channels + ind_linkChannel]; AnimNumOfNTTO numOfNTTO_link = a3d.numOfNTTO[ch_link.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto_link = a3d.ntto[numOfNTTO_link.numOfNTTO]; PhysicalObject physicalObject_link = subObjects[ind_linkChannel][numOfNTTO_link.numOfNTTO - a3d.start_NTTO]; if (physicalObject_link == null) { continue; } if (bones == null || bones.bones.Length <= d.bone + 1) { continue; } DeformBone bone = bones.r3bones[d.bone + 1]; if (bone != null) { Transform channelTransform = channelObjects[ind_linkChannel].transform; bone.UnityBone.transform.SetParent(channelTransform); bone.UnityBone.localPosition = Vector3.zero; bone.UnityBone.localRotation = Quaternion.identity; bone.UnityBone.localScale = Vector3.one; /*bone.UnityBone.position = channelTransform.position; * bone.UnityBone.rotation = channelTransform.rotation; * //bone.UnityBone.localScale = Vector3.one; * bone.UnityBone.localScale = channelTransform.localScale;*/ } } } } } } //this.currentFrame = (currentFrame + 1) % a3d.num_onlyFrames; } }
public static GeometricObject Read(Reader reader, Pointer offset) { MapLoader l = MapLoader.Loader; //l.print("Geometric Object: " + offset); GeometricObject m = new GeometricObject(offset); if (Settings.s.game == Settings.Game.LargoWinch) { uint flags = reader.ReadUInt32(); m.num_vertices = reader.ReadUInt16(); m.num_elements = reader.ReadUInt16(); m.off_element_types = Pointer.Read(reader); m.off_elements = Pointer.Read(reader); m.off_vertices = Pointer.Read(reader); m.off_normals = Pointer.Read(reader); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); m.lookAtMode = reader.ReadUInt32(); } else if (Settings.s.game == Settings.Game.R2Revolution) { m.off_element_types = Pointer.Read(reader); m.off_elements = Pointer.Read(reader); uint flags = reader.ReadUInt32(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); m.off_mapping = Pointer.Read(reader); m.num_vertices = reader.ReadUInt16(); m.num_elements = reader.ReadUInt16(); m.off_vertices = Pointer.Read(reader); m.off_normals = Pointer.Read(reader); m.lookAtMode = flags & 3; } else { if (Settings.s.engineVersion <= Settings.EngineVersion.Montreal) { m.num_vertices = (ushort)reader.ReadUInt32(); } m.off_vertices = Pointer.Read(reader); m.off_normals = Pointer.Read(reader); if (Settings.s.engineVersion < Settings.EngineVersion.R3) { m.off_materials = Pointer.Read(reader); } else { m.off_blendWeights = Pointer.Read(reader); } if (Settings.s.mode != Settings.Mode.RaymanArenaGC && Settings.s.mode != Settings.Mode.RaymanArenaGCDemo && Settings.s.game != Settings.Game.RM && Settings.s.mode != Settings.Mode.DonaldDuckPKGC && !(Settings.s.platform == Settings.Platform.PS2 && Settings.s.engineVersion == Settings.EngineVersion.R3)) { reader.ReadInt32(); } if (Settings.s.engineVersion <= Settings.EngineVersion.Montreal) { m.num_elements = (ushort)reader.ReadUInt32(); } m.off_element_types = Pointer.Read(reader); m.off_elements = Pointer.Read(reader); reader.ReadInt32(); reader.ReadInt32(); if (Settings.s.engineVersion == Settings.EngineVersion.R2) { reader.ReadInt32(); reader.ReadInt32(); } if (Settings.s.game == Settings.Game.Dinosaur) { reader.ReadInt32(); reader.ReadInt32(); reader.ReadInt32(); } if (Settings.s.engineVersion > Settings.EngineVersion.Montreal) { m.lookAtMode = reader.ReadUInt32(); //if (m.lookAtMode != 0) l.print(m.lookAtMode); m.num_vertices = reader.ReadUInt16(); m.num_elements = reader.ReadUInt16(); reader.ReadInt32(); reader.ReadSingle(); // bounding volume radius reader.ReadSingle(); // x reader.ReadSingle(); // z reader.ReadSingle(); // y reader.ReadInt32(); if (Settings.s.engineVersion == Settings.EngineVersion.R3) { reader.ReadInt32(); if (!(Settings.s.platform == Settings.Platform.PS2 && (Settings.s.game == Settings.Game.RM || Settings.s.game == Settings.Game.RA))) { reader.ReadInt16(); if (Settings.s.platform == Settings.Platform.PS2) { reader.ReadInt16(); reader.ReadUInt32(); } } } } else { reader.ReadInt32(); reader.ReadInt32(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); } } m.name = "Mesh @ " + offset; if (Settings.s.hasNames) { m.name = reader.ReadString(0x32); } if (Settings.s.platform == Settings.Platform.PS2 && Settings.s.engineVersion >= Settings.EngineVersion.R3) { reader.Align(0x4); reader.ReadUInt32(); reader.ReadUInt32(); m.optimizedObject = new Pointer <PS2OptimizedSDCStructure>(reader, resolve: false); reader.ReadUInt32(); reader.ReadUInt32(); if (Settings.s.game == Settings.Game.R3) { m.ps2IsSinus = reader.ReadUInt32(); } } // Vertices Pointer.DoAt(ref reader, m.off_vertices, () => { m.vertices = new Vector3[m.num_vertices]; for (int i = 0; i < m.num_vertices; i++) { float x = reader.ReadSingle(); float z = reader.ReadSingle(); float y = reader.ReadSingle(); m.vertices[i] = new Vector3(x, y, z); } }); // Normals Pointer.DoAt(ref reader, m.off_normals, () => { m.normals = new Vector3[m.num_vertices]; for (int i = 0; i < m.num_vertices; i++) { float x = reader.ReadSingle(); float z = reader.ReadSingle(); float y = reader.ReadSingle(); m.normals[i] = new Vector3(x, y, z); } }); Pointer.DoAt(ref reader, m.off_blendWeights, () => { m.blendWeights = new float[4][]; /*reader.ReadUInt32(); // 0 * R3Pointer off_blendWeightsStart = R3Pointer.Read(reader); * R3Pointer.Goto(ref reader, off_blendWeightsStart);*/ for (int i = 0; i < 4; i++) { Pointer off_blendWeights = Pointer.Read(reader); Pointer.DoAt(ref reader, off_blendWeights, () => { m.blendWeights[i] = new float[m.num_vertices]; for (int j = 0; j < m.num_vertices; j++) { m.blendWeights[i][j] = reader.ReadSingle(); } }); } reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); }); Pointer.DoAt(ref reader, m.off_mapping, () => { // Revolution only reader.ReadUInt32(); Pointer.Read(reader); Pointer off_mappingBlocks = Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); ushort num_mappingBlocks = reader.ReadUInt16(); reader.ReadUInt16(); Pointer.DoAt(ref reader, off_mappingBlocks, () => { m.mapping = new int[num_mappingBlocks][]; for (int i = 0; i < num_mappingBlocks; i++) { Pointer off_mapping = Pointer.Read(reader); Pointer.DoAt(ref reader, off_mapping, () => { m.mapping[i] = new int[m.num_vertices]; for (int j = 0; j < m.num_vertices; j++) { m.mapping[i][j] = reader.ReadUInt16(); if (m.mapping[i][j] >= m.num_vertices) { l.print(m.offset); } } }); } }); }); // Read element types & initialize arrays Pointer.Goto(ref reader, m.off_element_types); m.element_types = new ushort[m.num_elements]; m.elements = new IGeometricObjectElement[m.num_elements]; for (uint i = 0; i < m.num_elements; i++) { m.element_types[i] = reader.ReadUInt16(); } // Process elements for (uint i = 0; i < m.num_elements; i++) { Pointer.Goto(ref reader, m.off_elements + (i * 4)); Pointer block_offset = Pointer.Read(reader); Pointer.Goto(ref reader, block_offset); switch (m.element_types[i]) { case 1: // Material m.elements[i] = GeometricObjectElementTriangles.Read(reader, block_offset, m); break; case 3: // Sprite m.elements[i] = GeometricObjectElementSprites.Read(reader, block_offset, m); break; case 13: case 15: m.bones = DeformSet.Read(reader, block_offset, m); m.elements[i] = m.bones; break; default: m.elements[i] = null; /*1 = indexedtriangles * 2 = facemap * 3 = sprite * 4 = TMesh * 5 = points * 6 = lines * 7 = spheres * 8 = alignedboxes * 9 = cones * 13 = deformationsetinfo*/ l.print("Unknown geometric element type " + m.element_types[i] + " at offset " + block_offset); break; } } ReadMeshFromATO(reader, m); if (Settings.s.platform == Settings.Platform.PS2 && Settings.s.engineVersion == Settings.EngineVersion.R3) { m.optimizedObject?.Resolve(reader, onPreRead: opt => opt.isSinus = m.ps2IsSinus); m.ReadMeshFromSDC(); } m.InitGameObject(); return(m); }
public static MeshObject Read(EndianBinaryReader reader, PhysicalObject po, Pointer offset) { MapLoader l = MapLoader.Loader; MeshObject m = new MeshObject(po, offset); Pointer off_modelstart = Pointer.Read(reader); m.off_modelstart = off_modelstart; Pointer.Goto(ref reader, off_modelstart); m.off_vertices = Pointer.Read(reader); m.off_normals = Pointer.Read(reader); m.off_blendWeights = Pointer.Read(reader); if (l.mode == MapLoader.Mode.Rayman3PC || l.mode == MapLoader.Mode.RaymanArenaPC || l.mode == MapLoader.Mode.Rayman3GC || l.mode == MapLoader.Mode.Rayman2PC) { reader.ReadInt32(); } m.off_subblock_types = Pointer.Read(reader); m.off_subblocks = Pointer.Read(reader); reader.ReadInt32(); reader.ReadInt32(); reader.ReadInt32(); if (l.mode == MapLoader.Mode.Rayman2PC) { reader.ReadInt32(); reader.ReadInt32(); } m.num_vertices = reader.ReadUInt16(); m.num_subblocks = reader.ReadUInt16(); reader.ReadInt32(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadInt32(); if (l.mode != MapLoader.Mode.Rayman2PC) { reader.ReadInt32(); reader.ReadInt16(); } m.name = "Mesh"; if (l.mode == MapLoader.Mode.Rayman3GC) { m.name = new string(reader.ReadChars(0x32)).TrimEnd('\0'); } // Vertices Pointer off_current = Pointer.Goto(ref reader, m.off_vertices); //print("Loading vertices at " + String.Format("0x{0:X}", fs.Position) + " | Amount: " + num_vertices); m.vertices = new Vector3[m.num_vertices]; for (int i = 0; i < m.num_vertices; i++) { float x = reader.ReadSingle(); float z = reader.ReadSingle(); float y = reader.ReadSingle(); m.vertices[i] = new Vector3(x, y, z); } // Normals Pointer.Goto(ref reader, m.off_normals); m.normals = new Vector3[m.num_vertices]; for (int i = 0; i < m.num_vertices; i++) { float x = reader.ReadSingle(); float z = reader.ReadSingle(); float y = reader.ReadSingle(); m.normals[i] = new Vector3(x, y, z); } if (m.off_blendWeights != null) { Pointer.Goto(ref reader, m.off_blendWeights); /*reader.ReadUInt32(); // 0 * R3Pointer off_blendWeightsStart = R3Pointer.Read(reader); * R3Pointer.Goto(ref reader, off_blendWeightsStart);*/ reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); m.blendWeights = new float[m.num_vertices]; for (int i = 0; i < m.num_vertices; i++) { m.blendWeights[i] = reader.ReadSingle(); } } // Read subblock types & initialize arrays Pointer.Goto(ref reader, m.off_subblock_types); m.subblock_types = new ushort[m.num_subblocks]; m.subblocks = new IGeometricElement[m.num_subblocks]; for (uint i = 0; i < m.num_subblocks; i++) { m.subblock_types[i] = reader.ReadUInt16(); } m.gao = new GameObject(m.name); m.gao.tag = "Visual"; // Process blocks for (uint i = 0; i < m.num_subblocks; i++) { Pointer.Goto(ref reader, m.off_subblocks + (i * 4)); Pointer block_offset = Pointer.Read(reader); Pointer.Goto(ref reader, block_offset); switch (m.subblock_types[i]) { case 1: // Material m.subblocks[i] = MeshElement.Read(reader, block_offset, m); break; case 3: // Sprite m.subblocks[i] = SpriteElement.Read(reader, block_offset, m); break; case 13: m.bones = DeformSet.Read(reader, block_offset, m); m.subblocks[i] = m.bones; break; default: m.subblocks[i] = null; /*1 = indexedtriangles * 2 = facemap * 3 = sprite * 4 = TMesh * 5 = points * 6 = lines * 7 = spheres * 8 = alignedboxes * 9 = cones * 13 = deformationsetinfo*/ l.print("Unknown geometric element type " + m.subblock_types[i] + " at offset " + block_offset); break; } } m.InitGameObjects(); return(m); }
void UpdateFrame(uint currentFrame) { if (loaded && a3d != null && channelObjects != null & subObjects != null) { // First pass: reset TRS for all sub objects for (int i = 0; i < channelObjects.Length; i++) { GameObject c = channelObjects[i]; if (c != null) { c.transform.SetParent(perso.Gao.transform); c.transform.localPosition = Vector3.zero; c.transform.localEulerAngles = Vector3.zero; c.transform.localScale = Vector3.one; // prevent float precision errors after a long time, lol } for (int j = 0; j < subObjects[i].Length; j++) { if (subObjects[i][j] == null) { continue; } subObjects[i][j].Gao.transform.parent = c.transform; subObjects[i][j].Gao.transform.localPosition = Vector3.zero; subObjects[i][j].Gao.transform.localEulerAngles = Vector3.zero; subObjects[i][j].Gao.transform.localScale = subObjects[i][j].scaleMultiplier.HasValue ? subObjects[i][j].scaleMultiplier.Value : Vector3.one; subObjects[i][j].Gao.SetActive(false); } } AnimOnlyFrame of = a3d.onlyFrames[a3d.start_onlyFrames + currentFrame]; // Create hierarchy for this frame for (int i = of.start_hierarchies_for_frame; i < of.start_hierarchies_for_frame + of.num_hierarchies_for_frame; i++) { AnimHierarchy h = a3d.hierarchies[i]; if (!channelIDDictionary.ContainsKey(h.childChannelID) || !channelIDDictionary.ContainsKey(h.parentChannelID)) { continue; } List <int> ch_child_list = GetChannelByID(h.childChannelID); List <int> ch_parent_list = GetChannelByID(h.parentChannelID); foreach (int ch_child in ch_child_list) { foreach (int ch_parent in ch_parent_list) { channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform); } } //channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform); } // Final pass for (int i = 0; i < a3d.num_channels; i++) { AnimChannel ch = a3d.channels[a3d.start_channels + i]; AnimFramesKFIndex kfi = a3d.framesKFIndex[currentFrame + ch.framesKF]; AnimKeyframe kf = a3d.keyframes[kfi.kf]; AnimVector pos = a3d.vectors[kf.positionVector]; AnimQuaternion qua = a3d.quaternions[kf.quaternion]; AnimVector scl = a3d.vectors[kf.scaleVector]; AnimNumOfNTTO numOfNTTO = a3d.numOfNTTO[ch.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto = a3d.ntto[numOfNTTO.numOfNTTO]; //if (ntto.IsBoneNTTO) continue; PhysicalObject physicalObject = subObjects[i][numOfNTTO.numOfNTTO - a3d.start_NTTO]; Vector3 vector = pos.vector; Quaternion quaternion = qua.quaternion; Vector3 scale = scl.vector; int framesSinceKF = (int)currentFrame - (int)kf.frame; AnimKeyframe nextKF = null; int framesDifference; float interpolation; if (kf.IsEndKeyframe) { AnimFramesKFIndex next_kfi = a3d.framesKFIndex[0 + ch.framesKF]; nextKF = a3d.keyframes[next_kfi.kf]; framesDifference = a3d.num_onlyFrames - 1 + (int)nextKF.frame - (int)kf.frame; if (framesDifference == 0) { interpolation = 0; } else { //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor); interpolation = framesSinceKF / (float)framesDifference; } } else { nextKF = a3d.keyframes[kfi.kf + 1]; framesDifference = (int)nextKF.frame - (int)kf.frame; //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor); interpolation = framesSinceKF / (float)framesDifference; } //print(interpolation); AnimVector pos2 = a3d.vectors[nextKF.positionVector]; AnimQuaternion qua2 = a3d.quaternions[nextKF.quaternion]; AnimVector scl2 = a3d.vectors[nextKF.scaleVector]; vector = Vector3.Lerp(pos.vector, pos2.vector, interpolation); quaternion = Quaternion.Lerp(qua.quaternion, qua2.quaternion, interpolation); scale = Vector3.Lerp(scl.vector, scl2.vector, interpolation); float positionMultiplier = Mathf.Lerp(kf.positionMultiplier, nextKF.positionMultiplier, interpolation); if (physicalObject != null) { physicalObject.Gao.SetActive(true); } channelObjects[i].transform.localPosition = vector * positionMultiplier; channelObjects[i].transform.localRotation = quaternion; channelObjects[i].transform.localScale = scale; } for (int i = 0; i < a3d.num_channels; i++) { AnimChannel ch = a3d.channels[a3d.start_channels + i]; Transform baseChannelTransform = channelObjects[i].transform; Vector3 invertedScale = new Vector3(1f / baseChannelTransform.localScale.x, 1f / baseChannelTransform.localScale.y, 1f / baseChannelTransform.localScale.z); AnimNumOfNTTO numOfNTTO = a3d.numOfNTTO[ch.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto = a3d.ntto[numOfNTTO.numOfNTTO]; PhysicalObject physicalObject = subObjects[i][numOfNTTO.numOfNTTO - a3d.start_NTTO]; if (physicalObject == null) { continue; } DeformSet bones = physicalObject.Bones; // Deformations if (bones != null) { for (int j = 0; j < a3d.num_deformations; j++) { AnimDeformation d = a3d.deformations[a3d.start_deformations + j]; if (d.channel < ch.id) { continue; } if (d.channel > ch.id) { break; } if (!channelIDDictionary.ContainsKey(d.linkChannel)) { continue; } List <int> ind_linkChannel_list = GetChannelByID(d.linkChannel); foreach (int ind_linkChannel in ind_linkChannel_list) { AnimChannel ch_link = a3d.channels[a3d.start_channels + ind_linkChannel]; AnimNumOfNTTO numOfNTTO_link = a3d.numOfNTTO[ch_link.numOfNTTO + of.numOfNTTO]; AnimNTTO ntto_link = a3d.ntto[numOfNTTO_link.numOfNTTO]; PhysicalObject physicalObject_link = subObjects[ind_linkChannel][numOfNTTO_link.numOfNTTO - a3d.start_NTTO]; if (physicalObject_link == null) { continue; } if (bones == null || bones.bones.Length <= d.bone + 1) { continue; } DeformBone bone = bones.r3bones[d.bone + 1]; if (bone != null) { Transform channelTransform = channelObjects[ind_linkChannel].transform; bone.UnityBone.transform.SetParent(channelTransform); bone.UnityBone.localPosition = Vector3.zero; bone.UnityBone.localRotation = Quaternion.identity; bone.UnityBone.localScale = Vector3.one; /*bone.UnityBone.position = channelTransform.position; * bone.UnityBone.rotation = channelTransform.rotation; * //bone.UnityBone.localScale = Vector3.one; * bone.UnityBone.localScale = channelTransform.localScale;*/ } } } } } this.currentFrame = (currentFrame + 1) % a3d.num_onlyFrames; } /*else if (loaded && (a3d == null || !playAnimation) && perso.physical_objects != null) { * for (int i = 0; i < perso.physical_objects.Length; i++) { * if (perso.physical_objects[i] != null) { * GameObject poGao = perso.physical_objects[i].Gao; * if (poGao != null && !poGao.activeSelf) { * poGao.transform.SetParent(perso.Gao.transform); * poGao.transform.localPosition = Vector3.zero; * poGao.transform.localEulerAngles = Vector3.zero; * poGao.SetActive(true); * } * } * } * }*/ }