public SBHsdMaterial(HSD_DOBJ dobj) { _mobj = dobj.Mobj; /*if (_mobj.Textures != null) * foreach (var tex in _mobj.Textures.List) * Console.WriteLine(tex.Flags.ToString());*/ }
/// <summary> /// /// </summary> /// <param name="objFileStream"></param> /// <returns></returns> public static HSD_JOBJ GenerateEmblemModel(EmblemModel model) { List <GX_Vertex> vertexList = new List <GX_Vertex>(); foreach (var ve in model.f) { foreach (var i in ve) { var x = ((model.v[i - 1][0] - model.xRange.X) / Math.Abs(model.xRange.Y - model.xRange.X)) * model.aspectX; var y = (1 - (model.v[i - 1][2] - model.yRange.X) / Math.Abs(model.xRange.Y - model.yRange.X)) * model.aspectY; vertexList.Add(new GX_Vertex() { POS = new GXVector3(x * 6 - 3, y * 6 - 3, 0) }); } } HSD_JOBJ jobj = new HSD_JOBJ(); jobj.Flags = JOBJ_FLAG.CLASSICAL_SCALING | JOBJ_FLAG.XLU; jobj.SX = 3; jobj.SY = 3; jobj.SZ = 3; jobj.TZ = 67.4f; HSD_DOBJ dobj = new HSD_DOBJ(); dobj.Mobj = new HSD_MOBJ() { RenderFlags = RENDER_MODE.CONSTANT | RENDER_MODE.NO_ZUPDATE | RENDER_MODE.XLU, Material = new HSD_Material() { Alpha = 0.6f, Shininess = 50, DiffuseColor = Color.FromArgb(255, 128, 128, 230), SpecularColor = Color.FromArgb(255, 255, 255, 255), AmbientColor = Color.FromArgb(255, 128, 128, 128), } }; jobj.Dobj = dobj; POBJ_Generator pobjGen = new POBJ_Generator(); GXAttribName[] attrs = new GXAttribName[] { GXAttribName.GX_VA_POS, GXAttribName.GX_VA_NULL }; dobj.Pobj = pobjGen.CreatePOBJsFromTriangleList(vertexList, attrs, null); dobj.Pobj.Flags = 0; pobjGen.SaveChanges(); return(jobj); }
/// <summary> /// /// </summary> /// <param name="vertices"></param> public void AddBuffer(HSD_DOBJ dobj, GX_Vertex[] vertices) { // generate buffer int buf; GL.GenBuffers(1, out buf); GL.BindBuffer(BufferTarget.ArrayBuffer, buf); GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * GX_Vertex.Stride, vertices, BufferUsageHint.StaticDraw); if (buf != -1) { attributeToBuffer.Add(dobj, buf); } }
/// <summary> /// /// </summary> public static void MergeIntoOneObject(HSD_JOBJ jobj) { // gather all pobjs HSD_DOBJ result = null; List <HSD_POBJ> pobj = new List <HSD_POBJ>(); foreach (var j in jobj.BreathFirstList) { if (j.Dobj != null) { foreach (var d in j.Dobj.List) { if (d.Pobj != null) { foreach (var p in d.Pobj.List) { pobj.Add(p); } } } if (result == null) { result = j.Dobj; result.Next = null; } } j.Dobj = null; } // link pobjs for (int i = 0; i < pobj.Count; i++) { if (i == pobj.Count - 1) { pobj[i].Next = null; } else { pobj[i].Next = pobj[i + 1]; } } // put them all in the first dobj result.Pobj = pobj[0]; jobj.Dobj = result; }
/// <summary> /// /// </summary> /// <param name="vertices"></param> public void AddShapeSets(HSD_DOBJ dobj, List <List <GX_Shape> > shapes) { if (!dobjToShapes.ContainsKey(dobj)) { dobjToShapes.Add(dobj, new int[shapes.Count]); } else { foreach (var v in dobjToShapes[dobj]) { GL.DeleteBuffer(v); } dobjToShapes[dobj] = new int[shapes.Count]; } int si = 0; foreach (var shape in shapes) { // convert to array var arr = shape.ToArray(); // generate buffer int buf; GL.GenBuffers(1, out buf); GL.BindBuffer(BufferTarget.ArrayBuffer, buf); GL.BufferData(BufferTarget.ArrayBuffer, arr.Length * GX_Shape.Stride, arr, BufferUsageHint.StaticDraw); if (buf != -1) { dobjToShapes[dobj][si] = buf; } si++; } }
public DOBJContextMenu() : base() { MenuItem ImportAfter = new MenuItem("Import DOBJ After"); ImportAfter.Click += (sender, args) => { if (MainForm.SelectedDataNode.Accessor is HSD_DOBJ dobj) { var f = FileIO.OpenFile("DAT (.dat)|*.dat"); if (f != null) { HSDRawFile dat = new HSDRawFile(f); HSD_DOBJ newDOBJ = new HSD_DOBJ(); newDOBJ._s = dat.Roots[0].Data._s; if (newDOBJ._s.Length == newDOBJ.TrimmedSize) { newDOBJ.Next = dobj.Next; dobj.Next = newDOBJ; } } } }; MenuItems.Add(ImportAfter); }
/// <summary> /// /// </summary> /// <param name="c"></param> /// <param name="dobj"></param> /// <param name="parentJOBJ"></param> /// <param name="jobjManager"></param> public void RenderDOBJShader(Camera camera, HSD_DOBJ dobj, HSD_JOBJ parentJOBJ, JOBJManager jobjManager, bool selected = false) { if (dobj.Pobj == null) return; if (HiddenDOBJs.Contains(dobj) || (selected && OnlyRenderSelected)) return; if (OnlyRenderSelected && SelectedDOBJ != null && SelectedDOBJ._s != dobj._s) return; var mobj = dobj.Mobj; var pobjs = dobj.Pobj.List; if(!DOBJtoBuffer.ContainsKey(dobj)) LoadDOBJ(dobj, jobjManager); if (!DOBJtoBuffer.ContainsKey(dobj)) return; if (GXShader == null) { GXShader = new Shader(); GXShader.LoadShader(@"Shader\gx.vert"); GXShader.LoadShader(@"Shader\gx.frag"); } GL.UseProgram(GXShader.programId); var mvp = camera.MvpMatrix; GL.UniformMatrix4(GXShader.GetVertexAttributeUniformLocation("mvp"), false, ref mvp); Vector3 camPos = (camera.RotationMatrix * new Vector4(camera.Translation, 1)).Xyz; GXShader.SetVector3("cameraPos", camPos); Matrix4 single = Matrix4.Identity; if (parentJOBJ != null && jobjManager != null) single = jobjManager.GetWorldTransform(parentJOBJ); GL.UniformMatrix4(GXShader.GetVertexAttributeUniformLocation("singleBind"), false, ref single); var rootJOBJ = jobjManager.GetJOBJ(0); GXShader.SetBoolToInt("isRootBound", parentJOBJ?._s == rootJOBJ?._s); GXShader.SetWorldTransformBones(jobjManager.GetWorldTransforms()); //GXShader.SetBindTransformBones(jobjManager.GetBindTransforms()); var tb = jobjManager.GetBindTransforms(); if (tb.Length > 0) GXShader.SetMatrix4x4("binds", tb); GL.Uniform3(GXShader.GetVertexAttributeUniformLocation("overlayColor"), OverlayColor); Matrix4 sphereMatrix = camera.ModelViewMatrix; sphereMatrix.Invert(); sphereMatrix.Transpose(); GXShader.SetMatrix4x4("sphereMatrix", ref sphereMatrix); float wscale = 1; float hscale = 1; bool mirrorX = false; bool mirrorY = false; if (mobj != null) BindMOBJ(GXShader, mobj, out wscale, out hscale, out mirrorX, out mirrorY); GL.BindBuffer(BufferTarget.ArrayBuffer, DOBJtoBuffer[dobj]); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX"), 1, VertexAttribPointerType.Short, false, GX_Vertex.Stride, 0); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 8); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 20); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_CLR0")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_CLR0"), 4, VertexAttribPointerType.Float, true, GX_Vertex.Stride, 56); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0"), 2, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 88); if (selected) { GL.Uniform1(GXShader.GetVertexAttributeUniformLocation("colorOverride"), 1); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); } else { GL.PolygonMode(MaterialFace.Back, PolygonMode.Fill); GL.Uniform1(GXShader.GetVertexAttributeUniformLocation("colorOverride"), 0); } foreach (var p in DOBJtoPOBJCache[dobj]) { var en = p.Envelopes; GL.Uniform4(GXShader.GetVertexAttributeUniformLocation("envelopeIndex"), p.Envelopes.Length, ref p.Envelopes[0].X); var we = p.Weights; GL.Uniform4(GXShader.GetVertexAttributeUniformLocation("weights"), p.Weights.Length, ref p.Weights[0].X); GL.Uniform1(GXShader.GetVertexAttributeUniformLocation("hasEnvelopes"), p.HasWeighting ? 1 : 0); foreach (var dl in p.DisplayLists) GL.DrawArrays(dl.PrimType, dl.Offset, dl.Count); } GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX")); GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS")); GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM")); GL.DisableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0")); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.UseProgram(0); }
/// <summary> /// Prepares DOBJ for rendering by loading relevant information into a cache /// </summary> private void LoadDOBJ(HSD_DOBJ dobj, JOBJManager jobjManager) { if(DOBJtoBuffer.ContainsKey(dobj)) { GL.DeleteBuffer(DOBJtoBuffer[dobj]); DOBJtoBuffer.Remove(dobj); } List<CachedPOBJ> pobjs = new List<CachedPOBJ>(); List<GX_Vertex> vertices = new List<GX_Vertex>(); int off = 0; foreach(var pobj in dobj.Pobj.List) { var dl = pobj.ToDisplayList(); vertices.AddRange(dl.Vertices); var pobjCache = new CachedPOBJ(); // build envelopes int eni = 0; foreach(var v in dl.Envelopes) { Vector4 b = new Vector4(); Vector4 w = new Vector4(); for(int i = 0; i < v.EnvelopeCount; i++) { if (i >= 4) break; w[i] = v.GetWeightAt(i); b[i] = jobjManager.IndexOf(v.GetJOBJAt(i)); } pobjCache.Weights[eni] = w; pobjCache.Envelopes[eni] = b; eni++; pobjCache.HasWeighting = v.EnvelopeCount > 0; } // load display list foreach (var v in dl.Primitives) { pobjCache.DisplayLists.Add(new CachedDL() { Offset = off, Count = v.Count, PrimType = GXTranslator.toPrimitiveType(v.PrimitiveType) }); off += v.Count; } pobjs.Add(pobjCache); } var arr = vertices.ToArray(); int buf; GL.GenBuffers(1, out buf); GL.BindBuffer(BufferTarget.ArrayBuffer, buf); GL.BufferData(BufferTarget.ArrayBuffer, arr.Length * GX_Vertex.Stride, arr, BufferUsageHint.StaticDraw); DOBJtoBuffer.Add(dobj, buf); DOBJtoPOBJCache.Add(dobj, pobjs); }
public static HSD_DOBJ GenerateOutlineMesh(HSD_DOBJ DOBJ) { var settings = new OutlineSettings(); using (PropertyDialog d = new PropertyDialog("Outline Settings", settings)) { if (d.ShowDialog() != DialogResult.OK) { return(null); } } var pobjGen = new POBJ_Generator(); pobjGen.UseTriangleStrips = settings.UseStrips; var newDOBJ = new HSD_DOBJ(); newDOBJ.Mobj = new HSD_MOBJ() { Material = new HSD_Material() { AmbientColor = Color.White, SpecularColor = Color.Black, DiffuseColor = settings.Color, DIF_A = 255, SPC_A = 255, AMB_A = 255, Shininess = 50, Alpha = 1 }, RenderFlags = RENDER_MODE.CONSTANT }; foreach (var pobj in DOBJ.Pobj.List) { var dl = pobj.ToDisplayList(); var vertices = dl.Vertices; GXAttribName[] attrs = new GXAttribName[] { GXAttribName.GX_VA_POS, GXAttribName.GX_VA_NULL }; if (pobj.HasAttribute(GXAttribName.GX_VA_PNMTXIDX)) { attrs = new GXAttribName[] { GXAttribName.GX_VA_PNMTXIDX, GXAttribName.GX_VA_POS, GXAttribName.GX_VA_NULL }; } List <GX_Vertex> newVerties = new List <GX_Vertex>(); var offset = 0; foreach (var prim in dl.Primitives) { var verts = vertices.GetRange(offset, prim.Count); offset += prim.Count; switch (prim.PrimitiveType) { case GXPrimitiveType.Quads: verts = TriangleConverter.QuadToList(verts); break; case GXPrimitiveType.TriangleStrip: verts = TriangleConverter.StripToList(verts); break; case GXPrimitiveType.Triangles: break; default: Console.WriteLine(prim.PrimitiveType); break; } newVerties.AddRange(verts); } // extrude for (int i = 0; i < newVerties.Count; i++) { var v = newVerties[i]; v.POS.X += v.NRM.X * settings.Size; v.POS.Y += v.NRM.Y * settings.Size; v.POS.Z += v.NRM.Z * settings.Size; //v.CLR0.R = settings.Color.R / 255f; //v.CLR0.G = settings.Color.G / 255f; //v.CLR0.B = settings.Color.B / 255f; //v.CLR0.A = settings.Color.A / 255f; newVerties[i] = v; } // invert faces for (int i = 0; i < newVerties.Count; i += 3) { var temp = newVerties[i]; newVerties[i] = newVerties[i + 2]; newVerties[i + 2] = temp; } var newpobj = pobjGen.CreatePOBJsFromTriangleList(newVerties, attrs, dl.Envelopes); foreach (var p in newpobj.List) { p.Flags |= POBJ_FLAG.CULLBACK | POBJ_FLAG.UNKNOWN1; } if (newDOBJ.Pobj == null) { newDOBJ.Pobj = newpobj; } else { newDOBJ.Pobj.Add(newpobj); } } pobjGen.SaveChanges(); return(newDOBJ); }
/// <summary> /// /// </summary> /// <returns></returns> private void ProcessMesh(IOScene scene, IOMesh mesh, HSD_JOBJ rootnode) { HSD_JOBJ parent = rootnode; HashSet <HSD_JOBJ> nodes = new HashSet <HSD_JOBJ>(); foreach (var j in rootnode.BreathFirstList) { nodes.Add(j); } if (mesh.ParentBone != null && _cache.NameToJOBJ.ContainsKey(mesh.ParentBone.Name)) { parent = _cache.NameToJOBJ[mesh.ParentBone.Name]; } HSD_DOBJ root = null; HSD_DOBJ prev = null; //var skeleton = rootnode.BreathFirstList; Console.WriteLine("Processing " + mesh.Name); bool singleBinded = mesh.Name.Contains("SINGLE"); foreach (var poly in mesh.Polygons) { // Skip Empty Polygon if (poly.Indicies.Count == 0) { continue; } // convert to triangles poly.ToTriangles(mesh); if (poly.PrimitiveType != IOPrimitive.TRIANGLE) { continue; } // Generate DOBJ HSD_DOBJ dobj = new HSD_DOBJ(); if (Settings.ImportMeshNames) { dobj.ClassName = mesh.Name; } if (root == null) { root = dobj; } else { prev.Next = dobj; } prev = dobj; // generate material var material = scene.Materials.Find(e => e.Name == poly.MaterialName); dobj.Mobj = GenerateMaterial(material); Console.WriteLine(mesh.Name + " " + material?.Name); // reflective mobjs do not use uvs var hasReflection = false; // bump maps need tangents and bitangents var hasBump = false; // Assess needed attributes based on the material MOBJ if (mesh.Name.Contains("REFLECTIVE")) { hasReflection = true; } #if DEBUG if (Settings.MetalModel) { hasReflection = true; } #endif if (mesh.Name.Contains("BUMP")) { hasBump = true; } if (dobj.Mobj.Textures != null) { foreach (var t in dobj.Mobj.Textures.List) { if (t.Flags.HasFlag(TOBJ_FLAGS.COORD_REFLECTION)) { hasReflection = true; } if (t.Flags.HasFlag(TOBJ_FLAGS.BUMP)) { hasBump = true; } } } // assess attributes List <GXAttribName> Attributes = new List <GXAttribName>(); if (mesh.HasEnvelopes() && Settings.ImportRigging && !singleBinded) { Attributes.Add(GXAttribName.GX_VA_PNMTXIDX); if (hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX0MTXIDX); if (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 1) { Attributes.Add(GXAttribName.GX_VA_TEX1MTXIDX); } #if DEBUG if (Settings.MetalModel && !Attributes.Contains(GXAttribName.GX_VA_TEX1MTXIDX)) { Attributes.Add(GXAttribName.GX_VA_TEX1MTXIDX); } #endif } } Attributes.Add(GXAttribName.GX_VA_POS); if (hasBump) { Attributes.Add(GXAttribName.GX_VA_NBT); } else if (mesh.HasNormals && Settings.ImportNormals) { Attributes.Add(GXAttribName.GX_VA_NRM); } if (mesh.HasColorSet(0) && Settings.ImportVertexColor) { Attributes.Add(GXAttribName.GX_VA_CLR0); } if (mesh.HasColorSet(1) && Settings.ImportVertexColor) { Attributes.Add(GXAttribName.GX_VA_CLR1); } if (mesh.HasUVSet(0) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX0); } if ((mesh.HasUVSet(1) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 1)) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX1); } if ((mesh.HasUVSet(2) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 2)) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX2); } if ((mesh.HasUVSet(3) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 3)) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX3); } if ((mesh.HasUVSet(4) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 4)) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX4); } if ((mesh.HasUVSet(5) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 5)) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX5); } if ((mesh.HasUVSet(6) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 6)) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX6); } if ((mesh.HasUVSet(7) || (dobj.Mobj.Textures != null && dobj.Mobj.Textures.List.Count > 7)) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX7); } var vertices = new List <GX_Vertex>(); var jobjList = new List <HSD_JOBJ[]>(); var weightList = new List <float[]>(); foreach (var face in poly.Indicies) { var v = mesh.Vertices[face]; GX_Vertex vertex = new GX_Vertex(); var tkvert = new Vector3(v.Position.X, v.Position.Y, v.Position.Z); var tknrm = new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z); var tktan = new Vector3(v.Tangent.X, v.Tangent.Y, v.Tangent.Z); var tkbitan = new Vector3(v.Binormal.X, v.Binormal.Y, v.Binormal.Z); var parentTransform = _cache.jobjToWorldTransform[parent].Inverted(); if (_cache.jobjToWorldTransform[parent] != Matrix4.Identity) { tkvert = Vector3.TransformPosition(tkvert, parentTransform); tknrm = Vector3.TransformNormal(tknrm, parentTransform).Normalized(); tktan = Vector3.TransformNormal(tktan, parentTransform).Normalized(); tkbitan = Vector3.TransformNormal(tkbitan, parentTransform).Normalized(); } if (mesh.HasEnvelopes() && Settings.ImportRigging) { // create weighting lists List <float> weight = new List <float>(); List <HSD_JOBJ> bones = new List <HSD_JOBJ>(); if (v.Envelope.Weights.Count == 0) { weight.Add(1); bones.Add(rootnode); } if (v.Envelope.Weights.Count > 4) { throw new Exception($"Too many weights! {v.Envelope.Weights.Count} in {mesh.Name}"); } foreach (var bw in v.Envelope.Weights) { // check if skeleton actually contains bone if (_cache.NameToJOBJ.ContainsKey(bw.BoneName) && nodes.Contains(_cache.NameToJOBJ[bw.BoneName])) { // add envelope bones.Add(_cache.NameToJOBJ[bw.BoneName]); weight.Add(bw.Weight); // indicate enveloped jobjs if (!_cache.EnvelopedJOBJs.Contains(_cache.NameToJOBJ[bw.BoneName])) { _cache.EnvelopedJOBJs.Add(_cache.NameToJOBJ[bw.BoneName]); } } else { throw new Exception($"Bone not found \"{bw.BoneName}\" Weight: {bw.Weight} in {mesh.Name}"); } } jobjList.Add(bones.ToArray()); weightList.Add(weight.ToArray()); // invert single binds if (v.Envelope.Weights.Count == 1) { var inv = _cache.jobjToWorldTransform[_cache.NameToJOBJ[v.Envelope.Weights[0].BoneName]].Inverted(); tkvert = Vector3.TransformPosition(tkvert, inv); tknrm = Vector3.TransformNormal(tknrm, inv).Normalized(); tktan = Vector3.TransformNormal(tknrm, inv).Normalized(); tkbitan = Vector3.TransformNormal(tknrm, inv).Normalized(); } } vertex.POS = GXTranslator.fromVector3(tkvert); vertex.NRM = GXTranslator.fromVector3(tknrm.Normalized()); vertex.TAN = GXTranslator.fromVector3(tktan); vertex.BITAN = GXTranslator.fromVector3(tkbitan); if (Settings.InvertNormals) { vertex.NRM.X *= -1; vertex.NRM.Y *= -1; vertex.NRM.Z *= -1; vertex.TAN.X *= -1; vertex.TAN.Y *= -1; vertex.TAN.Z *= -1; vertex.BITAN.X *= -1; vertex.BITAN.Y *= -1; vertex.BITAN.Z *= -1; } if (mesh.HasUVSet(0)) { vertex.TEX0 = new GXVector2(v.UVs[0].X, v.UVs[0].Y); } if (mesh.HasUVSet(1)) { vertex.TEX1 = new GXVector2(v.UVs[1].X, v.UVs[1].Y); } if (mesh.HasUVSet(2)) { vertex.TEX2 = new GXVector2(v.UVs[2].X, v.UVs[2].Y); } if (mesh.HasUVSet(3)) { vertex.TEX3 = new GXVector2(v.UVs[3].X, v.UVs[3].Y); } if (mesh.HasUVSet(4)) { vertex.TEX4 = new GXVector2(v.UVs[4].X, v.UVs[4].Y); } if (mesh.HasUVSet(5)) { vertex.TEX5 = new GXVector2(v.UVs[5].X, v.UVs[5].Y); } if (mesh.HasUVSet(6)) { vertex.TEX6 = new GXVector2(v.UVs[6].X, v.UVs[6].Y); } if (mesh.HasUVSet(7)) { vertex.TEX7 = new GXVector2(v.UVs[7].X, v.UVs[7].Y); } if (mesh.HasColorSet(0)) { vertex.CLR0 = new GXColor4( v.Colors[0].X * (Settings.MultiplyVertexColorBy2 ? 2 : 1), v.Colors[0].Y * (Settings.MultiplyVertexColorBy2 ? 2 : 1), v.Colors[0].Z * (Settings.MultiplyVertexColorBy2 ? 2 : 1), Settings.ImportVertexAlpha ? v.Colors[0].W : 1); } if (mesh.HasColorSet(1)) { vertex.CLR1 = new GXColor4( v.Colors[1].X * (Settings.MultiplyVertexColorBy2 ? 2 : 1), v.Colors[1].Y * (Settings.MultiplyVertexColorBy2 ? 2 : 1), v.Colors[1].Z * (Settings.MultiplyVertexColorBy2 ? 2 : 1), Settings.ImportVertexAlpha ? v.Colors[1].W : 1); } vertices.Add(vertex); } // generate pobjs HSD_POBJ pobj = null; if (mesh.HasEnvelopes() && Settings.ImportRigging && !singleBinded) { pobj = _cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), jobjList, weightList); } else { pobj = _cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), null); } if (singleBinded && jobjList.Count > 0 && jobjList[0].Length > 0) { parent = jobjList[0][0]; } if (pobj != null) { if (dobj.Pobj == null) { dobj.Pobj = pobj; } else { dobj.Pobj.Add(pobj); } } } if (parent.Dobj == null) { parent.Dobj = root; } else { parent.Dobj.Add(root); } }
/// <summary> /// /// </summary> /// <returns></returns> private static HSD_DOBJ GetMeshes(ProcessingCache cache, ModelImportSettings settings, Scene scene, Node node) { HSD_DOBJ root = null; HSD_DOBJ prev = null; Console.WriteLine("Processing " + node.Name); foreach (int index in node.MeshIndices) { Mesh mesh = scene.Meshes[index]; var material = scene.Materials[mesh.MaterialIndex]; Console.WriteLine(mesh.Name + " " + material.Name); // Generate DOBJ HSD_DOBJ dobj = new HSD_DOBJ(); // hack to make dobjs merged by texture if (settings.ImportTexture && settings.ForceMergeObjects == ForceGroupModes.Texture && material.HasTextureDiffuse && cache.TextureToDOBJ.ContainsKey(material.TextureDiffuse.FilePath)) { dobj = cache.TextureToDOBJ[material.TextureDiffuse.FilePath]; } else { if (root == null) { root = dobj; } else { prev.Next = dobj; } prev = dobj; dobj.Mobj = GenerateMaterial(cache, settings, material); if (settings.ForceMergeObjects == ForceGroupModes.Texture && material.HasTextureDiffuse && settings.ImportTexture) { cache.TextureToDOBJ.Add(material.TextureDiffuse.FilePath, dobj); } } if (root != null && settings.ForceMergeObjects == ForceGroupModes.MeshGroup) { dobj = root; } // Assessment if (!mesh.HasFaces) { continue; } // Assess needed attributes based on the material MOBJ // reflective mobjs do not use uvs var hasReflection = false; // bump maps need tangents and bitangents var hasBump = false; if (dobj.Mobj.Textures != null) { foreach (var t in dobj.Mobj.Textures.List) { if (t.Flags.HasFlag(TOBJ_FLAGS.COORD_REFLECTION)) { hasReflection = true; } if (t.Flags.HasFlag(TOBJ_FLAGS.BUMP)) { hasBump = true; } } } List <GXAttribName> Attributes = new List <GXAttribName>(); // todo: rigging List <HSD_JOBJ>[] jobjs = new List <HSD_JOBJ> [mesh.Vertices.Count]; List <float>[] weights = new List <float> [mesh.Vertices.Count]; if (mesh.HasBones) { Attributes.Add(GXAttribName.GX_VA_PNMTXIDX); foreach (var v in mesh.Bones) { var jobj = cache.NameToJOBJ[v.Name]; if (!cache.EnvelopedJOBJs.Contains(jobj)) { cache.EnvelopedJOBJs.Add(jobj); } if (v.HasVertexWeights) { foreach (var vw in v.VertexWeights) { if (jobjs[vw.VertexID] == null) { jobjs[vw.VertexID] = new List <HSD_JOBJ>(); } if (weights[vw.VertexID] == null) { weights[vw.VertexID] = new List <float>(); } if (vw.Weight > 0) { jobjs[vw.VertexID].Add(jobj); weights[vw.VertexID].Add(vw.Weight); } } } } } if (hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX0MTXIDX); } if (mesh.HasVertices) { Attributes.Add(GXAttribName.GX_VA_POS); } if (mesh.HasVertexColors(0) && settings.ShadingType == ShadingType.VertexColor) { Attributes.Add(GXAttribName.GX_VA_CLR0); } //if (mesh.HasVertexColors(1) && settings.ImportVertexColors) // Attributes.Add(GXAttribName.GX_VA_CLR1); if (!hasBump && mesh.HasNormals && settings.ShadingType == ShadingType.Material) { Attributes.Add(GXAttribName.GX_VA_NRM); } if (hasBump) { Attributes.Add(GXAttribName.GX_VA_NBT); } if (mesh.HasTextureCoords(0) && !hasReflection) { Attributes.Add(GXAttribName.GX_VA_TEX0); } //if (mesh.HasTextureCoords(1)) // Attributes.Add(GXAttribName.GX_VA_TEX1); var vertices = new List <GX_Vertex>(); var jobjList = new List <HSD_JOBJ[]>(vertices.Count); var wList = new List <float[]>(vertices.Count); foreach (var face in mesh.Faces) { PrimitiveType faceMode; switch (face.IndexCount) { case 1: faceMode = PrimitiveType.Point; break; case 2: faceMode = PrimitiveType.Line; break; case 3: faceMode = PrimitiveType.Triangle; break; default: faceMode = PrimitiveType.Polygon; break; } if (faceMode != PrimitiveType.Triangle) { continue; //throw new NotSupportedException($"Non triangle primitive types not supported at this time {faceMode}"); } for (int i = 0; i < face.IndexCount; i++) { int indicie = face.Indices[i]; GX_Vertex vertex = new GX_Vertex(); if (mesh.HasBones) { jobjList.Add(jobjs[indicie].ToArray()); wList.Add(weights[indicie].ToArray()); // Single Binds Get Inverted var tkvert = new Vector3(mesh.Vertices[indicie].X, mesh.Vertices[indicie].Y, mesh.Vertices[indicie].Z) * settings.Scale; var tknrm = new Vector3(mesh.Normals[indicie].X, mesh.Normals[indicie].Y, mesh.Normals[indicie].Z); Vector3 tktan = Vector3.Zero; Vector3 tkbitan = Vector3.Zero; if (mesh.HasTangentBasis) { tktan = new Vector3(mesh.Tangents[indicie].X, mesh.Tangents[indicie].Y, mesh.Tangents[indicie].Z); tkbitan = new Vector3(mesh.BiTangents[indicie].X, mesh.BiTangents[indicie].Y, mesh.BiTangents[indicie].Z); } if (jobjs[indicie].Count == 1 || weights[indicie][0] == 1) { tkvert = Vector3.TransformPosition(tkvert, cache.jobjToInverseTransform[jobjs[indicie][0]]); tknrm = Vector3.TransformNormal(tknrm, cache.jobjToInverseTransform[jobjs[indicie][0]]); if (mesh.HasTangentBasis) { tktan = Vector3.TransformNormal(tktan, cache.jobjToInverseTransform[jobjs[indicie][0]]); tkbitan = Vector3.TransformNormal(tkbitan, cache.jobjToInverseTransform[jobjs[indicie][0]]); } } vertex.POS = GXTranslator.fromVector3(tkvert); vertex.NRM = GXTranslator.fromVector3(tknrm); vertex.TAN = GXTranslator.fromVector3(tktan); vertex.BITAN = GXTranslator.fromVector3(tkbitan); } else { if (mesh.HasVertices) { vertex.POS = new GXVector3(mesh.Vertices[indicie].X * settings.Scale, mesh.Vertices[indicie].Y * settings.Scale, mesh.Vertices[indicie].Z * settings.Scale); } if (mesh.HasNormals) { vertex.NRM = new GXVector3(mesh.Normals[indicie].X, mesh.Normals[indicie].Y, mesh.Normals[indicie].Z); } if (mesh.HasTangentBasis) { vertex.TAN = new GXVector3(mesh.Tangents[indicie].X, mesh.Tangents[indicie].Y, mesh.Tangents[indicie].Z); vertex.BITAN = new GXVector3(mesh.BiTangents[indicie].X, mesh.BiTangents[indicie].Y, mesh.BiTangents[indicie].Z); } } if (settings.InvertNormals) { vertex.NRM.X *= -1; vertex.NRM.Y *= -1; vertex.NRM.Z *= -1; } if (mesh.HasTextureCoords(0)) { vertex.TEX0 = new GXVector2( mesh.TextureCoordinateChannels[0][indicie].X, mesh.TextureCoordinateChannels[0][indicie].Y); } if (mesh.HasTextureCoords(1)) { vertex.TEX1 = new GXVector2( mesh.TextureCoordinateChannels[1][indicie].X, mesh.TextureCoordinateChannels[1][indicie].Y); } if (mesh.HasVertexColors(0)) { vertex.CLR0 = new GXColor4( mesh.VertexColorChannels[0][indicie].R, mesh.VertexColorChannels[0][indicie].G, mesh.VertexColorChannels[0][indicie].B, settings.ImportVertexAlpha ? mesh.VertexColorChannels[0][indicie].A : 1); } if (mesh.HasVertexColors(1)) { vertex.CLR0 = new GXColor4( mesh.VertexColorChannels[1][indicie].R, mesh.VertexColorChannels[1][indicie].G, mesh.VertexColorChannels[1][indicie].B, settings.ImportVertexAlpha ? mesh.VertexColorChannels[1][indicie].A : 1); } vertices.Add(vertex); } } HSD_POBJ pobj = null; if (mesh.HasBones) { pobj = cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), jobjList, wList); } else { pobj = cache.POBJGen.CreatePOBJsFromTriangleList(vertices, Attributes.ToArray(), null); } if (pobj != null) { if (dobj.Pobj == null) { dobj.Pobj = pobj; } else { dobj.Pobj.Add(pobj); } } } return(root); }
public DOBJHandler(HSD_DOBJ dobj) { _dobj = dobj; }
/// <summary> /// /// </summary> /// <param name="dobj"></param> /// <returns></returns> public bool BindBuffer(Shader GXShader, HSD_DOBJ dobj, int shapeset1, int shapeset2, float blend) { if (!attributeToBuffer.ContainsKey(dobj)) { return(false); } GXShader.SetFloat("shape_blend", blend); // normal attributes GL.BindBuffer(BufferTarget.ArrayBuffer, attributeToBuffer[dobj]); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("PNMTXIDX"), 1, VertexAttribPointerType.Short, false, GX_Vertex.Stride, 0); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 8); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 20); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_BTAN")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_TAN"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 32); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TAN")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_BTAN"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 44); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_CLR0")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_CLR0"), 4, VertexAttribPointerType.Float, true, GX_Vertex.Stride, 56); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX0"), 2, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 88); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX1")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX1"), 2, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 96); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX2")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX2"), 2, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 104); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX3")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_TEX3"), 2, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 112); // shape sets (if exists) if (dobjToShapes.ContainsKey(dobj)) { if (shapeset1 < dobjToShapes[dobj].Length) { GL.BindBuffer(BufferTarget.ArrayBuffer, dobjToShapes[dobj][shapeset1]); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS"), 3, VertexAttribPointerType.Float, false, GX_Shape.Stride, 0); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM"), 3, VertexAttribPointerType.Float, false, GX_Shape.Stride, 12); } if (shapeset2 < dobjToShapes[dobj].Length) { GL.BindBuffer(BufferTarget.ArrayBuffer, dobjToShapes[dobj][shapeset2]); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS_SHAPE")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS_SHAPE"), 3, VertexAttribPointerType.Float, false, GX_Shape.Stride, 0); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM_SHAPE")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM_SHAPE"), 3, VertexAttribPointerType.Float, false, GX_Shape.Stride, 12); } } else { GL.BindBuffer(BufferTarget.ArrayBuffer, attributeToBuffer[dobj]); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS_SHAPE")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_POS_SHAPE"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 8); GL.EnableVertexAttribArray(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM_SHAPE")); GL.VertexAttribPointer(GXShader.GetVertexAttributeUniformLocation("GX_VA_NRM_SHAPE"), 3, VertexAttribPointerType.Float, false, GX_Vertex.Stride, 20); } return(true); }