public override GameObject LoadObject(string path, Mission mission) { GameObject rootObject = LoadCachedObject(path); if (rootObject == null) { rootObject = new GameObject(path); } else { return(rootObject); } Stream fs; try { fs = GameAPI.instance.fileSystem.GetStreamFromPath(path); } catch (Exception ex) { GameObject.DestroyImmediate(rootObject); Debug.LogWarning(ex.ToString()); return(null); } using (BinaryReader reader = new BinaryReader(fs)) { var modelLoader = new MafiaFormats.Reader4DS(); var model = modelLoader.loadModel(reader); fs.Close(); if (model == null) { return(null); } var meshId = 0; var children = new List <KeyValuePair <int, Transform> >(); foreach (var mafiaMesh in model.meshes) { var child = new GameObject(mafiaMesh.meshName, typeof(MeshFilter)); var meshFilter = child.GetComponent <MeshFilter>(); StoreReference(mission, child.name, child); children.Add(new KeyValuePair <int, Transform>(mafiaMesh.parentID, child.transform)); if (mafiaMesh.meshType == MafiaFormats.MeshType.Joint) { var bone = child.AddComponent <Bone>(); bone.data = mafiaMesh.joint; continue; } else if (mafiaMesh.meshType == MafiaFormats.MeshType.Collision) { Material[] temp; child.AddComponent <MeshCollider>().sharedMesh = GenerateMesh(mafiaMesh, child, mafiaMesh.standard.lods[0], model, out temp); continue; } else if (mafiaMesh.meshType == MafiaFormats.MeshType.Sector) { // NOTE: Set up dummy data for this sector. MafiaFormats.Scene2BINLoader.Object dummySectorData = new MafiaFormats.Scene2BINLoader.Object(); dummySectorData.type = MafiaFormats.Scene2BINLoader.ObjectType.Sector; var objDef = child.AddComponent <ObjectDefinition>(); objDef.data = dummySectorData; objDef.sectorBounds.SetMinMax(mafiaMesh.sector.minBox, mafiaMesh.sector.maxBox); objDef.Init(); continue; } else if (mafiaMesh.meshType != MafiaFormats.MeshType.Standard) { continue; } if (mafiaMesh.standard.instanced != 0) { continue; } var def = child.AddComponent <ModelDefinition>(); def.model = model; def.mesh = mafiaMesh; Material[] materials; switch (mafiaMesh.visualMeshType) { case MafiaFormats.VisualMeshType.Standard: { // TODO build up more lods if (mafiaMesh.standard.lods.Count > 0) { var meshRenderer = child.AddComponent <MeshRenderer>(); meshFilter.mesh = GenerateMesh(mafiaMesh, child, mafiaMesh.standard.lods[0], model, out materials); meshRenderer.materials = materials; meshRenderer.shadowCastingMode = ShadowCastingMode.TwoSided; // Handle special textures foreach (var m in meshRenderer.sharedMaterials) { var name = m.GetTexture("_MainTex")?.name; if (IsTextureGlow(name)) { var glowTexture = (Texture2D)Resources.Load("Flares/" + Path.GetFileNameWithoutExtension(name)); m.shader = Shader.Find("Unlit/Transparent"); m.SetTexture("_MainTex", glowTexture); break; } } } else { continue; } } break; case MafiaFormats.VisualMeshType.Single_Mesh: { var meshRenderer = child.AddComponent <SkinnedMeshRenderer>(); meshFilter.mesh = GenerateMesh(mafiaMesh, child, mafiaMesh.singleMesh.standard.lods[0], model, out materials); meshRenderer.materials = materials; meshRenderer.sharedMesh = meshFilter.sharedMesh; meshRenderer.shadowCastingMode = ShadowCastingMode.TwoSided; } break; case MafiaFormats.VisualMeshType.Single_Morph: { var meshRenderer = child.AddComponent <SkinnedMeshRenderer>(); meshFilter.mesh = GenerateMesh(mafiaMesh, child, mafiaMesh.singleMorph.singleMesh.standard.lods[0], model, out materials); meshRenderer.materials = materials; meshRenderer.sharedMesh = meshFilter.sharedMesh; meshRenderer.shadowCastingMode = ShadowCastingMode.TwoSided; } break; case MafiaFormats.VisualMeshType.Billboard: { // TODO build up more lods var standard = mafiaMesh.billboard.standard; if (standard.lods.Count > 0) { //NOTE: (DavoSK) Add our custom billboard here child.AddComponent <CustomBillboard>(); var meshRenderer = child.AddComponent <MeshRenderer>(); meshFilter.mesh = GenerateMesh(mafiaMesh, child, standard.lods[0], model, out materials); meshRenderer.materials = materials; meshRenderer.shadowCastingMode = ShadowCastingMode.TwoSided; // Handle special textures foreach (var m in meshRenderer.sharedMaterials) { var name = m.GetTexture("_MainTex")?.name; if (IsTextureGlow(name)) { var glowTexture = (Texture2D)Resources.Load("Flares/" + Path.GetFileNameWithoutExtension(name)); m.shader = Shader.Find("Unlit/Transparent"); m.SetTexture("_MainTex", glowTexture); break; } } } else { continue; } } break; case MafiaFormats.VisualMeshType.Glow: { List <string> usedMaps = new List <string>(); foreach (var g in mafiaMesh.glow.glowData) { if (g.materialID - 1 >= model.materials.Count) { continue; } var matID = g.materialID - 1; var mat = model.materials[matID]; var mapName = mat.diffuseMapName; if (usedMaps.Contains(mapName)) { continue; } foreach (var m in model.meshes) { if (m.standard.lods == null) { continue; } if (m.standard.lods.Count < 1) { continue; } bool used = false; foreach (var gr in m.standard.lods[0].faceGroups) { if (gr.materialID == matID) { GenerateGlow(mapName, rootObject, m.pos); used = true; break; } } if (used == true) { break; } } usedMaps.Add(mapName); } } break; // TODO add more visual types default: continue; } def.modelName = Path.GetFileName(path); meshId++; } for (int i = 0; i < children.Count; i++) { var parentId = children[i].Key; var mafiaMesh = model.meshes[i]; if (parentId > 0) { children[i].Value.parent = children[parentId - 1].Value; } else { children[i].Value.parent = rootObject.transform; } children[i].Value.localPosition = mafiaMesh.pos; children[i].Value.localRotation = mafiaMesh.rot; children[i].Value.localScale = mafiaMesh.scale; } // NOTE(zaklaus): Do some extra work if this is a skinned mesh var baseObject = rootObject.transform.Find("base"); if (baseObject != null) { var skinnedMesh = baseObject.GetComponent <SkinnedMeshRenderer>(); if (skinnedMesh != null) { var def = baseObject.GetComponent <ModelDefinition>(); MafiaFormats.SingleMesh data; if (def.mesh.visualMeshType == MafiaFormats.VisualMeshType.Single_Mesh) { data = def.mesh.singleMesh; } else { data = def.mesh.singleMorph.singleMesh; } var boneData = data.LODs[0]; var bones = new List <Bone>(skinnedMesh.GetComponentsInChildren <Bone>()); var boneArray = new Transform[bones.Count]; foreach (var b in bones) { boneArray[b.data.boneID] = b.transform; } /* TODO: var boneTransforms = new List<Transform>(boneArray); */ var bindPoses = new Matrix4x4[bones.Count]; var boneWeights = new BoneWeight[skinnedMesh.sharedMesh.vertexCount]; skinnedMesh.bones = boneArray; int skipVertices = 0;//(int)boneData.nonWeightedVertCount; for (int i = 0; i < boneData.bones.Count; i++) { bindPoses[i] = boneData.bones[i].transform; for (int j = 0; j < boneData.bones[i].oneWeightedVertCount; j++) { boneWeights[skipVertices + j].boneIndex0 = i; boneWeights[skipVertices + j].weight0 = 1f; boneWeights[skipVertices + j].boneIndex1 = (int)boneData.bones[i].boneID; boneWeights[skipVertices + j].weight1 = 0f; } skipVertices += (int)boneData.bones[i].oneWeightedVertCount; for (int j = 0; j < boneData.bones[i].weights.Count; j++) { boneWeights[skipVertices + j].boneIndex0 = i; boneWeights[skipVertices + j].weight0 = boneData.bones[i].weights[j]; boneWeights[skipVertices + j].boneIndex1 = (int)boneData.bones[i].boneID; boneWeights[skipVertices + j].weight1 = 1f - boneData.bones[i].weights[j]; } skipVertices += boneData.bones[i].weights.Count; } skinnedMesh.sharedMesh.bindposes = bindPoses; skinnedMesh.sharedMesh.boneWeights = boneWeights; } } children.Clear(); } StoreCachedObject(path, rootObject); return(rootObject); }
public override GameObject LoadObject(string path) { GameObject rootObject = null;// LoadCachedObject(path); if (rootObject == null) { rootObject = new GameObject(path); } else { return(rootObject); } FileStream fs; try { fs = new FileStream(GameManager.instance.fileSystem.GetPath(path), FileMode.Open); } catch (Exception ex) { GameObject.DestroyImmediate(rootObject); Debug.LogWarning(ex.ToString()); return(null); } using (BinaryReader reader = new BinaryReader(fs)) { var modelLoader = new MafiaFormats.Reader4DS(); var model = modelLoader.loadModel(reader); var meshId = 0; var children = new List <KeyValuePair <int, Transform> >(); foreach (var mafiaMesh in model.meshes) { var child = new GameObject(mafiaMesh.meshName, typeof(MeshFilter)); var meshFilter = child.GetComponent <MeshFilter>(); children.Add(new KeyValuePair <int, Transform>(mafiaMesh.parentID, child.transform)); if (mafiaMesh.meshType == MafiaFormats.MeshType.Bone) { var bone = child.AddComponent <Bone>(); bone.data = mafiaMesh.bone; continue; } else if (mafiaMesh.meshType == MafiaFormats.MeshType.Collision) { Material[] temp; child.AddComponent <MeshCollider>().sharedMesh = GenerateMesh(mafiaMesh, child, mafiaMesh.standard.lods[0], model, out temp); continue; } else if (mafiaMesh.meshType != MafiaFormats.MeshType.Standard) { continue; } if (mafiaMesh.standard.instanced != 0) { continue; } Material[] materials; switch (mafiaMesh.visualMeshType) { case MafiaFormats.VisualMeshType.Standard: { // TODO build up more lods if (mafiaMesh.standard.lods.Count > 0) { var meshRenderer = child.AddComponent <MeshRenderer>(); meshFilter.mesh = GenerateMesh(mafiaMesh, child, mafiaMesh.standard.lods[0], model, out materials); meshRenderer.materials = materials; bool isTwoSided = model.materials.FindAll(x => (x.flags.HasFlag(MafiaFormats.MaterialFlag.Doublesided_Material))).Count > 0; if (isTwoSided) { meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; } } else { continue; } } break; case MafiaFormats.VisualMeshType.Single_Mesh: { var meshRenderer = child.AddComponent <SkinnedMeshRenderer>(); meshFilter.mesh = GenerateMesh(mafiaMesh, child, mafiaMesh.singleMesh.standard.lods[0], model, out materials); meshRenderer.materials = materials; meshRenderer.sharedMesh = meshFilter.sharedMesh; var data = child.AddComponent <SkinnedMeshData>(); data.mesh = mafiaMesh.singleMesh; } break; case MafiaFormats.VisualMeshType.Single_Morph: { var meshRenderer = child.AddComponent <SkinnedMeshRenderer>(); meshFilter.mesh = GenerateMesh(mafiaMesh, child, mafiaMesh.singleMorph.singleMesh.standard.lods[0], model, out materials); meshRenderer.materials = materials; meshRenderer.sharedMesh = meshFilter.sharedMesh; var data = child.AddComponent <SkinnedMeshData>(); data.mesh = mafiaMesh.singleMorph.singleMesh; } break; // TODO add more visual types default: continue; } meshId++; } for (int i = 0; i < children.Count; i++) { var parentId = children[i].Key; var mafiaMesh = model.meshes[i]; if (parentId > 0) { children[i].Value.parent = children[parentId - 1].Value; } else { children[i].Value.parent = rootObject.transform; } children[i].Value.localPosition = mafiaMesh.pos; children[i].Value.localRotation = mafiaMesh.rot; children[i].Value.localScale = mafiaMesh.scale; } // NOTE(zaklaus): Do some extra work if this is a skinned mesh var baseObject = rootObject.transform.Find("base"); if (baseObject != null) { var skinnedMesh = baseObject.GetComponent <SkinnedMeshRenderer>(); if (skinnedMesh != null) { var data = baseObject.GetComponent <SkinnedMeshData>(); var boneData = data.mesh.LODs[0]; var bones = new List <Bone>(skinnedMesh.GetComponentsInChildren <Bone>()); var boneArray = new Transform[bones.Count]; foreach (var b in bones) { boneArray[b.data.boneID] = b.transform; } var boneTransforms = new List <Transform>(boneArray); var bindPoses = new Matrix4x4[bones.Count]; var boneWeights = new BoneWeight[skinnedMesh.sharedMesh.vertexCount]; skinnedMesh.bones = boneArray; int skipVertices = (int)boneData.nonWeightedVertCount; for (int i = 0; i < boneData.joints.Count; i++) { bindPoses[i] = boneData.joints[i].transform; for (int j = 0; j < boneData.joints[i].oneWeightedVertCount; j++) { boneWeights[skipVertices + j].boneIndex0 = i; boneWeights[skipVertices + j].weight0 = 1f; } skipVertices += (int)boneData.joints[i].oneWeightedVertCount; for (int j = 0; j < boneData.joints[i].weights.Count; j++) { boneWeights[skipVertices + j].boneIndex0 = i; boneWeights[skipVertices + j].weight0 = boneData.joints[i].weights[j]; boneWeights[skipVertices + j].boneIndex1 = (int)boneData.joints[i].boneID; boneWeights[skipVertices + j].weight1 = 1f - boneData.joints[i].weights[j]; } skipVertices += boneData.joints[i].weights.Count; } skinnedMesh.sharedMesh.bindposes = bindPoses; skinnedMesh.sharedMesh.boneWeights = boneWeights; } } children.Clear(); } //StoreChachedObject(path, rootObject); fs.Close(); return(rootObject); }