private static void CalcNodeBoundingBox(RSM.Node node, Mat4 _matrix) { var v = new Vector3(); var box = node.box; var nodes = node.model.nodes; var vertices = node.vertices; float x, y, z; //find position node.matrix = _matrix.Clone(); Mat4.Translate(node.matrix, node.matrix, node.pos); //dynamic or static model if (node.rotKeyframes.Count == 0) { Mat4.Rotate(node.matrix, node.matrix, node.rotAngle, node.rotAxis); } Mat4.Scale(node.matrix, node.matrix, node.scale); Mat4 matrix = node.matrix.Clone(); if (!node.isOnly) { Mat4.Translate(matrix, matrix, node.offset); } Mat4.Multiply(matrix, matrix, Mat4.FromMat3(node.mat3, null)); for (int i = 0, count = vertices.Count; i < count; i++) { x = vertices[i][0]; y = vertices[i][1]; z = vertices[i][2]; v[0] = matrix[0] * x + matrix[4] * y + matrix[8] * z + matrix[12]; v[1] = matrix[1] * x + matrix[5] * y + matrix[9] * z + matrix[13]; v[2] = matrix[2] * x + matrix[6] * y + matrix[10] * z + matrix[14]; for (int j = 0; j < 3; j++) { box.min[j] = Math.Min(v[j], box.min[j]); box.max[j] = Math.Max(v[j], box.max[j]); } } for (int i = 0; i < 3; i++) { box.offset[i] = (box.max[i] + box.min[i]) / 2.0f; box.range[i] = (box.max[i] - box.min[i]) / 2.0f; box.center[i] = box.min[i] + box.range[i]; } for (int i = 0, count = nodes.Length; i < count; i++) { if (string.Equals(nodes[i].parentName, node.name) && !string.Equals(node.name, node.parentName)) { nodes[i].parent = node; node.children.Add(nodes[i]); CalcNodeBoundingBox(nodes[i], node.matrix); } } }
private static RSM.Node LoadNode(RSM rsm, BinaryReader data, double version) { RSM.Node node = new RSM.Node(); node.model = rsm; node.isOnly = rsm.nodes.Length == 1; node.name = data.ReadBinaryString(40); node.parentName = data.ReadBinaryString(40); //read textures int textureCount = data.ReadLong(); node.textures = new long[textureCount]; for (int i = 0; i < textureCount; i++) { node.textures[i] = data.ReadLong(); } //read options node.mat3 = new Vector3[] { new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat()), new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat()), new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat()) }; node.offset = new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat()); node.pos = new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat()); node.rotAngle = data.ReadFloat(); node.rotAxis = new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat()); node.scale = new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat()); //read vertices int verticeCount = data.ReadLong(); node.vertices = new List <Vector3>(); for (int i = 0; i < verticeCount; i++) { node.vertices.Add(new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat())); } //read textures vertices int tverticeCount = data.ReadLong(); node.tVertices = new float[tverticeCount * 6]; for (int i = 0; i < tverticeCount; i++) { if (version >= 1.2) { node.tVertices[(i * 6) + 0] = data.ReadUByte() / 255f; node.tVertices[(i * 6) + 1] = data.ReadUByte() / 255f; node.tVertices[(i * 6) + 2] = data.ReadUByte() / 255f; node.tVertices[(i * 6) + 3] = data.ReadUByte() / 255f; } node.tVertices[(i * 6) + 4] = data.ReadFloat() * 0.98f + 0.01f; node.tVertices[(i * 6) + 5] = data.ReadFloat() * 0.98f + 0.01f; } //read faces int faceCount = data.ReadLong(); node.faces = new RSM.Face[faceCount]; for (int i = 0; i < faceCount; i++) { node.faces[i] = new RSM.Face() { vertidx = new Vector3Int(data.ReadUShort(), data.ReadUShort(), data.ReadUShort()), tvertidx = new Vector3Int(data.ReadUShort(), data.ReadUShort(), data.ReadUShort()), texid = data.ReadUShort(), padding = data.ReadUShort(), twoSided = data.ReadLong(), smoothGroup = version >= 1.2 ? data.ReadLong() : 0 }; } //read position keyframes if (version >= 1.5) { int pkfCount = data.ReadLong(); for (int i = 0; i < pkfCount; i++) { node.posKeyframes.Add(data.ReadLong(), new Vector3(data.ReadFloat(), data.ReadFloat(), data.ReadFloat())); } } //read rotation keyframes int rkfCount = data.ReadLong(); for (int i = 0; i < rkfCount; i++) { int time = data.ReadLong(); Quaternion quat = new Quaternion(data.ReadFloat(), data.ReadFloat(), data.ReadFloat(), data.ReadFloat()); if (!node.rotKeyframes.ContainsKey(time)) { //some models have multiple keyframes with the //same timestamp, here we just keep the first one //and throw out the rest. node.rotKeyframes.Add(time, quat); } } node.box = new RSM.Box(); return(node); }
public void BuildMeshes() { GameObject parent = new GameObject("_Models"); parent.transform.parent = MapRenderer.mapParent.transform; Dictionary <int, AnimProperties> anims = new Dictionary <int, AnimProperties>(); int nodeId = 0; foreach (RSM.CompiledModel model in models) { GameObject modelObj = new GameObject(model.rsm.name); modelObj.transform.parent = parent.transform; foreach (var nodeData in model.nodesData) { foreach (var meshesByTexture in nodeData) { long textureId = meshesByTexture.Key; RSM.NodeMeshData meshData = meshesByTexture.Value; RSM.Node node = meshData.node; if (meshesByTexture.Value.vertices.Count == 0) { continue; } for (int i = 0; i < meshData.vertices.Count; i += 3) { meshData.triangles.AddRange(new int[] { i + 0, i + 1, i + 2 }); } //create node unity mesh Mesh mesh = new Mesh(); mesh.vertices = meshData.vertices.ToArray(); mesh.triangles = meshData.triangles.ToArray(); //mesh.normals = meshData.normals.ToArray(); mesh.uv = meshData.uv.ToArray(); GameObject nodeObj = new GameObject(node.name); nodeObj.transform.parent = modelObj.transform; string textureFile = model.rsm.textures[textureId]; var mf = nodeObj.AddComponent <MeshFilter>(); mf.mesh = mesh; var mr = nodeObj.AddComponent <MeshRenderer>(); if (meshData.twoSided) { mr.material = material2s; if (textureFile.EndsWith("tga")) { mr.material.shader = Resources.Load("2SidedAlpha") as Shader; mr.material.renderQueue += 1; } } else { mr.material = material; if (textureFile.EndsWith("tga")) { mr.material.shader = Resources.Load("ModelShaderAlpha") as Shader; mr.material.renderQueue += 1; } } mr.material.mainTexture = FileManager.Load("data/texture/" + textureFile) as Texture2D; if (model.rsm.shadeType == RSM.SHADING.SMOOTH) { NormalSolver.RecalculateNormals(mf.mesh, 60); } else { mf.mesh.RecalculateNormals(); } var matrix = node.GetPositionMatrix(); nodeObj.transform.position = matrix.ExtractPosition(); var rotation = matrix.ExtractRotation(); nodeObj.transform.rotation = rotation; nodeObj.transform.localScale = matrix.ExtractScale(); var properties = nodeObj.AddComponent <NodeProperties>(); properties.nodeId = nodeId; properties.mainName = model.rsm.mainNode.name; properties.parentName = node.parentName; if (node.posKeyframes.Count > 0 || node.rotKeyframes.Count > 0) { nodeObj.AddComponent <NodeAnimation>().nodeId = nodeId; anims.Add(nodeId, new AnimProperties() { posKeyframes = node.posKeyframes, rotKeyframes = node.rotKeyframes, animLen = model.rsm.animLen, baseRotation = rotation, isChild = properties.isChild }); } nodeId++; } } modelObj.SetActive(false); //instantiate model for (int i = 0; i < model.rsm.instances.Count; i++) { GameObject instanceObj; if (i == model.rsm.instances.Count - 1) { //last instance instanceObj = modelObj; } else { instanceObj = UnityEngine.Object.Instantiate(modelObj); } instanceObj.transform.parent = parent.transform; instanceObj.name += "[" + i + "]"; RSW.ModelDescriptor descriptor = model.rsm.instances[i]; instanceObj.transform.Rotate(Vector3.forward, -descriptor.rotation[2]); instanceObj.transform.Rotate(Vector3.right, -descriptor.rotation[0]); instanceObj.transform.Rotate(Vector3.up, descriptor.rotation[1]); Vector3 scale = new Vector3(descriptor.scale[0], -descriptor.scale[1], descriptor.scale[2]); instanceObj.transform.localScale = scale; //avoid z fighting between models float xRandom = UnityEngine.Random.Range(-0.002f, 0.002f); float yRandom = UnityEngine.Random.Range(-0.002f, 0.002f); float zRandom = UnityEngine.Random.Range(-0.002f, 0.002f); Vector3 position = new Vector3(descriptor.position[0] + xRandom, descriptor.position[1] + yRandom, descriptor.position[2] + zRandom); position.x += MapRenderer.width; position.y *= -1; position.z += MapRenderer.height; instanceObj.transform.position = position; //setup hierarchy var propertiesComponents = instanceObj.GetComponentsInChildren <NodeProperties>(); foreach (var properties in propertiesComponents) { if (properties.isChild) { var nodeParent = instanceObj.transform.FindRecursive(properties.parentName); properties.transform.parent = nodeParent; } } //setup animations var animComponents = instanceObj.GetComponentsInChildren <NodeAnimation>(); foreach (var animComponent in animComponents) { var properties = anims[animComponent.nodeId]; animComponent.Initialize(properties); } instanceObj.SetActive(true); } } anims.Clear(); }