/// <summary> /// 导出材质 /// </summary> /// <param name="writer"></param> /// <param name="material"></param> /// <param name="path"></param> static void ExportMaterial(TextWriter writer, ModelMaterial material, string path) { writer.WriteLine("newmtl {0}", material.name); writer.WriteLine("Ka 1.0 1.0 1.0"); writer.WriteLine("Kd 1.0 1.0 1.0"); writer.WriteLine("Ks 0.0 0.0 0.0"); writer.WriteLine("d 1.0"); writer.WriteLine("illum 1"); if (!string.IsNullOrEmpty(material.texture)) { string texture = Path.GetFileName(material.texture); try { File.Copy(material.texture, path + "/" + texture); } catch (System.Exception) { } writer.WriteLine("map_Kd {0}", texture); if (material.cutoff < 1f) { writer.WriteLine("map_d {0}", texture); } } writer.WriteLine(); }
public double[] CalcRange(IModelDataEntity modelDataEntity, string materialName, double[] generalRange) { Model modelObject = (modelDataEntity as ModelDataEntity)._model; ModelMaterial foundMaterial = modelObject.ModelMaterials.Find(materialObject => materialObject.Name.ToLower() == materialName.ToLower()); return(foundMaterial.Y); }
private static ModelMaterial ReadMaterial(BinaryReader r) { var data = new ModelMaterial(); data.Descriptions = ReadList(r, 3, ReadString); data.Params = ReadParamList(r); return data; }
private void EnableMaterial(ModelMaterial modelMaterial) { // Load the textures used in this material if (!string.IsNullOrEmpty(modelMaterial.Texture0)) { if (modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClamp)) { CacheTexture(modelMaterial.Texture0, TextureWrapMode.ClampToBorder); } else { CacheTexture(modelMaterial.Texture0); } } if (!string.IsNullOrEmpty(modelMaterial.Texture1)) { if (modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClamp)) { CacheTexture(modelMaterial.Texture1, TextureWrapMode.ClampToBorder); } else { CacheTexture(modelMaterial.Texture1); } } if (!string.IsNullOrEmpty(modelMaterial.Texture2)) { if (modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClamp)) { CacheTexture(modelMaterial.Texture2, TextureWrapMode.ClampToBorder); } else { CacheTexture(modelMaterial.Texture2); } } // Set two-sided rendering if (modelMaterial.Flags.HasFlag(MaterialFlags.TwoSided)) { GL.Disable(EnableCap.CullFace); } else { GL.Enable(EnableCap.CullFace); } if (modelMaterial.BlendMode == BlendingMode.Transparent) { GL.Enable(EnableCap.Blend); } else { GL.Disable(EnableCap.Blend); } }
/// <summary> /// Disposes of the model /// </summary> /// <param name="disposing"></param> protected override void Dispose(bool disposing) { if (!disposed) { if (disposing) { if (diffuse != null) { diffuse.Dispose(); } if (normal != null) { normal.Dispose(); } if (colorTable != null) { colorTable.Dispose(); } if (mask != null) { mask.Dispose(); } if (specular != null) { specular.Dispose(); } if (ModelMaterial != null) { ModelMaterial.Dispose(); } if (SecondModelMaterial != null) { SecondModelMaterial.Dispose(); } if (ThirdModelMaterial != null) { ThirdModelMaterial.Dispose(); } if (mData != null) { mData.Clear(); } } disposed = true; } base.Dispose(disposing); }
ModelMaterial ReadMaterial(Chunk root) { var loader = root.Loader; var reader = root.Reader; Chunk chunk; ModelMaterial material = new ModelMaterial(); int?shading = null; while (root.ReadSubchunk(out chunk)) { switch (chunk.Id) { case ChunkId.MaterialName: material.Name = chunk.ReadContentString(); break; case ChunkId.MaterialAmbient: material.AmbientColor = chunk.ReadContentColor(Vector3d.One); break; case ChunkId.MaterialDiffuse: material.DiffuseColor = chunk.ReadContentColor(Vector3d.One); break; case ChunkId.MaterialSpecular: material.SpecularColor = chunk.ReadContentColor(Vector3d.One); break; case ChunkId.MaterialSpecularSoften: material.SpecularSoftness = chunk.ReadContentPercentage(0.1); break; case ChunkId.MaterialSpecularLevel: material.SpecularLevel = chunk.ReadContentPercentage(1); break; case ChunkId.MaterialTransparency: material.Opacity = chunk.ReadContentPercentage(1); break; case ChunkId.MaterialTransparencyFalloff: material.OpacityFalloffLevel = 1 - chunk.ReadContentPercentage(0); break; case ChunkId.MaterialReflectionBlur: double reflectionBlur = chunk.ReadContentPercentage(0); if (reflectionBlur != 0) { loader.AddError(chunk.Offset, "Expected a reflection blur value of 0 for material; value is ignored."); } break; case ChunkId.MaterialShading: shading = chunk.ReadContentInt(-1); break; case ChunkId.MaterialSelfIlluminationPercentage: material.SelfIlluminationLevel = chunk.ReadContentPercentage(0); break; case ChunkId.MaterialTransparencyFalloffIn: material.OpacityFalloff = ModelMaterialOpacityFalloff.In; break; case ChunkId.MaterialWireSize: material.WireSize = reader.ReadSingle(); break; default: root.ReportUnknownSubchunkError(chunk); break; } chunk.RequireAtEnd(); } return(material); }
public override void OnInspectorGUI() { if (GUILayout.Button("Apply Material")) { ModelMaterial mat = (ModelMaterial)target; mat.gameObject.GetComponent <ModelObject>().ApplyMaterial(mat); } GUILayout.Space(10); DrawDefaultInspector(); }
public void AddMaterial(ModelMaterial material) { if (ModelMaterials.ContainsKey(material.Id)) { ModelMaterials[material.Id] = material; } else { ModelMaterials.Add(material.Id, material); } NumberOfMaterials = ModelMaterials.Count; }
public void DeleteMaterial_MaterialDoesNotExistInProblem_ExpectNothingHappens() { //Arrange var modelProblem = new ModelProblem("problem"); var otherProblem = new ModelProblem("otherProblem"); var strayMaterial = new ModelMaterial(otherProblem, 666, "strayMaterial", 1); //Act modelProblem.DeleteMaterial(strayMaterial); //Assert Assert.That(modelProblem.Materials, Is.Empty); }
internal ModelMaterialParameter(ModelMaterial material, int materialIndex, int index, AssetLoader loader) : base(material, index, loader) { var reader = loader.Reader; Material = material; MaterialIndex = materialIndex; Value = reader.ReadStringzAtUInt32(Encoding); Name = reader.ReadStringzAtUInt32(Encoding); Unknowns.ReadSingles(reader, 2); Unknowns.ReadInt16s(reader, 1); // Always 257? reader.RequireZeroes(2); reader.RequireZeroes(12); }
public ModelMaterial getMaterial(string name) { foreach (ModelMaterial m in materials) { if (m.id == name) { return(m); } } ModelMaterial mat = new ModelMaterial(); mat.id = name; mat.diffuse = Color.WHITE; materials.Add(mat); return(mat); }
public void NewTarget(Vector3D position) { GameObject newTarget = new GameObject(); var targetMaterial = new ModelMaterial() { TextureFile = "Target.3ds.jpg" }; newTarget.ObjectType = "Target"; newTarget.Active = true; newTarget.Position = position; newTarget.Model.ModelFile = "target.3ds"; newTarget.Model.Materials.Add(targetMaterial); GameObjects.Add(newTarget); }
/// <summary> /// Sets the current <see cref="ModelMaterial"/> that the shader renders. /// </summary> /// <param name="modelMaterial">The material to use.</param> public void SetMaterial(ModelMaterial modelMaterial) { Enable(); // Set two-sided rendering if (modelMaterial.Flags.HasFlag(MaterialFlags.TwoSided)) { GL.Disable(EnableCap.CullFace); } else { GL.Enable(EnableCap.CullFace); } if (BlendingState.EnableBlending[modelMaterial.BlendMode]) { GL.Enable(EnableCap.Blend); } else { GL.Disable(EnableCap.Blend); } switch (modelMaterial.BlendMode) { case BlendingMode.AlphaKey: { SetAlphaDiscardThreshold(224.0f / 255.0f); break; } case BlendingMode.Opaque: { SetAlphaDiscardThreshold(0.0f); break; } default: { SetAlphaDiscardThreshold(1.0f / 225.0f); break; } } }
private void CreateMaterial(ModelMaterial mat) { var material = new Material(Shader.Find("Standard")); AssetDatabase.CreateAsset(material, "Assets/Resources/Materials/" + mat.Id + "-" + mat.Name + ".mat"); material.color = mat.Color; material.SetFloat("_Glossiness", mat.Smothness); material.SetFloat("_Metallic", mat.Shininess); if (material.color[3] < 1) { material.SetFloat("_Mode", 3); material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); material.SetInt("_ZWrite", 0); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = 3000; } }
public void ApplyMaterial(ModelMaterial mat) { Materials.ForEach(m => { if (m.Id == mat.Id) { m.Applied = true; var materialToApply = Resources.Load <Material>("Materials/" + mat.Id + "-" + mat.Name); MeshRenderer render = Object.GetComponent <MeshRenderer>(); if (render == null) { render = Object.AddComponent <MeshRenderer>(); } render.material = materialToApply; } else { m.Applied = false; } }); }
private bool MaterialExists(ModelMaterial mat) { return(Resources.Load <Material>("Materials/" + mat.Id + "-" + mat.Name) != null); }
//public string Id //{ // get // { // return _id; // } // set // { // _id = value; // } //} //public string Name //{ // get // { // return _name; // } // set // { // _name = value; // } //} //public GameObject Object //{ // get // { // return _object; // } // set // { // _object = value; // } //} //public string Type //{ // get // { // return _type; // } // set // { // _type = value; // } //} //public string Category //{ // get // { // return _category; // } // set // { // _category = value; // } //} //public List<ModelMaterial> Materials //{ // get // { // return _objectMaterials; // } // set // { // _objectMaterials = value; // } //} public void AddMaterials(string result, bool updateMaterial) { string[] materialsStr = result.Split('#'); Object.GetComponents(Materials); Materials.ForEach(mat => DestroyImmediate(mat)); foreach (string m in materialsStr) { if (m == "") { continue; } string[] parameters = m.Substring(1, m.Length - 2).Split(';'); ModelMaterial mat = Object.AddComponent <ModelMaterial>(); foreach (string p in parameters) { string[] keyValue = p.Split(':'); switch (keyValue[0]) { case "id": mat.Id = keyValue[1]; break; case "name": mat.Name = keyValue[1].Replace('/', '-'); break; case "color": string[] values = keyValue[1].Substring(1, keyValue[1].Length - 2).Split(','); mat.Color = new Color( float.Parse(values[0], CultureInfo.InvariantCulture.NumberFormat) / 255, float.Parse(values[1], CultureInfo.InvariantCulture.NumberFormat) / 255, float.Parse(values[2], CultureInfo.InvariantCulture.NumberFormat) / 255, 1 - float.Parse(values[3], CultureInfo.InvariantCulture.NumberFormat) / 100); break; case "shininess": mat.Shininess = 1 - float.Parse(keyValue[1], CultureInfo.InvariantCulture.NumberFormat) / 255; break; case "smothness": mat.Smothness = 1 - float.Parse(keyValue[1], CultureInfo.InvariantCulture.NumberFormat) / 100; break; default: break; } } if (mat.Name != "") { Materials.Add(mat); if (!MaterialExists(mat) || updateMaterial) { CreateMaterial(mat); } } mat.Applied = false; } }
public void load(string path) { string line; string[] tokens; string curMatName = "default"; Color difcolor = Color.WHITE; Color speccolor = Color.WHITE; float opacity = 1.0f; float shininess = 0.0f; string texFilename = null; if (path == null || File.Exists(path) == false) { return; } StringReader reader = new StringReader(File.ReadAllText(path)); try { while ((line = reader.ReadLine()) != null) { if (line.Length > 0 && line[0] == '\t') { line = line.Substring(1).Trim(); } tokens = line.Split(' '); if (tokens[0].Length == 0) { continue; } else if (tokens[0][0] == '#') { continue; } else { string key = tokens[0].ToLower(); if (key == "newmtl") { ModelMaterial mat = new ModelMaterial(); mat.id = curMatName; mat.diffuse = difcolor; mat.specular = speccolor; mat.opacity = opacity; mat.shininess = shininess; if (texFilename != null) { ModelTexture tex = new ModelTexture(); tex.usage = ModelTexture.USAGE_DIFFUSE; tex.fileName = texFilename; if (mat.textures == null) { mat.textures = new List <ModelTexture>(1); } mat.textures.Add(tex); } materials.Add(mat); if (tokens.Length > 1) { curMatName = tokens[1]; curMatName = curMatName.Replace('.', '_'); } else { curMatName = "default"; } difcolor = Color.WHITE; speccolor = Color.WHITE; opacity = 1.0f; shininess = 0.0f; } else if (key == "kd" || key == "ks") // diffuse or specular { float r = float.Parse(tokens[1]); float g = float.Parse(tokens[2]); float b = float.Parse(tokens[3]); float a = 1; if (tokens.Length > 4) { a = float.Parse(tokens[4]); } if (tokens[0].ToLower() == "kd") { difcolor = new Color(r, g, b, a); } else { speccolor = new Color(r, g, b, a); } } else if (key == "tr" || key == "d") { opacity = float.Parse(tokens[1]); } else if (key == "ns") { shininess = float.Parse(tokens[1]); } else if (key == "map_kd") { // todo: double check this //texFilename = file.parent().child(tokens[1]).path(); texFilename = tokens[1]; } } } reader.Close(); } catch (IOException e) { return; } // last material ModelMaterial lastMat = new ModelMaterial(); lastMat.id = curMatName; lastMat.diffuse = difcolor; lastMat.specular = speccolor; lastMat.opacity = opacity; lastMat.shininess = shininess; if (texFilename != null) { ModelTexture tex = new ModelTexture(); tex.usage = ModelTexture.USAGE_DIFFUSE; tex.fileName = texFilename; if (lastMat.textures == null) { lastMat.textures = new List <ModelTexture>(1); } lastMat.textures.Add(tex); } materials.Add(lastMat); return; }
public ModelData loadModelData(string path, bool flipV = false) { if (logWarning) { Gdx.app.error("ObjLoader", "Wavefront (OBJ) is not fully supported, consult the documentation for more information"); } string[] tokens; char firstChar; MtlLoader mtl = new MtlLoader(); // Create a "default" Group and set it as the active group, in case // there are no groups or objects defined in the OBJ file. Group activeGroup = new Group("default"); groups.Add(activeGroup); var lines = File.ReadAllLines(path); int id = 0; for (int line_i = 0; line_i < lines.Length; line_i++) { var line = lines[line_i]; tokens = Regex.Split(line, @"\s+"); if (tokens.Length < 1) { break; } if (tokens[0].Length == 0) { continue; } else if ((firstChar = tokens[0].ToLower()[0]) == '#') { continue; } else if (firstChar == 'v') { if (tokens[0].Length == 1) { verts.Add(float.Parse(tokens[1])); verts.Add(float.Parse(tokens[2])); verts.Add(float.Parse(tokens[3])); } else if (tokens[0][1] == 'n') { norms.Add(float.Parse(tokens[1])); norms.Add(float.Parse(tokens[2])); norms.Add(float.Parse(tokens[3])); } else if (tokens[0][1] == 't') { uvs.Add(float.Parse(tokens[1])); uvs.Add((flipV ? 1 - float.Parse(tokens[2]) : float.Parse(tokens[2]))); } } else if (firstChar == 'f') { string[] parts; List <int> faces = activeGroup.faces; for (int i = 1; i < tokens.Length - 2; i--) { parts = Regex.Split(tokens[1], @"/"); faces.Add(getIndex(parts[0], verts.Count)); if (parts.Length > 2) { if (i == 1) { activeGroup.hasNorms = true; } faces.Add(getIndex(parts[2], norms.Count)); } if (parts.Length > 1 && parts[1].Length > 0) { if (i == 1) { activeGroup.hasUVs = true; } faces.Add(getIndex(parts[1], uvs.Count)); } parts = Regex.Split(tokens[++i], @"/"); faces.Add(getIndex(parts[0], verts.Count)); if (parts.Length > 2) { faces.Add(getIndex(parts[2], norms.Count)); } if (parts.Length > 1 && parts[1].Length > 0) { faces.Add(getIndex(parts[1], uvs.Count)); } parts = Regex.Split(tokens[++i], @"/"); faces.Add(getIndex(parts[0], verts.Count)); if (parts.Length > 2) { faces.Add(getIndex(parts[2], norms.Count)); } if (parts.Length > 1 && parts[1].Length > 0) { faces.Add(getIndex(parts[1], uvs.Count)); } activeGroup.numFaces++; } } else if (firstChar == 'o' || firstChar == 'g') { // This implementation only supports single object or group // definitions. i.e. "o group_a group_b" will set group_a // as the active group, while group_b will simply be // ignored. if (tokens.Length > 1) { activeGroup = setActiveGroup(tokens[1]); } else { activeGroup = setActiveGroup("default"); } } else if (tokens[0] == "mtllib") { // todo: check that // mtl.load(file.parent().child(tokens[1])); mtl.load(tokens[1]); } else if (tokens[0] == "usemtl") { if (tokens.Length == 1) { activeGroup.materialName = "default"; } else { activeGroup.materialName = tokens[1].Replace('.', '_'); } } } // todo: it will trigger collection change exception... check that // If the "default" group or any others were not used, get rid of them for (int i = 0; i < groups.Count; i++) { if (groups[i].numFaces < 1) { groups.RemoveAt(i); i--; } } // If there are no groups left, there is no valid Model to return if (groups.Count < 1) { return(null); } // Get number of objects/groups remaining after removing empty ones int numGroups = groups.Count; ModelData data = new ModelData(); for (int g = 0; g < numGroups; g++) { Group group = groups[g]; List <int> faces = group.faces; int numElements = faces.Count; int numFaces = group.numFaces; bool hasNorms = group.hasNorms; bool hasUVs = group.hasUVs; float[] finalVerts = new float[(numFaces * 3) * (3 + (hasNorms ? 3 : 0) + (hasUVs ? 2 : 0))]; for (int i = 0, vi = 0; i < numElements;) { int vertIndex = faces[i++] * 3; finalVerts[vi++] = verts[vertIndex++]; finalVerts[vi++] = verts[vertIndex++]; finalVerts[vi++] = verts[vertIndex]; if (hasNorms) { int normIndex = faces[i++] * 3; finalVerts[vi++] = norms[normIndex++]; finalVerts[vi++] = norms[normIndex++]; finalVerts[vi++] = norms[normIndex]; } if (hasUVs) { int uvIndex = faces[i++] * 2; finalVerts[vi++] = uvs[uvIndex++]; finalVerts[vi++] = uvs[uvIndex]; } } int numIndices = numFaces * 3 >= short.MaxValue ? 0 : numFaces * 3; uint[] finalIndices = new uint[numIndices]; // if there are too many vertices in a mesh, we can't use indices if (numIndices > 0) { for (int i = 0; i < numIndices; i++) { finalIndices[i] = (uint)i; } } List <VertexAttribute> attributes = new List <VertexAttribute>(); attributes.Add(new VertexAttribute(VertexAttributes.Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE)); if (hasNorms) { attributes.Add(new VertexAttribute(VertexAttributes.Usage.Normal, 3, ShaderProgram.NORMAL_ATTRIBUTE)); } if (hasUVs) { attributes.Add(new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0")); } string stringId = Convert.ToString(++id); string nodeId = "default" == group.name ? "node" + stringId : group.name; string meshId = "default" == group.name ? "mesh" + stringId : group.name; string partId = "default" == group.name ? "part" + stringId : group.name; ModelNode node = new ModelNode(); node.id = nodeId; node.meshId = meshId; node.scale = new Vector3(1, 1, 1); node.translation = new Vector3(); node.rotation = new Quaternion(); ModelNodePart pm = new ModelNodePart(); pm.meshPartId = partId; pm.materialId = group.materialName; node.parts = new ModelNodePart[] { pm }; ModelMeshPart part = new ModelMeshPart(); part.id = partId; part.indices = finalIndices; part.primitiveType = PrimitiveType.Triangles; ModelMesh mesh = new ModelMesh(); mesh.id = meshId; mesh.attributes = attributes.ToArray(); mesh.vertices = finalVerts; mesh.parts = new ModelMeshPart[] { part }; data.nodes.Add(node); data.meshes.Add(mesh); ModelMaterial mm = mtl.getMaterial(group.materialName); data.materials.Add(mm); } // for (ModelMaterial m : mtl.materials) // data.materials.Add(m); // An instance of ObjLoader can be used to load more than one OBJ. // Clearing the Array cache instead of instantiating new // Arrays should result in slightly faster load times for // subsequent calls to loadObj if (verts.Count > 0) { verts.Clear(); } if (norms.Count > 0) { norms.Clear(); } if (uvs.Count > 0) { uvs.Clear(); } if (groups.Count > 0) { groups.Clear(); } return(data); }
/// <summary> /// Renders the specified model group on a batch basis. /// </summary> private void RenderGroup(ModelGroup modelGroup, Matrix4 modelViewProjection) { // Reenable depth test GL.Enable(EnableCap.DepthTest); // Render the object // Send the vertices to the shader this.VertexBufferLookup[modelGroup].Bind(); this.VertexBufferLookup[modelGroup].EnableAttributes(); this.NormalBufferLookup[modelGroup].Bind(); this.NormalBufferLookup[modelGroup].EnableAttributes(); this.TextureCoordinateBufferLookup[modelGroup].Bind(); this.TextureCoordinateBufferLookup[modelGroup].EnableAttributes(); // Bind the index buffer this.VertexIndexBufferLookup[modelGroup].Bind(); if (this.ShouldRenderWireframe) { this.Shader.Wireframe.SetWireframeColour(EverlookConfiguration.Instance.WireframeColour); // Override blend setting GL.Enable(EnableCap.Blend); } // Render all the different materials (opaque first, transparent after) foreach (RenderBatch renderBatch in modelGroup.GetRenderBatches() .OrderBy(batch => batch.MaterialIndex) .ThenBy(batch => this.Model.GetMaterial(batch.MaterialIndex).BlendMode)) { this.Shader.Enable(); ModelMaterial modelMaterial = this.Model.GetMaterial(renderBatch.MaterialIndex); this.Shader.SetMaterial(modelMaterial); this.Shader.SetMVPMatrix(modelViewProjection); // Set the texture as the first diffuse texture in unit 0 Texture2D texture = this.Cache.GetCachedTexture(modelMaterial.Texture0); if (modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClamp)) { texture.WrappingMode = TextureWrapMode.Clamp; } else { texture.WrappingMode = TextureWrapMode.Repeat; } this.Shader.BindTexture2D(TextureUnit.Texture0, TextureUniform.Texture0, texture); // Finally, draw the model GL.DrawRangeElements ( PrimitiveType.Triangles, renderBatch.FirstPolygonIndex, renderBatch.FirstPolygonIndex + renderBatch.PolygonIndexCount - 1, renderBatch.PolygonIndexCount, DrawElementsType.UnsignedShort, new IntPtr(renderBatch.FirstPolygonIndex * 2) ); } // Release the attribute arrays this.VertexBufferLookup[modelGroup].DisableAttributes(); this.NormalBufferLookup[modelGroup].DisableAttributes(); this.TextureCoordinateBufferLookup[modelGroup].DisableAttributes(); }
/// <summary> /// 导出mesh /// </summary> /// <param name="writer"></param> /// <param name="model"></param> /// <param name="materalSet"></param> /// <param name="offset"></param> static void ExportMesh(TextWriter writer, Model model, HashSet <ModelMaterial> materalSet, ref int offset) { int vertexCount = model.mesh.vertexCount; writer.WriteLine( string.Format("g {0}", model.transform.name)); for (int i = 0; i < vertexCount; ++i) { Vector3 v = model.transform.TransformPoint(model.mesh.vertices[i]); v *= unitsScale; writer.WriteLine( string.Format("v {0} {1} {2}", -v.x, v.y, v.z)); } writer.WriteLine(); for (int i = 0; i < vertexCount; ++i) { Vector3 n = model.transform.TransformDirection(model.mesh.normals[i]); writer.WriteLine( string.Format("vn {0} {1} {2}", -n.x, n.y, n.z)); } writer.WriteLine(); for (int i = 0; i < vertexCount; ++i) { Vector2 t = model.mesh.uv[i]; writer.WriteLine( string.Format("vt {0} {1}", t.x, t.y)); } writer.WriteLine(); for (int i = 0; i < model.mesh.subMeshCount; ++i) { Material mtl = model.materials[i]; int[] triangles = model.mesh.GetTriangles(i); if (exportMaterial) { ModelMaterial modelMtl = new ModelMaterial(); modelMtl.name = mtl.name; modelMtl.cutoff = 1f; for (int t = 0; t < 100; ++t) { if (!materalSet.Contains(modelMtl)) { break; } modelMtl.name = string.Format("{0}_{1:d2}", mtl.name, t); } writer.WriteLine( string.Format("usemtl {0}", modelMtl.name)); writer.WriteLine( string.Format("usemap {0}", modelMtl.name)); if (mtl.mainTexture) { modelMtl.texture = AssetDatabase.GetAssetPath(mtl.mainTexture); } else { modelMtl.texture = null; } if (mtl.HasProperty("_Cutoff")) { modelMtl.cutoff = mtl.GetFloat("_Cutoff"); } materalSet.Add(modelMtl); } for (int j = 0; j < triangles.Length / 3; ++j) { writer.WriteLine( string.Format( "f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}", triangles[j * 3 + 0] + 1 + offset, triangles[j * 3 + 1] + 1 + offset, triangles[j * 3 + 2] + 1 + offset)); } } writer.WriteLine(); offset += vertexCount; }
private Material CreateMaterial(ModelMaterial modelmtrl) { var shininess = modelmtrl.Params.OfType<ParamF> ().FirstOrDefault(i => i.Name == "_Shininess"); var maintex = modelmtrl.Params.OfType<ParamTex>().FirstOrDefault(i => i.Name == "_MainTex"); var color = modelmtrl.Params.OfType<ParamCol>().FirstOrDefault(i => i.Name == "_Color"); var mtrl = new Material(); var id = modelmtrl.Descriptions[0]; var name = modelmtrl.Descriptions[0]; mtrl.ID = "Material-"+id; mtrl.Name = "Material-"+name; mtrl.Shader = ShaderType.Phong; mtrl.Shininess = null == shininess ? 1 : shininess.Value; mtrl.Transparency= 1; if(null != maintex) { var surf = new TextureSurface("Surface-"+id+"-Diff", name+"-Diff"); surf.Texture= CreateBitmapTexture(maintex); surf.TexCoord = 1; mtrl.AddSurface(SurfaceSlot.Diffuse, surf); } else if(null != color) { var surf = new ColorSurface("Surface-"+id+"-Diff", name+"-Diff"); surf.Color3 = new SlimDX.Color3(color.R, color.G, color.B); mtrl.AddSurface(SurfaceSlot.Diffuse, surf); } else { var surf = new ColorSurface("Surface-"+id+"-Diff", name+"-Diff"); surf.Color3 = new SlimDX.Color3(1, 1, 1); mtrl.AddSurface(SurfaceSlot.Diffuse, surf); } mtrl.AddSurface(SurfaceSlot.Ambient, new SlimDX.Color4(1.0f, 0.5f, 0.5f, 0.5f)); mtrl.AddSurface(SurfaceSlot.Specular, new SlimDX.Color4(1.0f, 0.0f, 0.0f, 0.0f)); mtrl.AddSurface(SurfaceSlot.Reflective, new SlimDX.Color4(1.0f, 0.0f, 0.0f, 0.0f)); mtrl.AddSurface(SurfaceSlot.Transparent, new SlimDX.Color4(1.0f, 1.0f, 1.0f, 1.0f)); Materials.Add(mtrl.ID, mtrl); Root.Instances.Add(mtrl); return mtrl; }
public static List<ModelMaterial> ReadFromStream(Stream stream) { var streamReader = new StreamReader(stream); var materialId = 0; var materials = new List<ModelMaterial>(); ModelMaterial material = null; string line; while ((line = streamReader.ReadLine()) != null) { var parts = line.Split(' '); switch (parts[0]) { case "newmtl": if (material != null) { materials.Add(material); } material = new ModelMaterial { MaterialId = materialId, MaterialName = parts[1] }; materialId++; break; case "map_Kd": if (material == null) { throw new ModelReaderException("No material to load diffuse texture"); } material.DiffuseTexture = parts[1]; break; case "Ka": if (material == null) { throw new ModelReaderException("No material to load ambient lighting"); } material.Ambient = new Color4( 1.0f, float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]) ); break; case "Kd": if (material == null) { throw new ModelReaderException("No material to load diffuse lighting"); } material.Diffuse = new Color4( 1.0f, float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]) ); break; case "Ks": if (material == null) { throw new ModelReaderException("No material to load specular lighting"); } material.Specular = new Color4( 1.0f, float.Parse(parts[1]), float.Parse(parts[2]), float.Parse(parts[3]) ); break; } } streamReader.Close(); if (material != null) { materials.Add(material); } return materials; }
/// <summary> /// Sets constant registers to a material which is passed to the pixel shader on the graphics device. /// </summary> /// <remarks>This method manages automatically the pixel registers and must be used after a ShaderHelper.SetPixelShader call.</remarks> /// <param name="graphicsDevice">The GraphicsDevice object.</param> /// <param name="material">A ModelMaterial object.</param> public static void SetPixelShaderConstantMaterial(GraphicsDevice graphicsDevice, ref ModelMaterial material) { int register = _pixelRegister; bool incrementPixelShaderRegister = false; if (_materialRegister == -1) { _materialRegister = _pixelRegister; incrementPixelShaderRegister = true; } else { register = _materialRegister; } Vector4 v1 = new Vector4(material.Ambientness, material.Diffuseness, material.Specularness, material.Emissiveness); // x,y,z,w graphicsDevice.SetPixelShaderConstantFloat4(register++, ref v1); Vector4 v2 = new Vector4(0.0f, 0.0f, 0.0f, material.Shininess); graphicsDevice.SetPixelShaderConstantFloat4(register++, ref v2); if (incrementPixelShaderRegister) { _pixelRegister = register; } }
protected ShapeModel(ModelMaterial material = null) : base(new Mesh(), material) { }
/// <summary> /// Renders the specified model group on a batch basis. /// </summary> private void RenderGroup(ModelGroup modelGroup, Matrix4 modelViewProjection) { GL.UseProgram(this.SimpleShaderID); // Render the object // Send the vertices to the shader GL.EnableVertexAttribArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, this.vertexBufferLookup[modelGroup]); GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0); // Send the normals to the shader GL.EnableVertexAttribArray(1); GL.BindBuffer(BufferTarget.ArrayBuffer, this.normalBufferLookup[modelGroup]); GL.VertexAttribPointer( 1, 3, VertexAttribPointerType.Float, false, 0, 0); // Send the texture coordinates to the shader GL.EnableVertexAttribArray(2); GL.BindBuffer(BufferTarget.ArrayBuffer, this.textureCoordinateBufferLookup[modelGroup]); GL.VertexAttribPointer( 2, 2, VertexAttribPointerType.Float, false, 0, 0); // Bind the index buffer int indexBufferID = this.vertexIndexBufferLookup[modelGroup]; GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBufferID); // Send the model matrix to the shader int projectionShaderVariableHandle = GL.GetUniformLocation(this.SimpleShaderID, "ModelViewProjection"); GL.UniformMatrix4(projectionShaderVariableHandle, false, ref modelViewProjection); // Render all the different materials (opaque first, transparent after) foreach (RenderBatch renderBatch in modelGroup.GetRenderBatches() .OrderBy(batch => batch.MaterialIndex) .ThenBy(batch => this.Model.GetMaterial(batch.MaterialIndex).BlendMode)) { // TODO: Render based on the shader. For now, simple rendering of diffuse texture ModelMaterial modelMaterial = this.Model.GetMaterial(renderBatch.MaterialIndex); EnableMaterial(modelMaterial); int textureID = this.Cache.GetCachedTexture(modelMaterial.Texture0); // Set the texture ID as a uniform sampler in unit 0 GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, textureID); int textureVariableHandle = GL.GetUniformLocation(this.SimpleShaderID, "texture0"); int textureUnit = 0; GL.Uniform1(textureVariableHandle, 1, ref textureUnit); // Finally, draw the model GL.DrawRangeElements(PrimitiveType.Triangles, renderBatch.FirstPolygonIndex, renderBatch.FirstPolygonIndex + renderBatch.PolygonIndexCount - 1, renderBatch.PolygonIndexCount, DrawElementsType.UnsignedShort, new IntPtr(renderBatch.FirstPolygonIndex * 2)); } // Release the attribute arrays GL.DisableVertexAttribArray(0); GL.DisableVertexAttribArray(1); GL.DisableVertexAttribArray(2); }
/// <summary> /// Sets the current <see cref="ModelMaterial"/> that the shader renders. /// </summary> /// <param name="modelMaterial">The material to use.</param> public void SetMaterial(ModelMaterial modelMaterial) { if (modelMaterial == null) { throw new ArgumentNullException(nameof(modelMaterial)); } Enable(); // Set two-sided rendering if (modelMaterial.Flags.HasFlag(MaterialFlags.TwoSided)) { GL.Disable(EnableCap.CullFace); } else { GL.Enable(EnableCap.CullFace); } if (BlendingState.EnableBlending[modelMaterial.BlendMode]) { GL.Enable(EnableCap.Blend); } else { GL.Disable(EnableCap.Blend); } var dstA = BlendingState.DestinationAlpha[modelMaterial.BlendMode]; var srcA = BlendingState.SourceAlpha[modelMaterial.BlendMode]; var dstC = BlendingState.DestinationColour[modelMaterial.BlendMode]; var srcC = BlendingState.SourceColour[modelMaterial.BlendMode]; GL.BlendFuncSeparate ( (BlendingFactorSrc)srcC, (BlendingFactorDest)dstC, (BlendingFactorSrc)srcA, (BlendingFactorDest)dstA ); switch (modelMaterial.BlendMode) { case BlendingMode.AlphaKey: { SetAlphaDiscardThreshold(224.0f / 255.0f); break; } case BlendingMode.Opaque: { SetAlphaDiscardThreshold(0.0f); break; } default: { SetAlphaDiscardThreshold(1.0f / 225.0f); break; } } }
private static void WriteMaterial(BinaryWriter w, ModelMaterial data) { Write(w, WriteString, data.Descriptions); WriteParamList(w, data.Params); }
/// <summary> /// Renders the specified model group on a batch basis. /// </summary> private void RenderGroup(ModelGroup modelGroup, Matrix4 modelViewProjection) { // Render the object // Send the vertices to the shader GL.EnableVertexAttribArray(0); GL.BindBuffer(BufferTarget.ArrayBuffer, this.VertexBufferLookup[modelGroup]); GL.VertexAttribPointer( 0, 3, VertexAttribPointerType.Float, false, 0, 0); // Send the normals to the shader GL.EnableVertexAttribArray(1); GL.BindBuffer(BufferTarget.ArrayBuffer, this.NormalBufferLookup[modelGroup]); GL.VertexAttribPointer( 1, 3, VertexAttribPointerType.Float, false, 0, 0); // Send the texture coordinates to the shader GL.EnableVertexAttribArray(2); GL.BindBuffer(BufferTarget.ArrayBuffer, this.TextureCoordinateBufferLookup[modelGroup]); GL.VertexAttribPointer( 2, 2, VertexAttribPointerType.Float, false, 0, 0); // Bind the index buffer int indexBufferID = this.VertexIndexBufferLookup[modelGroup]; GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBufferID); // Render all the different materials (opaque first, transparent after) foreach (RenderBatch renderBatch in modelGroup.GetRenderBatches() .OrderBy(batch => batch.MaterialIndex) .ThenBy(batch => this.Model.GetMaterial(batch.MaterialIndex).BlendMode)) { this.Shader.Enable(); ModelMaterial modelMaterial = this.Model.GetMaterial(renderBatch.MaterialIndex); this.Shader.SetMaterial(modelMaterial); this.Shader.SetMVPMatrix(modelViewProjection); // Set the texture as the first diffuse texture in unit 0 Texture2D texture = this.Cache.GetCachedTexture(modelMaterial.Texture0); if (modelMaterial.Flags.HasFlag(MaterialFlags.TextureWrappingClamp)) { texture.WrappingMode = TextureWrapMode.Clamp; } else { texture.WrappingMode = TextureWrapMode.Repeat; } this.Shader.BindTexture2D(TextureUnit.Texture0, TextureUniform.Diffuse0, texture); // Finally, draw the model GL.DrawRangeElements ( PrimitiveType.Triangles, renderBatch.FirstPolygonIndex, renderBatch.FirstPolygonIndex + renderBatch.PolygonIndexCount - 1, renderBatch.PolygonIndexCount, DrawElementsType.UnsignedShort, new IntPtr(renderBatch.FirstPolygonIndex * 2) ); } // Release the attribute arrays GL.DisableVertexAttribArray(0); GL.DisableVertexAttribArray(1); GL.DisableVertexAttribArray(2); }
public void AddMaterial(ModelMaterial material) { Materials.Add(material); }
protected Material convertMaterial(ModelMaterial mtl, TextureProvider textureProvider) { Material result = new Material(); result.id = mtl.id; if (mtl.ambient != default(Color)) { result.set(new ColorAttribute(ColorAttribute.Ambient, mtl.ambient)); } if (mtl.diffuse != default(Color)) { result.set(new ColorAttribute(ColorAttribute.Diffuse, mtl.diffuse)); } if (mtl.specular != default(Color)) { result.set(new ColorAttribute(ColorAttribute.Specular, mtl.specular)); } if (mtl.emissive != default(Color)) { result.set(new ColorAttribute(ColorAttribute.Emissive, mtl.emissive)); } if (mtl.reflection != default(Color)) { result.set(new ColorAttribute(ColorAttribute.Reflection, mtl.reflection)); } if (mtl.shininess > 0f) { result.set(new FloatAttribute(FloatAttribute.Shininess, mtl.shininess)); } if (mtl.opacity != 1.0f) { result.set(new BlendingAttribute(true, BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha, mtl.opacity)); } var textures = new Dictionary <string, Texture>(); // FIXME uvScaling/uvTranslation totally ignored if (mtl.textures != null) { foreach (ModelTexture tex in mtl.textures) { Texture texture; if (textures.ContainsKey(tex.fileName)) { texture = textures[tex.fileName]; } else { texture = textureProvider.load(tex.fileName); textures.Add(tex.fileName, texture); disposables.Add(texture); } var descriptor = new TextureDescriptor(texture); descriptor.minFilter = texture.getMinFilter(); descriptor.magFilter = texture.getMagFilter(); descriptor.uWrap = texture.getUWrap(); descriptor.vWrap = texture.getVWrap(); float offsetU = tex.uvTranslation == null ? 0f : tex.uvTranslation.X; float offsetV = tex.uvTranslation == null ? 0f : tex.uvTranslation.Y; float scaleU = tex.uvScaling == null ? 1f : tex.uvScaling.X; float scaleV = tex.uvScaling == null ? 1f : tex.uvScaling.Y; switch (tex.usage) { case ModelTexture.USAGE_DIFFUSE: result.set(new TextureAttribute(TextureAttribute.Diffuse, descriptor, offsetU, offsetV, scaleU, scaleV)); break; case ModelTexture.USAGE_SPECULAR: result.set(new TextureAttribute(TextureAttribute.Specular, descriptor, offsetU, offsetV, scaleU, scaleV)); break; case ModelTexture.USAGE_BUMP: result.set(new TextureAttribute(TextureAttribute.Bump, descriptor, offsetU, offsetV, scaleU, scaleV)); break; case ModelTexture.USAGE_NORMAL: result.set(new TextureAttribute(TextureAttribute.Normal, descriptor, offsetU, offsetV, scaleU, scaleV)); break; case ModelTexture.USAGE_AMBIENT: result.set(new TextureAttribute(TextureAttribute.Ambient, descriptor, offsetU, offsetV, scaleU, scaleV)); break; case ModelTexture.USAGE_EMISSIVE: result.set(new TextureAttribute(TextureAttribute.Emissive, descriptor, offsetU, offsetV, scaleU, scaleV)); break; case ModelTexture.USAGE_REFLECTION: result.set(new TextureAttribute(TextureAttribute.Reflection, descriptor, offsetU, offsetV, scaleU, scaleV)); break; } } } return(result); }