Skip to content

Commit

Permalink
Merge pull request #17 from jrz371/NonDracoExport
Browse files Browse the repository at this point in the history
Fixed non draco export
  • Loading branch information
Doerge authored Jan 19, 2021
2 parents 6d2ab4f + a620be3 commit 86f9c75
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 98 deletions.
55 changes: 38 additions & 17 deletions glTF-BinExporter/GlTFExporterCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,20 @@ protected override Result RunCommand(Rhino.RhinoDoc doc, RunMode mode)
{
GetObject go = Selection.GetValidExportObjects("Select objects to export.");

var opts = new ExportOptions() { UseDracoCompression = true, DracoCompressionLevel = 10, DracoQuantizationBits = 16, UseBinary = true };

// NOTE: The following options can be useful in dev/debug:
//bool useDracoCompression = true;
//Rhino.Input.RhinoGet.GetBool("Compression", true, "None", "Draco", ref useDracoCompression);
//bool useBinary = true;
//Rhino.Input.RhinoGet.GetBool("Mode", true, "Text", "Binary", ref useBinary);
//bool includeMaterials = true;
//Rhino.Input.RhinoGet.GetBool("Materials", true, "Exclude", "Include", ref opts.IncludeMaterial);
//int dracoCompressionLevel = 10;
Rhino.Input.RhinoGet.GetInteger("Draco Compression Level (max=10)", true, ref opts.DracoCompressionLevel, 1, 10);
//bool quantizaionBits = true;
Rhino.Input.RhinoGet.GetInteger("Quantization", true, ref opts.DracoQuantizationBits, 8, 32);
//Rhino.Input.RhinoGet.GetBool("Draco Quantization", true, "B", "Bits 16 Bits", ref quantizaionBits);
//opts.DracoQuantizationBits = quantizaionBits ? 24 : 12;

var dialog = new SaveFileDialog() { DefaultExt = ".glb", Title = "Select glTF Binary file to export to.", Filter = "glTF Binary (*.glb) | *.glb" };
var opts = new ExportOptions() { UseDracoCompression = false, DracoCompressionLevel = 10, DracoQuantizationBits = 16, UseBinary = true };

Rhino.Input.RhinoGet.GetBool("Binary or Text", true, "Text", "Binary", ref opts.UseBinary);

Rhino.Input.RhinoGet.GetBool("Compression", true, "None", "Draco", ref opts.UseDracoCompression);

if (opts.UseDracoCompression)
{
Rhino.Input.RhinoGet.GetInteger("Draco Compression Level (max=10)", true, ref opts.DracoCompressionLevel, 1, 10);
Rhino.Input.RhinoGet.GetInteger("Quantization", true, ref opts.DracoQuantizationBits, 8, 32);
}

var dialog = GetSaveFileDialog(opts.UseBinary);

var fileSelected = dialog.ShowSaveDialog();

if (!fileSelected) {
Expand Down Expand Up @@ -89,8 +86,32 @@ protected override Result RunCommand(Rhino.RhinoDoc doc, RunMode mode)
return Result.Success;
} catch (Exception e) {
RhinoApp.WriteLine("ERROR: Failed exporting selected geometry to file.");
System.Diagnostics.Debug.WriteLine(e.Message);
return Result.Failure;
}
}

private SaveFileDialog GetSaveFileDialog(bool binaryExport)
{
if(binaryExport)
{
return new SaveFileDialog()
{
DefaultExt = ".glb",
Title = "Select glTF Binary file to export to.",
Filter = "glTF Binary (*.glb) | *.glb"
};
}
else //Text glTF
{
return new SaveFileDialog()
{
DefaultExt = ".gltf",
Title = "Select glTF file to export to.",
Filter = "glTF Text (*.gltf) | *.gltf"
};
}
}

}
}
17 changes: 17 additions & 0 deletions glTF-BinExporter/glTF/GlBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class Buffer
public bool IsGLBinaryMode;

// dump to byte[] with ".flatten" + .ToArray();
[JsonIgnore]
public List<IEnumerable<byte>> RawBytes;

public bool ShouldSerializeRawBytes()
Expand Down Expand Up @@ -75,6 +76,22 @@ public void Add(Point3d point)
PrimitiveCount += 1;
}

public void Add(Vector3d point)
{
// Switch GL coords for Y<=>Z
float[] coords = new float[] { (float)point.X, (float)point.Z, -(float)point.Y };
Add(coords);
PrimitiveCount += 1;
}

public void Add(Point2f point)
{
// Switch GL coords for Y<=>Z
float[] coords = new float[] { (float)point.X, -(float)point.Y };
Add(coords);
PrimitiveCount += 1;
}

public void Add(MeshFace face)
{
if (face.IsTriangle)
Expand Down
250 changes: 169 additions & 81 deletions glTF-BinExporter/glTF/GlTFRootModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ namespace glTF_BinExporter.glTF
/// </summary>
public class RootModel
{
public int scene;
public int scene = 0;

public List<Scene> scenes;

public List<Node> nodes;
Expand Down Expand Up @@ -145,6 +146,9 @@ public void SerializeToGLB(in MemoryStream memoryStream)
bv.byteOffset = bv.bufferRef.binaryOffset;
}

//Have to get rid of the other buffers so only the new buffer
//all the data was dumped into remains
buffers.Clear();
buffers.Add(new Buffer(false) { byteLength = binaryChunkUnpaddedLength, uri = null });

// JSON Chunk
Expand Down Expand Up @@ -518,90 +522,174 @@ public void AddMaterial(Rhino.DocObjects.Material rhinoMaterial, Guid renderMatI

public void AddRhinoObject(Rhino.Geometry.Mesh[] rhinoMeshes, Rhino.DocObjects.Material material, Guid renderMatId)
{
// TODO: Disabled for now. Don't have bandwidth to fix none-DracoCompression for now. Beware of lot's of "old" code below.
//int currentMaterialIdx = materials.FindIndex(m => m.Id == material.Id);
//if (currentMaterialIdx == -1)
//{
// AddMaterial(material);
// currentMaterialIdx = materials.Count - 1;
//}
int currentMaterialIdx = materials.FindIndex(m => m.Id == material.Id);
if (currentMaterialIdx == -1)
{
AddMaterial(material, renderMatId);
currentMaterialIdx = materials.Count - 1;
}

//var primitives = new List<Primitive>();
//// For each rhino mesh, create gl-buffers, gl-meshes, etc.
//foreach (var rhinoMesh in rhinoMeshes)
//{
// // Create buffers for data (position, normals, indices etc.)
// var vtxBuffer = new Buffer(IsGLBinaryMode);
var primitives = new List<Primitive>();

// var min = new Point3d() { X = Double.PositiveInfinity, Y = Double.PositiveInfinity, Z = Double.PositiveInfinity };
// var max = new Point3d() { X = Double.NegativeInfinity, Y = Double.NegativeInfinity, Z = Double.NegativeInfinity };
// foreach (var p in rhinoMesh.Vertices)
// {
// vtxBuffer.Add(p);

// min.X = Math.Min(min.X, p.X);
// // Switch Y<=>Z for GL coords
// min.Y = Math.Min(min.Y, p.Z);
// min.Z = Math.Min(min.Z, -p.Y);

// max.X = Math.Max(max.X, p.X);
// // Switch Y<=>Z for GL coords
// max.Y = Math.Max(max.Y, p.Z);
// max.Z = Math.Max(max.Z, -p.Y);
// }
// buffers.Add(vtxBuffer);
// int vtxBufferIdx = buffers.Count - 1;

// var idsBuffer = new Buffer(IsGLBinaryMode);
// foreach (var f in rhinoMesh.Faces)
// {
// idsBuffer.Add(f);
// }
// buffers.Add(idsBuffer);
// int idsBufferIdx = buffers.Count - 1;

// // Create bufferviews
// var vtxBufferView = new BufferView() { bufferRef = vtxBuffer, buffer = vtxBufferIdx, byteOffset = 0, byteLength = vtxBuffer.byteLength, target = GlConstants.ARRAY_BUFFER };
// bufferViews.Add(vtxBufferView);
// int vtxBufferViewIdx = bufferViews.Count - 1;

// var idsBufferView = new BufferView() { bufferRef = idsBuffer, buffer = idsBufferIdx, byteOffset = 0, byteLength = idsBuffer.byteLength, target = GlConstants.ELEMENT_ARRAY_BUFFER };
// bufferViews.Add(idsBufferView);
// int idsBufferViewIdx = bufferViews.Count - 1;

// // Create accessors
// var vtxAccessor = new AccessorVec3
// {
// bufferView = vtxBufferViewIdx,
// count = vtxBuffer.PrimitiveCount,
// min = new float[] { (float)min.X, (float)min.Y, (float)min.Z },
// max = new float[] { (float)max.X, (float)max.Y, (float)max.Z }
// };
// accessors.Add(vtxAccessor);
// int vtxAccessorIdx = accessors.Count - 1;

// var idsAccessor = new AccessorScalar
// {
// bufferView = idsBufferViewIdx,
// count = idsBuffer.PrimitiveCount
// };
// accessors.Add(idsAccessor);
// int idsAccessorIdx = accessors.Count - 1;

// // Create primitives
// var attribute = new Attribute() { POSITION = vtxAccessorIdx };
// var primitive = new Primitive() { attributes = attribute, indices = idsAccessorIdx, material = currentMaterialIdx };

// // Create mesh
// primitives.Add(primitive);
//}
//var mesh = new Mesh() { primitives = primitives };
//meshes.Add(mesh);
foreach (var rhinoMesh in rhinoMeshes)
{
// Create buffers for data (position, normals, indices etc.)
var vtxBuffer = new Buffer(ExportOptions.UseBinary);
var vtxMin = new Point3d() { X = Double.PositiveInfinity, Y = Double.PositiveInfinity, Z = Double.PositiveInfinity };
var vtxMax = new Point3d() { X = Double.NegativeInfinity, Y = Double.NegativeInfinity, Z = Double.NegativeInfinity };
foreach (var p in rhinoMesh.Vertices)
{
vtxBuffer.Add(p);

//var node = new Node() { mesh = meshes.Count - 1 };
//nodes.Add(node);
vtxMin.X = Math.Min(vtxMin.X, p.X);
// Switch Y<=>Z for GL coords
vtxMin.Y = Math.Min(vtxMin.Y, p.Z);
vtxMin.Z = Math.Min(vtxMin.Z, -p.Y);

//scenes[scene].nodes.Add(nodes.Count - 1);
vtxMax.X = Math.Max(vtxMax.X, p.X);
// Switch Y<=>Z for GL coords
vtxMax.Y = Math.Max(vtxMax.Y, p.Z);
vtxMax.Z = Math.Max(vtxMax.Z, -p.Y);
}
buffers.Add(vtxBuffer);
int vtxBufferIdx = buffers.Count - 1;

var idsBuffer = new Buffer(ExportOptions.UseBinary);
foreach (var f in rhinoMesh.Faces)
{
idsBuffer.Add(f);
}
buffers.Add(idsBuffer);
int idsBufferIdx = buffers.Count - 1;

Buffer normalsBuffer = new Buffer(ExportOptions.UseBinary);
var normalsMin = new Point3d() { X = Double.PositiveInfinity, Y = Double.PositiveInfinity, Z = Double.PositiveInfinity };
var normalsMax = new Point3d() { X = Double.NegativeInfinity, Y = Double.NegativeInfinity, Z = Double.NegativeInfinity };
//normalsBuffer.Add(rhinoMesh.Normals.ToFloatArray());
foreach (var n in rhinoMesh.Normals)
{
normalsBuffer.Add(n);

normalsMin.X = Math.Min(normalsMin.X, n.X);
// Switch Y<=>Z for GL coords
normalsMin.Y = Math.Min(normalsMin.Y, n.Z);
normalsMin.Z = Math.Min(normalsMin.Z, -n.Y);

normalsMax.X = Math.Max(normalsMax.X, n.X);
// Switch Y<=>Z for GL coords
normalsMax.Y = Math.Max(normalsMax.Y, n.Z);
normalsMax.Z = Math.Max(normalsMax.Z, -n.Y);
}
int normalsIdx = buffers.AddAndReturnIndex(normalsBuffer);

Buffer texCoordsBuffer = new Buffer(ExportOptions.UseBinary);
var texCoordsMin = new Point2d() { X = Double.PositiveInfinity, Y = Double.PositiveInfinity };
var texCoordsMax = new Point2d() { X = Double.NegativeInfinity, Y = Double.NegativeInfinity };
foreach (var tx in rhinoMesh.TextureCoordinates)
{
texCoordsBuffer.Add(tx);

texCoordsMin.X = Math.Min(texCoordsMin.X, tx.X);
// Switch Y<=>Z for GL coords
texCoordsMin.Y = Math.Min(texCoordsMin.Y, -tx.Y);

texCoordsMax.X = Math.Max(texCoordsMax.X, tx.X);
// Switch Y<=>Z for GL coords
texCoordsMax.Y = Math.Max(texCoordsMax.Y, -tx.Y);
}

int texCoordsIdx = buffers.AddAndReturnIndex(texCoordsBuffer);

// Create bufferviews
var vtxBufferView = new BufferView() { bufferRef = vtxBuffer, buffer = vtxBufferIdx, byteOffset = 0, byteLength = vtxBuffer.byteLength, target = GLConstants.ARRAY_BUFFER };
bufferViews.Add(vtxBufferView);
int vtxBufferViewIdx = bufferViews.Count - 1;

var idsBufferView = new BufferView() { bufferRef = idsBuffer, buffer = idsBufferIdx, byteOffset = 0, byteLength = idsBuffer.byteLength, target = GLConstants.ELEMENT_ARRAY_BUFFER };
bufferViews.Add(idsBufferView);
int idsBufferViewIdx = bufferViews.Count - 1;

BufferView normalsBufferView = new BufferView()
{
bufferRef = normalsBuffer,
buffer = normalsIdx,
byteOffset = 0,
byteLength = normalsBuffer.byteLength,
target = GLConstants.ARRAY_BUFFER
};
int normalsBufferViewIdx = bufferViews.AddAndReturnIndex(normalsBufferView);

BufferView texCoordsBufferView = new BufferView()
{
bufferRef = texCoordsBuffer,
buffer = texCoordsIdx,
byteOffset = 0,
byteLength = texCoordsBuffer.byteLength,
target = GLConstants.ARRAY_BUFFER
};
int texCoordsBufferViewIdx = bufferViews.AddAndReturnIndex(texCoordsBufferView);

// Create accessors
var vtxAccessor = new AccessorVec3()
{
bufferView = vtxBufferViewIdx,
count = vtxBuffer.PrimitiveCount,
min = new float[] { (float)vtxMin.X, (float)vtxMin.Y, (float)vtxMin.Z },
max = new float[] { (float)vtxMax.X, (float)vtxMax.Y, (float)vtxMax.Z }
};

accessors.Add(vtxAccessor);
int vtxAccessorIdx = accessors.Count - 1;

var idsAccessor = new AccessorScalar()
{
min = new int[] { 0 },
max = new int[] { rhinoMesh.Vertices.Count - 1 },
bufferView = idsBufferViewIdx,
count = idsBuffer.PrimitiveCount
};
accessors.Add(idsAccessor);
int idsAccessorIdx = accessors.Count - 1;

AccessorVec3 normalsAccessor = new AccessorVec3()
{
bufferView = normalsBufferViewIdx,
count = rhinoMesh.Normals.Count,
min = new float[] { (float)normalsMin.X, (float)normalsMin.Y, (float)normalsMin.Z },
max = new float[] { (float)normalsMax.X, (float)normalsMax.Y, (float)normalsMax.Z }
};
int normalsAccessorIdx = accessors.AddAndReturnIndex(normalsAccessor);

AccessorVec2 texCoordsAccessor = new AccessorVec2()
{
bufferView = texCoordsBufferViewIdx,
count = rhinoMesh.TextureCoordinates.Count,
min = new float[] { (float)texCoordsMin.X, (float)texCoordsMin.Y },
max = new float[] { (float)texCoordsMax.X, (float)texCoordsMax.Y }
};
int texCoordsAccessorIdx = accessors.AddAndReturnIndex(texCoordsAccessor);

// Create primitives
var attribute = new Attribute()
{
POSITION = vtxAccessorIdx,
NORMAL = normalsAccessorIdx,
TEXCOORD_0 = texCoordsAccessorIdx
};

var primitive = new Primitive() { attributes = attribute, indices = idsAccessorIdx, material = currentMaterialIdx };

// Create mesh
primitives.Add(primitive);
}

var mesh = new Mesh() { primitives = primitives };
meshes.Add(mesh);

var node = new Node() { mesh = meshes.Count - 1 };
nodes.Add(node);

scenes[scene].nodes.Add(nodes.Count - 1);
}
}
}
7 changes: 7 additions & 0 deletions glTF-BinExporter/glTF/GlTFUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,12 @@ public static void ExportBinary(MemoryStream outStream, IEnumerable<RhinoObject>

outStream.Flush();
}

public static int AddAndReturnIndex<T>(this List<T> list, T item)
{
list.Add(item);
return list.Count - 1;
}

}
}

0 comments on commit 86f9c75

Please sign in to comment.