TriMesh
Inheritance: java.lang.Object, com.aspose.threed.A3DObject, com.aspose.threed.SceneObject, com.aspose.threed.Entity
All Implemented Interfaces: java.lang.Iterable
public class TriMesh extends Entity implements Iterable<Vertex>
TriMesh 包含可直接被 GPU 使用的原始数据。此类是一个实用工具,用于帮助构建仅包含每顶点数据的网格。 示例: 以下代码展示了如何使用自定义内存布局创建 TriMesh,并将其导出到文件。
//Define a vertex declaration as {FVector3 Position; FVector3 Normal; FVector2 UV}
VertexDeclaration vd = new VertexDeclaration();
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.POSITION);
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.NORMAL);
vd.addField(VertexFieldDataType.F_VECTOR2, VertexFieldSemantic.UV);
//convert a mesh to tri-mesh using specified memory layout
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(vd, mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
try(var s = new FileOutputStream("output.bin")) {
triMesh.writeVerticesTo(s);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write16bIndicesTo(s);
}
构造函数
| 构造函数 | 描述 |
|---|---|
| TriMesh(String name, VertexDeclaration declaration) | 初始化一个 TriMesh 实例 |
方法
TriMesh(String name, VertexDeclaration declaration)
public TriMesh(String name, VertexDeclaration declaration)
初始化一个 TriMesh 实例
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 名称 | java.lang.String | 此 TriMesh 的名称 |
| declaration | VertexDeclaration | 顶点的声明 |
addTriangle(int a, int b, int c)
public void addTriangle(int a, int b, int c)
添加一个新三角形
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| a | int | 第一个顶点的索引 |
| b | int | 第二个顶点的索引 |
| c | int | 第三个顶点的索引 |
beginVertex()
public Vertex beginVertex()
开始添加顶点
Returns: Vertex - The reference of internal vertex object in type Vertex
copyFrom(TriMesh input, VertexDeclaration vd)
public static TriMesh copyFrom(TriMesh input, VertexDeclaration vd)
从输入复制 TriMesh,使用新的顶点布局
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| input | TriMesh | 用于复制的输入 TriMesh |
| vd | VertexDeclaration | 输出 TriMesh 的新顶点声明 |
Returns: TriMesh - A new TriMesh instance with new vertex declaration. Example:
//Define a vertex declaration as {FVector3 Position; FVector3 Normal; FVector2 UV}
VertexDeclaration vd = new VertexDeclaration();
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.POSITION);
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.NORMAL);
vd.addField(VertexFieldDataType.F_VECTOR2, VertexFieldSemantic.UV);
//convert a mesh to TriMesh, the layout is automatically inferred from input mesh
var oldTriMesh = TriMesh.fromMesh((new Sphere()).toMesh());
//now create a new TriMesh from old TriMesh, using explicit memory layout defined by vd
var newTriMesh = TriMesh.copyFrom(oldTriMesh, vd);
endVertex()
public int endVertex()
结束添加顶点
Returns: int
equals(Object arg0)
public boolean equals(Object arg0)
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| arg0 | java.lang.Object |
Returns: 布尔
findProperty(String propertyName)
public Property findProperty(String propertyName)
查找属性。它可以是动态属性(由 CreateDynamicProperty/SetProperty 创建)或本机属性(通过其名称标识)
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| propertyName | java.lang.String | 属性名称。 |
Returns: Property - The property.
fromMesh(Mesh mesh)
public static TriMesh fromMesh(Mesh mesh)
从给定的网格对象创建 TriMesh,顶点声明基于输入网格的结构。
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| mesh | Mesh |
Returns: TriMesh - The TriMesh generated from given Mesh Example: The following code shows how to create a TriMesh with custom memory layout, and export it to file.
//Define a vertex declaration as {FVector3 Position; FVector3 Normal; FVector2 UV}
VertexDeclaration vd = new VertexDeclaration();
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.POSITION);
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.NORMAL);
vd.addField(VertexFieldDataType.F_VECTOR2, VertexFieldSemantic.UV);
//convert a mesh to tri-mesh using specified memory layout
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(vd, mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
try(var s = new FileOutputStream("output.bin")) {
triMesh.writeVerticesTo(s);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write16bIndicesTo(s);
}
fromMesh(Mesh mesh, boolean useFloat)
public static TriMesh fromMesh(Mesh mesh, boolean useFloat)
从给定的网格对象创建 TriMesh,顶点声明基于输入网格的结构。
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| mesh | Mesh | |
| useFloat | 布尔 | 对每个顶点元素组件使用 float 类型而不是 double 类型。 |
Returns: TriMesh - The TriMesh generated from given Mesh Example: The following code shows how to create a TriMesh with custom memory layout, and export it to file.
//Define a vertex declaration as {FVector3 Position; FVector3 Normal; FVector2 UV}
VertexDeclaration vd = new VertexDeclaration();
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.POSITION);
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.NORMAL);
vd.addField(VertexFieldDataType.F_VECTOR2, VertexFieldSemantic.UV);
//convert a mesh to tri-mesh using specified memory layout
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(vd, mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
try(var s = new FileOutputStream("output.bin")) {
triMesh.writeVerticesTo(s);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write16bIndicesTo(s);
}
fromMesh(VertexDeclaration declaration, Mesh mesh)
public static TriMesh fromMesh(VertexDeclaration declaration, Mesh mesh)
使用给定的顶点布局从给定的网格对象创建 TriMesh。
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| declaration | VertexDeclaration | 顶点的类型定义或内存布局 |
| mesh | Mesh | 源网格 |
Returns: TriMesh - Instance of TriMesh converted from input mesh with specified vertex’s memory layout Example: The following code shows how to create a TriMesh with custom memory layout, and export it to file.
//Define a vertex declaration as {FVector3 Position; FVector3 Normal; FVector2 UV}
VertexDeclaration vd = new VertexDeclaration();
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.POSITION);
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.NORMAL);
vd.addField(VertexFieldDataType.F_VECTOR2, VertexFieldSemantic.UV);
//convert a mesh to tri-mesh using specified memory layout
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(vd, mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
try(var s = new FileOutputStream("output.bin")) {
triMesh.writeVerticesTo(s);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write16bIndicesTo(s);
}
fromRawData(VertexDeclaration vd, byte[] vertices, int[] indices, boolean generateVertexMapping)
public static TriMesh fromRawData(VertexDeclaration vd, byte[] vertices, int[] indices, boolean generateVertexMapping)
从原始数据创建 TriMesh
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| vd | VertexDeclaration | 顶点声明,必须至少包含一个字段。 |
| 顶点 | byte[] | 输入的顶点数据,顶点的最小长度必须大于或等于顶点声明的大小 |
| 索引 | int[] | 三角形索引 |
| generateVertexMapping | boolean | 为每个顶点生成 Vertex,但仅进行序列化/反序列化时并非必需。 |
Returns: TriMesh - The TriMesh instance that encapsulated the input byte array. Remarks: The returned TriMesh will not copy the input byte array for performance, external changes on the array will be reflected to this instance. Example: The following code shows how to construct a TriMesh from raw bytes, this is useful when build your own 3D format
var indices = new int[] { 0, 1, 2 };
var vertices = new byte[]{
0, 0, 0, 191,
0, 0, 0, 0,
0, 0, 0, 191,
0, 0, 0, 191,
0, 0, 0, 0,
0, 0, 0, 63,
0, 0, 0, 63,
0, 0, 0, 0The string representation,
0, 0, 0, 63
};
VertexDeclaration vd = new VertexDeclaration();
vd.AddField(VertexFieldDataType.FVector3, VertexFieldSemantic.Position);
var triMesh = TriMesh.FromRawData(vd, vertices, indices, true);
getBoundingBox()
public BoundingBox getBoundingBox()
获取当前实体在其对象空间坐标系中的边界框。
Returns: BoundingBox - the bounding box of current entity in its object space coordinate system. Example: The following code shows how to calculate the bounding box of a shape
Entity entity = new Sphere();
entity.setRadius(10);
var bbox = entity.getBoundingBox();
System.out.printf("The bounding box of the entity is %s ~ %s", bbox.getMinimum(), bbox.getMaximum());
getCapacity()
public int getCapacity()
预分配顶点的容量。
Returns: int - 预分配顶点的容量。
getClass()
public final native Class<?> getClass()
Returns: java.lang.Class
getEntityRendererKey()
public EntityRendererKey getEntityRendererKey()
获取在渲染器中注册的实体渲染器的键
Returns: EntityRendererKey - the key of the entity renderer registered in the renderer
getExcluded()
public boolean getExcluded()
获取在导出期间是否排除此实体。
Returns: boolean - 是否在导出期间排除此实体。
getIndicesCount()
public int getIndicesCount()
此 TriMesh 中索引的数量。
Returns: int - 此 TriMesh 中索引的数量
getIntIndices()
public int[] getIntIndices()
将索引转换为 32 位整数数组
Returns: int[]
getName()
public String getName()
获取名称。
Returns: java.lang.String - 名称。
getParentNode()
public Node getParentNode()
获取第一个父节点,如果设置第一个父节点,则此实体将从其他父节点分离。
Returns: Node - the first parent node, if set the first parent node, this entity will be detached from other parent nodes.
getParentNodes()
public ArrayList<Node> getParentNodes()
获取所有父节点,实体可以附加到多个父节点以进行几何实例化
Returns: java.util.ArrayList<com.aspose.threed.Node> - 所有父节点,实体可以附加到多个父节点以实现几何实例化
getProperties()
public PropertyCollection getProperties()
获取所有属性的集合。
Returns: PropertyCollection - the collection of all properties.
getProperty(String property)
public Object getProperty(String property)
获取指定属性的值
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 属性 | java.lang.String | 属性名称 |
Returns: java.lang.Object - 找到的属性的值
getScene()
public Scene getScene()
获取此对象所属的场景
Returns: Scene - the scene that this object belongs to
getShortIndices()
public short[] getShortIndices()
将索引转换为 16 位整数数组
Returns: short[]
getUnmergedVerticesCount()
public int getUnmergedVerticesCount()
通过 beginVertex 和 endVertex 传入的未合并顶点的数量。
Returns: int - 通过 beginVertex 和 endVertex 传入的未合并顶点的数量。
getVertexDeclaration()
public VertexDeclaration getVertexDeclaration()
TriMesh 的顶点布局。
Returns: VertexDeclaration - The vertex layout of the TriMesh.
getVerticesCount()
public int getVerticesCount()
此 TriMesh 中顶点的数量。
Returns: int - 此 TriMesh 中顶点的数量
getVerticesSizeInBytes()
public int getVerticesSizeInBytes()
所有顶点的总大小(字节)
Returns: int - 所有顶点的总大小(字节)
hashCode()
public native int hashCode()
Returns: int
indicesToArray(int[][] result)
public void indicesToArray(int[][] result)
将索引转换为 32 位整数数组
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 结果 | int[][] |
indicesToArray(short[][] result)
public void indicesToArray(short[][] result)
将索引转换为 16 位整数数组
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 结果 | short[][] |
iterator()
public Iterator<Vertex> iterator()
获取枚举器以枚举 Vertex
Returns: java.util.Iterator<com.aspose.threed.Vertex>
loadVerticesFromBytes(byte[] verticesInBytes)
public void loadVerticesFromBytes(byte[] verticesInBytes)
从字节加载顶点,字节长度必须是顶点大小的整数倍。 示例: 以下代码展示了如何创建一个空的 TriMesh 并手动从原始字节加载顶点。
var indices = new int[] { 0, 1, 2 };
var vertices = new byte[]{
0, 0, 0, 191,
0, 0, 0, 0,
0, 0, 0, 191,
0, 0, 0, 191,
0, 0, 0, 0,
0, 0, 0, 63,
0, 0, 0, 63,
0, 0, 0, 0,
0, 0, 0, 63
};
VertexDeclaration vd = new VertexDeclaration();
vd.AddField(VertexFieldDataType.FVector3, VertexFieldSemantic.Position);
//create an empty TriMesh with specified vertex declaration
var triMesh = new TriMesh("", vd);
//load vertices directly from bytes
triMesh.LoadVerticesFromBytes(vertices);
triMesh.AddTriangle(0, 1, 2);
int[] indices = new int[] { 0, 1, 2 };
byte[] vertices = new byte[]{
0, 0, 0, 191,
0, 0, 0, 0,
0, 0, 0, 191,
0, 0, 0, 191,
0, 0, 0, 0,
0, 0, 0, 63,
0, 0, 0, 63,
0, 0, 0, 0,
0, 0, 0, 63
};
VertexDeclaration vd = new VertexDeclaration();
vd.addField(VertexFieldDataType.F_VECTOR3, VertexFieldSemantic.POSITION);
//create an empty TriMesh with specified vertex declaration
var triMesh = new TriMesh("", vd);
//load vertices directly from bytes
triMesh.loadVerticesFromBytes(vertices);
triMesh.addTriangle(0, 1, 2);
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| verticesInBytes | byte[] |
notify()
public final native void notify()
notifyAll()
public final native void notifyAll()
readDouble(int idx, VertexField field)
public double readDouble(int idx, VertexField field)
读取 double 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 float/double 兼容数据类型的字段 |
Returns: double - 指定顶点字段的 Double 值
readFVector2(int idx, VertexField field)
public FVector2 readFVector2(int idx, VertexField field)
读取 vector2 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 Vector2/FVector2 数据类型的字段 |
Returns: FVector2 - FVector2 of specified vertex’s field
readFVector3(int idx, VertexField field)
public FVector3 readFVector3(int idx, VertexField field)
读取 vector3 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 Vector3/FVector3 数据类型的字段 |
Returns: FVector3
readFVector4(int idx, VertexField field)
public FVector4 readFVector4(int idx, VertexField field)
读取 vector4 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 Vector4/FVector4 数据类型的字段 |
Returns: FVector4
readFloat(int idx, VertexField field)
public float readFloat(int idx, VertexField field)
读取 float 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 float/double 兼容数据类型的字段 |
Returns: float - 指定顶点字段的 Float 值
readVector2(int idx, VertexField field)
public Vector2 readVector2(int idx, VertexField field)
读取 vector2 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 Vector2/FVector2 数据类型的字段 |
Returns: Vector2 - Vector2 of specified vertex’s field
readVector3(int idx, VertexField field)
public Vector3 readVector3(int idx, VertexField field)
读取 vector3 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 Vector3/FVector3 数据类型的字段 |
Returns: Vector3
readVector4(int idx, VertexField field)
public Vector4 readVector4(int idx, VertexField field)
读取 vector4 字段
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| idx | int | 要读取的顶点索引 |
| field | VertexField | 具有 Vector4/FVector4 数据类型的字段 |
Returns: Vector4
removeProperty(Property property)
public boolean removeProperty(Property property)
移除动态属性。
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| property | Property | 要删除哪个属性 |
Returns: boolean - 如果属性成功删除则为 true
removeProperty(String property)
public boolean removeProperty(String property)
移除通过名称标识的指定属性
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 属性 | java.lang.String | 要删除哪个属性 |
Returns: boolean - 如果属性成功删除则为 true
setExcluded(boolean value)
public void setExcluded(boolean value)
设置在导出期间是否排除此实体。
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 值 | 布尔 | 新值 |
setName(String value)
public void setName(String value)
设置名称。
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 值 | java.lang.String | 新值 |
setParentNode(Node value)
public void setParentNode(Node value)
设置第一个父节点,如果设置第一个父节点,则此实体将从其他父节点分离。
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| value | Node | 新值 |
setProperty(String property, Object value)
public void setProperty(String property, Object value)
设置指定属性的值
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 属性 | java.lang.String | 属性名称 |
| 值 | java.lang.Object | 属性的值 |
toString()
public String toString()
获取 TriMesh 的字符串表示
Returns: java.lang.String - 字符串表示形式
verticesToArray()
public byte[] verticesToArray()
将顶点数据转换为字节数组
Returns: byte[]
wait()
public final void wait()
wait(long arg0)
public final void wait(long arg0)
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| arg0 | long |
wait(long arg0, int arg1)
public final void wait(long arg0, int arg1)
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| arg0 | long | |
| arg1 | int |
write16bIndicesTo(Stream stream)
public void write16bIndicesTo(Stream stream)
将索引数据以 16 位整数写入流 Example:
//convert a mesh to TriMesh, the layout is automatically inferred from input mesh
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
var stream = new ByteArrayOutputStream();
try(var s = Stream.wrap(stream)) {
triMesh.writeVerticesTo(s);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write16bIndicesTo(s);
}
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| stream | Stream |
write16bIndicesTo(OutputStream stream)
public void write16bIndicesTo(OutputStream stream)
将索引数据以 16 位整数写入流
Parameters:
| 参数 | 类型 | 描述 |
|---|---|---|
| 流 | java.io.OutputStream |
//convert a mesh to TriMesh, the layout is automatically inferred from input mesh
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
var stream = new ByteArrayOutputStream();
triMesh.writeVerticesTo(stream);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write16bIndicesTo(stream);
``` |
### write32bIndicesTo(Stream stream) {#write32bIndicesTo-com.aspose.threed.Stream-}
public void write32bIndicesTo(Stream stream)
将索引数据以 32 位整数写入流 **Example:**
//convert a mesh to TriMesh, the layout is automatically inferred from input mesh var mesh = (new Sphere()).toMesh(); var triMesh = TriMesh.fromMesh(mesh); //save it to a stream, 115 vertices * 32bytes per vertex var stream = new ByteArrayOutputStream(); try(var s = Stream.wrap(stream)) { triMesh.writeVerticesTo(s); //save indices as ushort to stream, 504 indices * 2 bytes per index triMesh.write32bIndicesTo(s); }
**Parameters:**
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| stream | [Stream](../../com.aspose.threed/stream) | |
### write32bIndicesTo(OutputStream stream) {#write32bIndicesTo-java.io.OutputStream-}
public void write32bIndicesTo(OutputStream stream)
将索引数据以 32 位整数写入流
**Parameters:**
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| | 流 | java.io.OutputStream | **示例:** |
//convert a mesh to TriMesh, the layout is automatically inferred from input mesh
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
var stream = new ByteArrayOutputStream();
triMesh.writeVerticesTo(stream);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write32bIndicesTo(stream);
### writeVerticesTo(Stream stream) {#writeVerticesTo-com.aspose.threed.Stream-}
public void writeVerticesTo(Stream stream)
将顶点数据写入指定的流
**Parameters:**
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| | stream | [Stream](../../com.aspose.threed/stream) | 将顶点数据写入的流 **示例:** |
//convert a mesh to TriMesh, the layout is automatically inferred from input mesh var mesh = (new Sphere()).toMesh(); var triMesh = TriMesh.fromMesh(mesh); //save it to a stream, 115 vertices * 32bytes per vertex var stream = new ByteArrayOutputStream(); try(var s = Stream.wrap(stream)) { triMesh.writeVerticesTo(s); //save indices as ushort to stream, 504 indices * 2 bytes per index triMesh.write16bIndicesTo(s); }
### writeVerticesTo(OutputStream stream) {#writeVerticesTo-java.io.OutputStream-}
public void writeVerticesTo(OutputStream stream)
将顶点数据写入指定的流
**Parameters:**
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| | 流 | java.io.OutputStream | 将顶点数据写入的流 **示例:** |
//convert a mesh to TriMesh, the layout is automatically inferred from input mesh
var mesh = (new Sphere()).toMesh();
var triMesh = TriMesh.fromMesh(mesh);
//save it to a stream, 115 vertices * 32bytes per vertex
var stream = new ByteArrayOutputStream();
triMesh.writeVerticesTo(stream);
//save indices as ushort to stream, 504 indices * 2 bytes per index
triMesh.write16bIndicesTo(stream);