private void brgMeshFormatCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) { if (this.brgObjectsTreeListView.SelectedObject == null || !(this.brgObjectsTreeListView.SelectedObject is BrgMesh)) { return; } brgMeshFormatCheckedListBox.ItemCheck -= brgMeshFormatCheckedListBox_ItemCheck; BrgMesh mesh = (BrgMesh)this.brgObjectsTreeListView.SelectedObject; mesh.Header.Format = this.brgMeshFormatCheckedListBox.GetEnum <BrgMeshFormat>(); if (e.NewValue == CheckState.Checked) { mesh.Header.Format |= (BrgMeshFormat)this.brgMeshFormatCheckedListBox.Items[e.Index]; } else { mesh.Header.Format &= ~(BrgMeshFormat)this.brgMeshFormatCheckedListBox.Items[e.Index]; } brg.File.UpdateMeshSettings(mesh.Header.Flags, mesh.Header.Format, mesh.Header.AnimationType, mesh.Header.InterpolationType); this.brgMeshFormatCheckedListBox.SetEnum <BrgMeshFormat>(mesh.Header.Format); brgMeshFormatCheckedListBox.ItemCheck += brgMeshFormatCheckedListBox_ItemCheck; }
private void CreateNormalBuffer(BrgMesh mesh, GltfFormatter formatter, Stream bufferStream) { long bufferViewOffset; Vector3 max = new Vector3(float.MinValue); Vector3 min = new Vector3(float.MaxValue); using (BinaryWriter writer = new BinaryWriter(bufferStream, Encoding.UTF8, true)) { // padding writer.Write(new byte[(-bufferStream.Length) & (PaddingBytes(Accessor.ComponentTypeEnum.FLOAT) - 1)]); bufferViewOffset = bufferStream.Length; foreach (int index in Indices) { Vector3 vec = mesh.Normals[index]; vec = vec / vec.Length(); max.X = Math.Max(max.X, vec.X); max.Y = Math.Max(max.Y, vec.Y); max.Z = Math.Max(max.Z, vec.Z); min.X = Math.Min(min.X, vec.X); min.Y = Math.Min(min.Y, vec.Y); min.Z = Math.Min(min.Z, vec.Z); writer.Write(vec.X); writer.Write(vec.Y); writer.Write(vec.Z); } } BufferView posBufferView = new BufferView(); posBufferView.Buffer = 0; posBufferView.ByteLength = Indices.Count * 12; posBufferView.ByteOffset = (int)bufferViewOffset; posBufferView.ByteStride = 12; posBufferView.Name = "normalBufferView"; posBufferView.Target = BufferView.TargetEnum.ARRAY_BUFFER; Accessor posAccessor = new Accessor(); posAccessor.BufferView = formatter.bufferViews.Count; posAccessor.ByteOffset = 0; posAccessor.ComponentType = Accessor.ComponentTypeEnum.FLOAT; posAccessor.Count = Indices.Count; posAccessor.Max = new[] { max.X, max.Y, max.Z }; posAccessor.Min = new[] { min.X, min.Y, min.Z }; posAccessor.Name = "normalBufferViewAccessor"; posAccessor.Type = Accessor.TypeEnum.VEC3; formatter.bufferViews.Add(posBufferView); formatter.accessors.Add(posAccessor); }
private void CreateIndexBuffer(BrgMesh mesh, GltfFormatter formatter, Stream bufferStream) { long bufferViewOffset; short faceMin = short.MaxValue; short faceMax = short.MinValue; using (BinaryWriter writer = new BinaryWriter(bufferStream, Encoding.UTF8, true)) { // padding writer.Write(new byte[(-bufferStream.Length) & (PaddingBytes(Accessor.ComponentTypeEnum.UNSIGNED_SHORT) - 1)]); bufferViewOffset = bufferStream.Length; foreach (var face in Faces) { faceMin = Math.Min(faceMin, face.Indices[0]); faceMin = Math.Min(faceMin, face.Indices[1]); faceMin = Math.Min(faceMin, face.Indices[2]); faceMax = Math.Max(faceMax, face.Indices[0]); faceMax = Math.Max(faceMax, face.Indices[1]); faceMax = Math.Max(faceMax, face.Indices[2]); writer.Write(face.Indices[0]); writer.Write(face.Indices[1]); writer.Write(face.Indices[2]); } } BufferView indexBufferView = new BufferView(); indexBufferView.Buffer = 0; indexBufferView.ByteLength = Faces.Count * 6; indexBufferView.ByteOffset = (int)bufferViewOffset; indexBufferView.Name = "indexBufferView"; indexBufferView.Target = BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER; Accessor indexAccessor = new Accessor(); indexAccessor.BufferView = formatter.bufferViews.Count; indexAccessor.ByteOffset = 0; indexAccessor.ComponentType = Accessor.ComponentTypeEnum.UNSIGNED_SHORT; indexAccessor.Count = Faces.Count * 3; indexAccessor.Max = new[] { (float)faceMax }; indexAccessor.Min = new[] { (float)faceMin }; indexAccessor.Name = "indexBufferViewAccessor"; indexAccessor.Type = Accessor.TypeEnum.SCALAR; formatter.bufferViews.Add(indexBufferView); formatter.accessors.Add(indexAccessor); }
public void Serialize(MeshPrimitive primitive, BrgMesh mesh, GltfFormatter formatter, Stream bufferStream) { if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { primitive.Mode = MeshPrimitive.ModeEnum.TRIANGLES; CreateIndexBuffer(mesh, formatter, bufferStream); primitive.Indices = formatter.accessors.Count - 1; primitive.Attributes = CreateAttributes(mesh, formatter, bufferStream); } else { Targets.Add(CreateAttributes(mesh, formatter, bufferStream)); } }
private Dictionary <string, int> CreateAttributes(BrgMesh mesh, GltfFormatter formatter, Stream bufferStream) { var attributes = new Dictionary <string, int>(); CreatePositionBuffer(mesh, formatter, bufferStream); int posAccessor = formatter.accessors.Count - 1; attributes.Add("POSITION", posAccessor); CreateNormalBuffer(mesh, formatter, bufferStream); int normAccessor = formatter.accessors.Count - 1; attributes.Add("NORMAL", normAccessor); return(attributes); }
private void brgMeshAnimTypeRadioButton_CheckedChanged(object sender, EventArgs e) { if (this.brgObjectsTreeListView.SelectedObject == null || !(this.brgObjectsTreeListView.SelectedObject is BrgMesh)) { return; } keyframeRadioButton.CheckedChanged -= brgMeshAnimTypeRadioButton_CheckedChanged; nonuniRadioButton.CheckedChanged -= brgMeshAnimTypeRadioButton_CheckedChanged; skinBoneRadioButton.CheckedChanged -= brgMeshAnimTypeRadioButton_CheckedChanged; BrgMesh mesh = (BrgMesh)this.brgObjectsTreeListView.SelectedObject; if (this.keyframeRadioButton.Checked) { mesh.Header.AnimationType = BrgMeshAnimType.KeyFrame; } else if (this.nonuniRadioButton.Checked) { mesh.Header.AnimationType = BrgMeshAnimType.NonUniform; } else if (this.skinBoneRadioButton.Checked) { mesh.Header.AnimationType = BrgMeshAnimType.SkinBone; } brg.File.UpdateMeshSettings(mesh.Header.Flags, mesh.Header.Format, mesh.Header.AnimationType, mesh.Header.InterpolationType); if (mesh.Header.AnimationType == BrgMeshAnimType.KeyFrame) { this.keyframeRadioButton.Checked = true; } else if (mesh.Header.AnimationType == BrgMeshAnimType.NonUniform) { this.nonuniRadioButton.Checked = true; } else if (mesh.Header.AnimationType == BrgMeshAnimType.SkinBone) { this.skinBoneRadioButton.Checked = true; } keyframeRadioButton.CheckedChanged += brgMeshAnimTypeRadioButton_CheckedChanged; nonuniRadioButton.CheckedChanged += brgMeshAnimTypeRadioButton_CheckedChanged; skinBoneRadioButton.CheckedChanged += brgMeshAnimTypeRadioButton_CheckedChanged; }
private void brgMeshInterpolationTypeCheckBox_CheckStateChanged(object sender, EventArgs e) { if (this.brgObjectsTreeListView.SelectedObject == null || !(this.brgObjectsTreeListView.SelectedObject is BrgMesh)) { return; } interpolationTypeCheckBox.CheckStateChanged -= brgMeshInterpolationTypeCheckBox_CheckStateChanged; BrgMesh mesh = (BrgMesh)this.brgObjectsTreeListView.SelectedObject; mesh.Header.InterpolationType = (BrgMeshInterpolationType)Convert.ToByte(this.interpolationTypeCheckBox.Checked); brg.File.UpdateMeshSettings(mesh.Header.Flags, mesh.Header.Format, mesh.Header.AnimationType, mesh.Header.InterpolationType); this.interpolationTypeCheckBox.Checked = Convert.ToBoolean(mesh.Header.InterpolationType); interpolationTypeCheckBox.CheckStateChanged += brgMeshInterpolationTypeCheckBox_CheckStateChanged; }
public void LoadMeshUI() { BrgMesh mesh = (BrgMesh)this.Plugin.brgObjectsTreeListView.SelectedObject; this.Plugin.interpolationTypeCheckBox.Checked = Convert.ToBoolean(mesh.Header.InterpolationType); this.Plugin.brgMeshFlagsCheckedListBox.SetEnum <BrgMeshFlag>(mesh.Header.Flags); this.Plugin.brgMeshFormatCheckedListBox.SetEnum <BrgMeshFormat>(mesh.Header.Format); if (mesh.Header.AnimationType == BrgMeshAnimType.KeyFrame) { this.Plugin.keyframeRadioButton.Checked = true; } else if (mesh.Header.AnimationType == BrgMeshAnimType.NonUniform) { this.Plugin.nonuniRadioButton.Checked = true; } else if (mesh.Header.AnimationType == BrgMeshAnimType.SkinBone) { this.Plugin.skinBoneRadioButton.Checked = true; } }
public void Import(string fileName) { // Only need to Update the HEADER, and Animation.Duration, ASETHEADER is auto handled this.File = new BrgFile(); BrgFile model = this.File; // just ref here so I don't have to rename model to this.File Grendgine_Collada cModel = Grendgine_Collada.Grendgine_Load_File(fileName); //Materials BrgMaterial mat = new BrgMaterial(model); model.Materials.Add(mat); mat.AmbientColor = new Color3D(); mat.DiffuseColor = new Color3D(); mat.SpecularColor = new Color3D(0.5f); mat.SpecularExponent = 5; mat.Id = 100; mat.Opacity = 1f; mat.Flags |= BrgMatFlag.HasTexture | BrgMatFlag.SpecularExponent; model.Header.NumMaterials = model.Materials.Count(); //Meshes foreach (Grendgine_Collada_Geometry geo in cModel.Library_Geometries.Geometry) { BrgMesh mesh = new BrgMesh(model); model.Meshes.Add(mesh); mesh.Header.Flags |= BrgMeshFlag.MATERIAL; mesh.Header.Flags |= model.Meshes.Count == 1 ? 0 : BrgMeshFlag.SECONDARYMESH; mesh.Header.AnimationType |= BrgMeshAnimType.KeyFrame; mesh.Header.Format |= 0; mesh.ExtendedHeader.NumMaterials = (byte)model.Header.NumMaterials; mesh.ExtendedHeader.AnimationLength = 30; mesh.ExtendedHeader.NumUniqueMaterials = 0; string polyVertSourceID; string polyNormalsSourceID; string materialID; int[] vertCountPerPoly; int[] vertLinkPerPoly; int[] vertNormalBindings; //Locate the vertices and convert them string vertexPosSourceID = geo.Mesh.Vertices.Input.First <Grendgine_Collada_Input_Unshared>(x => x.Semantic == Grendgine_Collada_Input_Semantic.POSITION).source; Grendgine_Collada_Float_Array vertsArray = FindSourceByID(geo.Mesh, vertexPosSourceID).Float_Array; mesh.Vertices = FloatToVectorArray(vertsArray); mesh.Header.NumVertices = (short)mesh.Vertices.Count; //Check for polygons otherwise skip mesh if (geo.Mesh.Polylist != null || geo.Mesh.Polylist.Length > 0) { mesh.Header.NumFaces = (short)geo.Mesh.Polylist[0].Count; polyVertSourceID = geo.Mesh.Polylist[0].Input.First <Grendgine_Collada_Input_Unshared>(x => x.Semantic == Grendgine_Collada_Input_Semantic.VERTEX).source; polyNormalsSourceID = geo.Mesh.Polylist[0].Input.First <Grendgine_Collada_Input_Unshared>(x => x.Semantic == Grendgine_Collada_Input_Semantic.NORMAL).source; vertCountPerPoly = geo.Mesh.Polylist[0].VCount.Value(); materialID = geo.Mesh.Polylist[0].Material; vertLinkPerPoly = geo.Mesh.Polylist[0].P.Value(); mesh.Faces = new List <Face>(mesh.Header.NumFaces); vertNormalBindings = new int[mesh.Header.NumVertices]; int polyindex = 0; Face ff; foreach (int count in vertCountPerPoly) { if (count == 3) //If triangle { ff = new Face(); ff.Indices = new List <short>(3); ff.Indices.Add((short)vertLinkPerPoly[polyindex]); ff.Indices.Add((short)vertLinkPerPoly[polyindex + 4]); ff.Indices.Add((short)vertLinkPerPoly[polyindex + 2]); //List correct normal bindings vertNormalBindings[ff.Indices[0]] = vertLinkPerPoly[polyindex + 1]; vertNormalBindings[ff.Indices[1]] = vertLinkPerPoly[polyindex + 5]; vertNormalBindings[ff.Indices[2]] = vertLinkPerPoly[polyindex + 3]; //Bind materials if (mesh.Header.Flags.HasFlag(BrgMeshFlag.MATERIAL)) { ff.MaterialIndex = (short)mat.Id; } mesh.Faces.Add(ff); } polyindex += count * 2; //Including face normal bindings } } else { break; } //Locate the vertex normals Grendgine_Collada_Float_Array normalsArray = FindSourceByID(geo.Mesh, polyNormalsSourceID).Float_Array; if (normalsArray.Count != vertsArray.Count) { System.Windows.Forms.MessageBox.Show("The mesh hash only face normals instead of vertex normals. Be sure to export only smooth shaded models.", "Model Import Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Warning); } List <Vector3D> unsortedNormals = FloatToVectorArray(normalsArray); mesh.Normals = new List <Vector3D>(mesh.Header.NumVertices); for (int i = 0; i < mesh.Header.NumVertices; i++) { mesh.Normals.Add(unsortedNormals[vertNormalBindings[i]]); } mesh.VertexMaterials = new List <short>(mesh.Header.NumVertices); for (int i = 0; i < mesh.Header.NumVertices; i++) { mesh.VertexMaterials.Add((short)mat.Id); } } model.Header.NumMeshes = model.Meshes.Count(); }
private void ExportAttachpoints(string attachDummy, BrgMesh mesh, float time) { time += Maxscript.QueryFloat("animationRange.start.ticks / 4800.0"); //System.Windows.Forms.MessageBox.Show("4"); int numAttachpoints = Maxscript.QueryInteger("{0}.count", attachDummy); //System.Windows.Forms.MessageBox.Show("5 " + numAttachpoints); if (mesh.Header.Flags.HasFlag(BrgMeshFlag.ATTACHPOINTS)) { mesh.Attachpoints = new List <BrgAttachpoint>(); for (int i = 0; i < numAttachpoints; i++) { string aName = Maxscript.QueryString("{0}[{1}].name", attachDummy, i + 1); int nameId; if (!BrgAttachpoint.TryGetIdByName(aName.Substring(6), out nameId)) { continue; } BrgAttachpoint att = new BrgAttachpoint(); //System.Windows.Forms.MessageBox.Show(aName); //System.Windows.Forms.MessageBox.Show("5.1"); //System.Windows.Forms.MessageBox.Show(mesh.Attachpoints.Count + " " + i); att.NameId = nameId; Maxscript.Command("{0}[{1}].name = \"{2}\"", attachDummy, i + 1, att.GetMaxName()); //System.Windows.Forms.MessageBox.Show("5.2"); Maxscript.SetVarAtTime(time, "{0}Transform", "{0}[{1}].rotation as matrix3", attachDummy, i + 1); Maxscript.SetVarAtTime(time, "{0}Position", "{0}[{1}].position", attachDummy, i + 1); Maxscript.SetVarAtTime(time, "{0}Scale", "{0}[{1}].scale * {0}[{1}].boxsize", attachDummy, i + 1); //System.Windows.Forms.MessageBox.Show("5.3"); Vector3 scale = new Vector3(Maxscript.QueryFloat("{0}Scale.X", attachDummy), Maxscript.QueryFloat("{0}Scale.Y", attachDummy), Maxscript.QueryFloat("{0}Scale.Z", attachDummy)); Vector3 bBox = scale / 2; //System.Windows.Forms.MessageBox.Show("5.4"); att.XVector.X = -Maxscript.QueryFloat("{0}Transform[1].z", attachDummy); att.XVector.Y = Maxscript.QueryFloat("{0}Transform[3].z", attachDummy); att.XVector.Z = -Maxscript.QueryFloat("{0}Transform[2].z", attachDummy); att.YVector.X = -Maxscript.QueryFloat("{0}Transform[1].y", attachDummy); att.YVector.Y = Maxscript.QueryFloat("{0}Transform[3].y", attachDummy); att.YVector.Z = -Maxscript.QueryFloat("{0}Transform[2].y", attachDummy); att.ZVector.X = -Maxscript.QueryFloat("{0}Transform[1].x", attachDummy); att.ZVector.Y = Maxscript.QueryFloat("{0}Transform[3].x", attachDummy); att.ZVector.Z = -Maxscript.QueryFloat("{0}Transform[2].x", attachDummy); att.Position.X = -Maxscript.QueryFloat("{0}Position.x", attachDummy); att.Position.Z = -Maxscript.QueryFloat("{0}Position.y", attachDummy); att.Position.Y = Maxscript.QueryFloat("{0}Position.z", attachDummy); //System.Windows.Forms.MessageBox.Show("5.5"); att.BoundingBoxMin.X = -bBox.X; att.BoundingBoxMin.Z = -bBox.Y; att.BoundingBoxMin.Y = -bBox.Z; att.BoundingBoxMax.X = bBox.X; att.BoundingBoxMax.Z = bBox.Y; att.BoundingBoxMax.Y = bBox.Z; mesh.Attachpoints.Add(att); } //System.Windows.Forms.MessageBox.Show("# Atpts: " + Attachpoint.Count); } }
private void ExportBrgMesh(string mainObject, BrgMesh mesh, float time, Dictionary <int, int> matIdMapping) { time += Maxscript.QueryFloat("animationRange.start.ticks / 4800.0"); string mainMesh = "mainMesh"; string mainObjectName = Maxscript.QueryString("{0}.name", mainObject); // Figure out the proper data to import if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { Maxscript.Command("{0} = ExportPreservedTexCoordData (GetMeshSnapshotAtTime {1} {2})", mainMesh, mainObject, time); } else { Maxscript.Command("{0} = GetMeshSnapshotAtTime {1} {2}", mainMesh, mainObject, time); } Maxscript.Command("ExportBrgVertNormals {0}", time); Maxscript.SetVarAtTime(time, "meshCenter", "{0}.center", mainObject); mesh.Header.CenterPosition = new Vector3 ( -Maxscript.QueryFloat("meshCenter.x"), Maxscript.QueryFloat("meshCenter.z"), -Maxscript.QueryFloat("meshCenter.y") ); Maxscript.Command("grnd = getNodeByName \"Dummy_hotspot\""); if (!Maxscript.QueryBoolean("grnd == undefined")) { mesh.Header.HotspotPosition = new Vector3 ( -Maxscript.QueryFloat("grnd.position.x"), Maxscript.QueryFloat("grnd.position.z"), -Maxscript.QueryFloat("grnd.position.y") ); } Maxscript.SetVarAtTime(time, "{0}BBMax", "{0}.max", mainObject); Maxscript.SetVarAtTime(time, "{0}BBMin", "{0}.min", mainObject); Vector3 bBoxMax = new Vector3(Maxscript.QueryFloat("{0}BBMax.X", mainObject), Maxscript.QueryFloat("{0}BBMax.Y", mainObject), Maxscript.QueryFloat("{0}BBMax.Z", mainObject)); Vector3 bBoxMin = new Vector3(Maxscript.QueryFloat("{0}BBMin.X", mainObject), Maxscript.QueryFloat("{0}BBMin.Y", mainObject), Maxscript.QueryFloat("{0}BBMin.Z", mainObject)); Vector3 bBox = (bBoxMax - bBoxMin) / 2; mesh.Header.MinimumExtent = new Vector3(-bBox.X, -bBox.Z, -bBox.Y); mesh.Header.MaximumExtent = new Vector3(bBox.X, bBox.Z, bBox.Y); int numVertices = Maxscript.QueryInteger("brgVertIndices.count"); int numFaces = Maxscript.QueryInteger("brgFaceArray.count"); int currNumVertices = mesh.Vertices.Count; //System.Windows.Forms.MessageBox.Show("1 " + numVertices); for (int i = 0; i < numVertices; i++) { //System.Windows.Forms.MessageBox.Show("1.1"); try { Maxscript.Command("vertex = getVert {0} brgVertIndices[{1}]", mainMesh, i + 1); //System.Windows.Forms.MessageBox.Show("1.4"); mesh.Vertices.Add(new Vector3(-Maxscript.QueryFloat("vertex.x"), Maxscript.QueryFloat("vertex.z"), -Maxscript.QueryFloat("vertex.y"))); //System.Windows.Forms.MessageBox.Show("1.5"); mesh.Normals.Add(new Vector3( -Maxscript.QueryFloat("{0}[{1}].x", "averagedNormals", i + 1), Maxscript.QueryFloat("{0}[{1}].z", "averagedNormals", i + 1), -Maxscript.QueryFloat("{0}[{1}].y", "averagedNormals", i + 1))); //System.Windows.Forms.MessageBox.Show("1.7"); } catch (Exception ex) { throw new Exception("In mesh " + mainObjectName + " error exporting verts/normals index " + (i + 1) + ".", ex); } } //System.Windows.Forms.MessageBox.Show("2"); if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH) || mesh.Header.Flags.HasFlag(BrgMeshFlag.ANIMTEXCOORDS)) { if (mesh.Header.Flags.HasFlag(BrgMeshFlag.TEXCOORDSA)) { for (int i = 0; i < numVertices; i++) { Maxscript.Command("tVert = getTVert {0} brgVertTVIndices[{1}]", mainMesh, i + 1); mesh.TextureCoordinates.Add(new Vector3(Maxscript.QueryFloat("tVert.x"), Maxscript.QueryFloat("tVert.y"), 0f)); } } } //System.Windows.Forms.MessageBox.Show("3"); if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { if (mesh.Header.Flags.HasFlag(BrgMeshFlag.MATERIAL)) { mesh.VertexMaterials.AddRange(new Int16[numVertices]); } for (int i = 0; i < numFaces; ++i) { Face f = new Face(); mesh.Faces.Add(f); if (mesh.Header.Flags.HasFlag(BrgMeshFlag.MATERIAL)) { int faceMatId = Maxscript.QueryInteger("getFaceMatId {0} {1}", mainMesh, i + 1); if (matIdMapping.ContainsKey(faceMatId)) { f.MaterialIndex = (Int16)matIdMapping[faceMatId]; } else { throw new Exception("In mesh " + mainObjectName + " face index " + (i + 1) + " has an invalid material id " + faceMatId + "."); } } //System.Windows.Forms.MessageBox.Show("3.1"); Maxscript.Command("face = brgFaceArray[{0}]", i + 1); f.Indices.Add((Int16)(Maxscript.QueryInteger("face.x") - 1 + currNumVertices)); f.Indices.Add((Int16)(Maxscript.QueryInteger("face.z") - 1 + currNumVertices)); f.Indices.Add((Int16)(Maxscript.QueryInteger("face.y") - 1 + currNumVertices)); //System.Windows.Forms.MessageBox.Show("3.2"); if (mesh.Header.Flags.HasFlag(BrgMeshFlag.MATERIAL)) { mesh.VertexMaterials[f.Indices[0]] = f.MaterialIndex; mesh.VertexMaterials[f.Indices[1]] = f.MaterialIndex; mesh.VertexMaterials[f.Indices[2]] = f.MaterialIndex; } } } Maxscript.Command("delete {0}", mainMesh); }
public void Export() { BrgFile brg = this.File; Maxscript.Command("exportStartTime = timeStamp()"); //Maxscript.Command("print heapSize"); BrgMeshFlag flags = brg.Meshes[0].Header.Flags; BrgMeshFormat format = brg.Meshes[0].Header.Format; BrgMeshAnimType animationType = brg.Meshes[0].Header.AnimationType; BrgMeshInterpolationType interpolationType = brg.Meshes[0].Header.InterpolationType; Maxscript.Command("ExportBrgData()"); int totalNumVerts = Maxscript.QueryInteger("brgtotalNumVerts"); int totalNumFaces = Maxscript.QueryInteger("brgtotalNumFaces"); int meshCount = Maxscript.QueryInteger("brgMeshes.count"); if (meshCount == 0) { throw new Exception("No Editable_Mesh objects detected!"); } if (Maxscript.QueryBoolean("keys.Count == 0")) { throw new Exception("Could not acquire animation keys!"); } brg.Header.NumMeshes = Maxscript.QueryInteger("keys.Count"); brg.Animation = new Animation(); for (int i = 1; i <= brg.Header.NumMeshes; ++i) { brg.Animation.MeshKeys.Add(Maxscript.QueryFloat("keys[{0}]", i)); } if (brg.Header.NumMeshes == 1) { brg.Animation.Duration = 0; } else { brg.Animation.Duration = Maxscript.QueryFloat("(animationRange.end.ticks - animationRange.start.ticks) / 4800.0"); } brg.Animation.TimeStep = brg.Animation.Duration / (float)brg.Header.NumMeshes; string mainObject = "mainObject"; brg.Materials = new List <BrgMaterial>(); brg.Meshes = new List <BrgMesh>(brg.Header.NumMeshes); for (int m = 0; m < meshCount; ++m) { Maxscript.Command("{0} = brgMeshes[{1}]", mainObject, m + 1); // Materials Dictionary <int, int> matIdMapping = new Dictionary <int, int>(); if (Maxscript.QueryBoolean("classof {0}.material == Multimaterial", mainObject)) { brg.Header.NumMaterials = Maxscript.QueryInteger("{0}.material.materialList.count", mainObject); for (int i = 0; i < brg.Header.NumMaterials; i++) { BrgMaterial mat = new BrgMaterial(brg); mat.Id = brg.Materials.Count + 1; Maxscript.Command("mat = {0}.material.materialList[{1}]", mainObject, i + 1); this.ExportBrgMaterial(mainObject, mat); int matListIndex = brg.Materials.IndexOf(mat); int actualMatId = Maxscript.QueryInteger("{0}.material.materialIdList[{1}]", mainObject, i + 1); if (matListIndex >= 0) { if (!matIdMapping.ContainsKey(actualMatId)) { matIdMapping.Add(actualMatId, brg.Materials[matListIndex].Id); } } else { brg.Materials.Add(mat); if (matIdMapping.ContainsKey(actualMatId)) { matIdMapping[actualMatId] = mat.Id; } else { matIdMapping.Add(actualMatId, mat.Id); } } } } else if (Maxscript.QueryBoolean("classof {0}.material == Standardmaterial", mainObject)) { BrgMaterial mat = new BrgMaterial(brg); mat.Id = brg.Materials.Count + 1; Maxscript.Command("mat = {0}.material", mainObject); this.ExportBrgMaterial(mainObject, mat); int matListIndex = brg.Materials.IndexOf(mat); if (matListIndex >= 0) { matIdMapping.Add(1, brg.Materials[matListIndex].Id); } else { brg.Materials.Add(mat); matIdMapping.Add(1, mat.Id); } } else { if (flags.HasFlag(BrgMeshFlag.MATERIAL)) { throw new Exception("Not all meshes have a material applied! " + Maxscript.QueryString("{0}.name", mainObject)); } } // Mesh Animations for (int i = 0; i < brg.Header.NumMeshes; i++) { if (i > 0) { if (m == 0) { BrgMesh mesh = new BrgMesh(brg); mesh.Vertices = new List <Vector3>(totalNumVerts); mesh.Normals = new List <Vector3>(totalNumVerts); mesh.TextureCoordinates = new List <Vector3>(totalNumVerts); mesh.Faces = new List <Face>(totalNumFaces); brg.Meshes[0].MeshAnimations.Add(mesh); } brg.UpdateMeshSettings(i, flags, format, animationType, interpolationType); this.ExportBrgMesh(mainObject, (BrgMesh)brg.Meshes[0].MeshAnimations[i - 1], brg.Animation.MeshKeys[i], matIdMapping); } else { if (m == 0) { BrgMesh mesh = new BrgMesh(brg); mesh.Vertices = new List <Vector3>(totalNumVerts); mesh.Normals = new List <Vector3>(totalNumVerts); mesh.TextureCoordinates = new List <Vector3>(totalNumVerts); mesh.Faces = new List <Face>(totalNumFaces); brg.Meshes.Add(mesh); } brg.UpdateMeshSettings(i, flags, format, animationType, interpolationType); this.ExportBrgMesh(mainObject, brg.Meshes[i], brg.Animation.MeshKeys[i], matIdMapping); } } } // Export Attachpoints, and Update some Mesh data HashSet <int> usedFaceMaterials = new HashSet <int>(); string attachDummy = Maxscript.NewArray("attachDummy"); Maxscript.Command("{0} = for helpObj in ($helpers/Dummy_*) where classof helpObj == Dummy collect helpObj", attachDummy);//"$helpers/Dummy_* as array"); for (int i = 0; i < brg.Header.NumMeshes; i++) { BrgMesh mesh; if (i > 0) { mesh = (BrgMesh)brg.Meshes[0].MeshAnimations[i - 1]; } else { mesh = brg.Meshes[i]; } this.ExportAttachpoints(attachDummy, mesh, brg.Animation.MeshKeys[i]); HashSet <int> diffFaceMats = new HashSet <int>(); if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH) && mesh.Header.Flags.HasFlag(BrgMeshFlag.MATERIAL)) { for (int j = 0; j < mesh.Faces.Count; ++j) { diffFaceMats.Add(mesh.Faces[j].MaterialIndex); } if (diffFaceMats.Count > 0) { mesh.ExtendedHeader.NumMaterials = (byte)(diffFaceMats.Count - 1); mesh.ExtendedHeader.NumUniqueMaterials = diffFaceMats.Count; } } usedFaceMaterials.UnionWith(diffFaceMats); mesh.ExtendedHeader.AnimationLength = this.File.Animation.Duration; } List <BrgMaterial> usedMats = new List <BrgMaterial>(brg.Materials.Count); for (int i = 0; i < brg.Materials.Count; ++i) { if (usedFaceMaterials.Contains(brg.Materials[i].Id)) { usedMats.Add(brg.Materials[i]); } } brg.Materials = usedMats; brg.Header.NumMaterials = brg.Materials.Count; //Maxscript.Command("print heapSize"); Maxscript.Command("exportEndTime = timeStamp()"); Maxscript.Format("Export took % seconds\n", "((exportEndTime - exportStartTime) / 1000.0)"); }
private void ImportBrgMesh(string mainObject, BrgMesh mesh, float time) { string vertArray = ""; string normArray = ""; string texVerts = ""; string faceMats = ""; string faceArray = ""; if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { vertArray = Maxscript.NewArray("vertArray"); normArray = Maxscript.NewArray("normArray"); texVerts = Maxscript.NewArray("texVerts"); faceMats = Maxscript.NewArray("faceMats"); faceArray = Maxscript.NewArray("faceArray"); } Maxscript.CommentTitle("Load Vertices/Normals/UVWs"); Maxscript.Command("uvwSetVertPosFunc = {0}.Unwrap_UVW.SetVertexPosition", mainObject); for (int i = 0; i < mesh.Vertices.Count; i++) { if (mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { Maxscript.AnimateAtTime(time, "meshSetVertFunc {0} {1} {2}", mainObject, i + 1, Maxscript.Point3Literal(-mesh.Vertices[i].X, -mesh.Vertices[i].Z, mesh.Vertices[i].Y)); if (mesh.Header.Flags.HasFlag(BrgMeshFlag.ANIMTEXCOORDS) && mesh.Header.Flags.HasFlag(BrgMeshFlag.TEXCOORDSA)) { Maxscript.Animate("uvwSetVertPosFunc {0}s {1} {2}", time, i + 1, Maxscript.Point3Literal(mesh.TextureCoordinates[i].X, mesh.TextureCoordinates[i].Y, 0)); } if (mesh.Header.Flags.HasFlag(BrgMeshFlag.ANIMVERTCOLORALPHA)) { if (mesh.Header.Flags.HasFlag(BrgMeshFlag.COLORALPHACHANNEL)) { Maxscript.AnimateAtTime(time, "meshop.setVertAlpha {0} -2 {1} {2}", mainObject, i + 1, mesh.Colors[i].A); } else if (mesh.Header.Flags.HasFlag(BrgMeshFlag.COLORCHANNEL)) { Maxscript.AnimateAtTime(time, "meshop.setVertColor {0} 0 {1} (color {2} {3} {4})", mainObject, i + 1, mesh.Colors[i].R, mesh.Colors[i].G, mesh.Colors[i].B); } } } else { Maxscript.Append(vertArray, Maxscript.Point3Literal(-mesh.Vertices[i].X, -mesh.Vertices[i].Z, mesh.Vertices[i].Y)); if (mesh.Header.Flags.HasFlag(BrgMeshFlag.TEXCOORDSA)) { Maxscript.Append(texVerts, Maxscript.Point3Literal(mesh.TextureCoordinates[i].X, mesh.TextureCoordinates[i].Y, 0)); } if (mesh.Header.Flags.HasFlag(BrgMeshFlag.COLORALPHACHANNEL)) { //Maxscript.Command("meshop.supportVAlphas {0}", mainObject); Maxscript.Command("meshop.setVertAlpha {0} -2 {1} {2}", mainObject, i + 1, mesh.Colors[i].A); } else if (mesh.Header.Flags.HasFlag(BrgMeshFlag.COLORCHANNEL)) { Maxscript.Command("meshop.setVertColor {0} 0 {1} (color {2} {3} {4})", mainObject, i + 1, mesh.Colors[i].R, mesh.Colors[i].G, mesh.Colors[i].B); } } } if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { if (mesh.Header.Flags.HasFlag(BrgMeshFlag.MATERIAL)) { Maxscript.CommentTitle("Load Face Materials"); foreach (var fMat in mesh.Faces) { Maxscript.Append(faceMats, fMat.MaterialIndex); } } Maxscript.CommentTitle("Load Faces"); foreach (var face in mesh.Faces) { Maxscript.Append(faceArray, Maxscript.Point3Literal(face.Indices[0] + 1, face.Indices[2] + 1, face.Indices[1] + 1)); } int mObjNum = 0; while (Maxscript.QueryInteger("($objects/{0}* as array).count", mainObject + mObjNum) > 0) { ++mObjNum; } Maxscript.Command("{0} = {1}", mainObject, Maxscript.NewMeshLiteral(mainObject + mObjNum, vertArray, faceArray, faceMats, texVerts)); //Maxscript.Command("{0} = getNodeByName \"{0}\"", mainObject); Maxscript.Command("dummy name:\"Dummy_hotspot\" pos:{0} boxsize:[10,10,0]", Maxscript.Point3Literal(-mesh.Header.HotspotPosition.X, -mesh.Header.HotspotPosition.Z, mesh.Header.HotspotPosition.Y)); Maxscript.CommentTitle("TVert Hack"); // Needed <= 3ds Max 2014; idk about 2015+ Maxscript.Command("buildTVFaces {0}", mainObject); for (int i = 1; i <= mesh.Faces.Count; i++) { Maxscript.Command("setTVFace {0} {1} {2}[{1}]", mainObject, i, faceArray); } Maxscript.CommentTitle("Load Normals for first Frame"); Maxscript.Command("max modify mode"); Maxscript.Command("select {0}", mainObject); Maxscript.Command("addModifier {0} (Edit_Normals()) ui:off", mainObject); Maxscript.Command("modPanel.setCurrentObject {0}.modifiers[#edit_normals]", mainObject); Maxscript.Command("{0}.modifiers[#edit_normals].Break selection:#{{1..{1}}}", mainObject, mesh.Normals.Count); Maxscript.Command("meshSetNormalIdFunc = {0}.modifiers[#edit_normals].SetNormalID", mainObject); for (int i = 0; i < mesh.Faces.Count; ++i) { Maxscript.Command("meshSetNormalIdFunc {0} {1} {2}", i + 1, 1, mesh.Faces[i].Indices[0] + 1); Maxscript.Command("meshSetNormalIdFunc {0} {1} {2}", i + 1, 2, mesh.Faces[i].Indices[2] + 1); Maxscript.Command("meshSetNormalIdFunc {0} {1} {2}", i + 1, 3, mesh.Faces[i].Indices[1] + 1); } Maxscript.Command("{0}.modifiers[#edit_normals].MakeExplicit selection:#{{1..{1}}}", mainObject, mesh.Normals.Count); Maxscript.Command("meshSetNormalFunc = {0}.modifiers[#edit_normals].SetNormal", mainObject); for (int i = 0; i < mesh.Normals.Count; i++) { Maxscript.Command("meshSetNormalFunc {0} {1}", i + 1, Maxscript.Point3Literal(-mesh.Normals[i].X, -mesh.Normals[i].Z, mesh.Normals[i].Y)); } Maxscript.Command("collapseStack {0}", mainObject); if (mesh.Header.Flags.HasFlag(BrgMeshFlag.ANIMTEXCOORDS)) { Maxscript.Command("select {0}", mainObject); Maxscript.Command("addModifier {0} (Unwrap_UVW()) ui:off", mainObject); Maxscript.Command("select {0}.verts", mainObject); Maxscript.Animate("{0}.Unwrap_UVW.moveSelected [0,0,0]", mainObject); } } Maxscript.CommentTitle("Load Attachpoints"); string attachDummyArray = "attachDummyArray"; if (!mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { Maxscript.NewArray(attachDummyArray); } for (int i = 0; i < mesh.Attachpoints.Count; ++i) { BrgAttachpoint att = mesh.Attachpoints[i]; if (mesh.Header.Flags.HasFlag(BrgMeshFlag.SECONDARYMESH)) { Maxscript.Command("attachpoint = {0}[{1}]", attachDummyArray, i + 1); Maxscript.AnimateAtTime(time, "attachpoint.rotation = {0}", att.GetMaxTransform()); Maxscript.AnimateAtTime(time, "attachpoint.position = {0}", att.GetMaxPosition()); if (this.uniformAttachpointScale) { Maxscript.AnimateAtTime(time, "attachpoint.scale = [1,1,1]"); } else { Maxscript.AnimateAtTime(time, "attachpoint.scale = {0}", att.GetMaxScale()); } } else { string attachDummy; if (this.uniformAttachpointScale) { attachDummy = Maxscript.NewDummy("attachDummy", att.GetMaxName(), att.GetMaxTransform(), att.GetMaxPosition(), "[0.25,0.25,0.25]", "[1,1,1]"); } else { attachDummy = Maxscript.NewDummy("attachDummy", att.GetMaxName(), att.GetMaxTransform(), att.GetMaxPosition(), att.GetMaxBoxSize(), att.GetMaxScale()); } Maxscript.Command("append {0} {1}", attachDummyArray, attachDummy); } } }
private void FromBrgMesh(BrgMesh brgMesh) { Vector3 max = new Vector3(float.MinValue); Vector3 min = new Vector3(float.MaxValue); using (FileStream fs = File.Open("posBuffer.bin", FileMode.Create, FileAccess.Write, FileShare.Read)) using (BinaryWriter writer = new BinaryWriter(fs)) { foreach (Vector3 vec in brgMesh.Vertices) { max.X = Math.Max(max.X, vec.X); max.Y = Math.Max(max.Y, vec.Y); max.Z = Math.Max(max.Z, vec.Z); min.X = Math.Min(min.X, vec.X); min.Y = Math.Min(min.Y, vec.Y); min.Z = Math.Min(min.Z, vec.Z); writer.Write(vec.X); writer.Write(vec.Y); writer.Write(vec.Z); } } glTFLoader.Schema.Buffer posBuffer = new glTFLoader.Schema.Buffer(); posBuffer.ByteLength = brgMesh.Vertices.Count * 12; posBuffer.Uri = "posBuffer.bin"; BufferView posBufferView = new BufferView(); posBufferView.Buffer = 0; posBufferView.ByteLength = posBuffer.ByteLength; posBufferView.ByteOffset = 0; posBufferView.ByteStride = 12; posBufferView.Name = "posBufferView"; posBufferView.Target = BufferView.TargetEnum.ARRAY_BUFFER; Accessor posAccessor = new Accessor(); posAccessor.BufferView = 0; posAccessor.ByteOffset = 0; posAccessor.ComponentType = Accessor.ComponentTypeEnum.FLOAT; posAccessor.Count = brgMesh.Vertices.Count; posAccessor.Max = new[] { max.X, max.Y, max.Z }; posAccessor.Min = new[] { min.X, min.Y, min.Z }; posAccessor.Name = "posBufferViewAccessor"; posAccessor.Type = Accessor.TypeEnum.VEC3; short faceMin = short.MaxValue; short faceMax = short.MinValue; using (FileStream fs = File.Open("indexBuffer.bin", FileMode.Create, FileAccess.Write, FileShare.Read)) using (BinaryWriter writer = new BinaryWriter(fs)) { foreach (var face in brgMesh.Faces) { faceMin = Math.Min(faceMin, face.Indices[0]); faceMin = Math.Min(faceMin, face.Indices[1]); faceMin = Math.Min(faceMin, face.Indices[2]); faceMax = Math.Max(faceMax, face.Indices[0]); faceMax = Math.Max(faceMax, face.Indices[1]); faceMax = Math.Max(faceMax, face.Indices[2]); writer.Write(face.Indices[0]); writer.Write(face.Indices[1]); writer.Write(face.Indices[2]); } } glTFLoader.Schema.Buffer indexBuffer = new glTFLoader.Schema.Buffer(); indexBuffer.ByteLength = brgMesh.Faces.Count * 6; indexBuffer.Uri = "indexBuffer.bin"; BufferView indexBufferView = new BufferView(); indexBufferView.Buffer = 1; indexBufferView.ByteLength = indexBuffer.ByteLength; indexBufferView.ByteOffset = 0; indexBufferView.Name = "indexBufferView"; indexBufferView.Target = BufferView.TargetEnum.ELEMENT_ARRAY_BUFFER; Accessor indexAccessor = new Accessor(); indexAccessor.BufferView = 1; indexAccessor.ByteOffset = 0; indexAccessor.ComponentType = Accessor.ComponentTypeEnum.UNSIGNED_SHORT; indexAccessor.Count = brgMesh.Faces.Count * 3; indexAccessor.Max = new[] { (float)faceMax }; indexAccessor.Min = new[] { (float)faceMin }; indexAccessor.Name = "indexBufferViewAccessor"; indexAccessor.Type = Accessor.TypeEnum.SCALAR; gltf.Buffers = new[] { posBuffer, indexBuffer }; gltf.BufferViews = new[] { posBufferView, indexBufferView }; gltf.Accessors = new[] { posAccessor, indexAccessor }; MeshPrimitive meshPrimitive = new MeshPrimitive(); meshPrimitive.Attributes = new Dictionary <string, int>(); meshPrimitive.Attributes.Add("POSITION", 0); meshPrimitive.Indices = 1; meshPrimitive.Mode = MeshPrimitive.ModeEnum.TRIANGLES; var mesh = new glTFLoader.Schema.Mesh(); mesh.Name = "mesh"; mesh.Primitives = new[] { meshPrimitive }; gltf.Meshes = new[] { mesh }; Node node = new Node(); node.Mesh = 0; node.Name = "node"; gltf.Nodes = new[] { node }; }