12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- using System ;
16
15
using System . Collections . Generic ;
17
16
using System . IO ;
18
17
using System . Linq ;
19
18
using UnityEngine ;
19
+ using UnityEngine . Rendering ;
20
20
21
21
namespace Mujoco {
22
22
@@ -27,6 +27,17 @@ public static Vector3 ReadVector3(this BinaryReader reader) {
27
27
var z = reader . ReadSingle ( ) ;
28
28
return new Vector3 ( x , y , z ) ;
29
29
}
30
+
31
+ public static int GetOrCreateVertexIndex ( Dictionary < Vector3 , int > vertexIndexMap , List < Vector3 > vertices , List < Vector3 > normals , Vector3 vertex , Vector3 normal ) {
32
+ if ( vertexIndexMap . TryGetValue ( vertex , out int existingIndex ) ) {
33
+ return existingIndex ;
34
+ }
35
+ int newIndex = vertexIndexMap . Count ;
36
+ vertexIndexMap . Add ( vertex , newIndex ) ;
37
+ vertices . Add ( vertex ) ;
38
+ normals . Add ( normal ) ;
39
+ return newIndex ;
40
+ }
30
41
}
31
42
32
43
public static class BinaryWriterExtensions {
@@ -50,7 +61,7 @@ public class StlMeshParser {
50
61
// The binary STL format is described here: https://en.wikipedia.org/wiki/STL_(file_format)
51
62
public static Mesh ParseBinary ( byte [ ] stlFileContents , Vector3 scale ) {
52
63
var fileTypeId = System . Text . Encoding . UTF8 . GetString (
53
- stlFileContents . Take ( _asciiFileTypeId . Length ) . ToArray ( ) ) ;
64
+ stlFileContents . Take ( _asciiFileTypeId . Length ) . ToArray ( ) ) ;
54
65
if ( fileTypeId == _asciiFileTypeId ) {
55
66
throw new IOException ( "Ascii STL file format is not supported." ) ;
56
67
}
@@ -59,27 +70,39 @@ public static Mesh ParseBinary(byte[] stlFileContents, Vector3 scale) {
59
70
using ( var reader = new BinaryReader ( stream ) ) {
60
71
reader . ReadBytes ( _headerLength ) ;
61
72
var numTriangles = reader . ReadUInt32 ( ) ;
62
- var numVertices = numTriangles * _verticesPerTriangle ;
63
- if ( numVertices > _unityLimitNumVerticesPerMesh ) {
64
- throw new IndexOutOfRangeException (
65
- "The mesh exceeds the number of vertices per mesh allowed by Unity. " +
66
- $ "({ numVertices } > { _unityLimitNumVerticesPerMesh } )") ;
67
- }
68
- var triangleIndices = new List < int > ( capacity : ( int ) numVertices ) ;
69
- var vertices = new List < Vector3 > ( capacity : ( int ) numVertices ) ;
70
- var normals = new List < Vector3 > ( capacity : ( int ) numVertices ) ;
71
- for ( var i = 0 ; i < numVertices ; i += _verticesPerTriangle ) {
73
+ var maxNumVertices = numTriangles * _verticesPerTriangle ;
74
+
75
+ Dictionary < Vector3 , int > vertexIndexMap = new Dictionary < Vector3 , int > ( ) ;
76
+ var triangleIndices = new int [ ( int ) numTriangles * _verticesPerTriangle ] ;
77
+ var vertices = new List < Vector3 > ( capacity : ( int ) maxNumVertices ) ;
78
+ var normals = new List < Vector3 > ( capacity : ( int ) maxNumVertices ) ;
79
+ for ( var i = 0 ; i < numTriangles ; i ++ ) {
72
80
var triangleNormal = ToXZY ( reader . ReadVector3 ( ) ) ;
73
- normals . AddRange ( new [ ] { triangleNormal , triangleNormal , triangleNormal } ) ;
74
- vertices . AddRange ( new [ ] {
75
- ToXZY ( reader . ReadVector3 ( ) ) ,
76
- ToXZY ( reader . ReadVector3 ( ) ) ,
77
- ToXZY ( reader . ReadVector3 ( ) ) } ) ;
78
- triangleIndices . AddRange ( new [ ] { i , i + 2 , i + 1 } ) ;
79
- reader . ReadInt16 ( ) ; // Read the unused attribute indices field.
81
+ var verts = new [ ]
82
+ {
83
+ ToXZY ( reader . ReadVector3 ( ) ) ,
84
+ ToXZY ( reader . ReadVector3 ( ) ) ,
85
+ ToXZY ( reader . ReadVector3 ( ) )
86
+ } ;
87
+ var indices = new [ ] { verts [ 0 ] , verts [ 2 ] , verts [ 1 ] } . Select ( v =>
88
+ BinaryReaderExtensions . GetOrCreateVertexIndex ( vertexIndexMap ,
89
+ vertices ,
90
+ normals ,
91
+ v ,
92
+ triangleNormal ) ) . ToArray ( ) ;
93
+ for ( int j = 0 ; j < 3 ; j ++ ) {
94
+ triangleIndices [ i * 3 + j ] = indices [ j ] ;
95
+ }
96
+ reader . ReadInt16 ( ) ; // Read the unused attribute indices field.
80
97
}
81
98
82
99
var mesh = new Mesh ( ) ;
100
+ var numVertices = vertexIndexMap . Count ;
101
+
102
+ if ( numVertices > _unityLimitNumVerticesPerMesh ) {
103
+ mesh . indexFormat = IndexFormat . UInt32 ;
104
+ }
105
+
83
106
mesh . vertices = vertices . ToArray ( ) ;
84
107
mesh . normals = normals . ToArray ( ) ;
85
108
mesh . triangles = triangleIndices . ToArray ( ) ;
@@ -88,6 +111,7 @@ public static Mesh ParseBinary(byte[] stlFileContents, Vector3 scale) {
88
111
mesh . RecalculateNormals ( ) ;
89
112
mesh . RecalculateTangents ( ) ;
90
113
mesh . RecalculateBounds ( ) ;
114
+
91
115
return mesh ;
92
116
}
93
117
}
@@ -126,7 +150,8 @@ public static byte[] SerializeBinary(Mesh mesh) {
126
150
127
151
writer . Write ( ( short ) 0 ) ;
128
152
}
129
- return stream . GetBuffer ( ) ;
153
+
154
+ return stream . ToArray ( ) ;
130
155
}
131
156
}
132
157
}
0 commit comments