Source code: com/trapezium/chisel/mutators/IFS_Triangulator.java
1 package com.trapezium.chisel.mutators;
2
3 import com.trapezium.chisel.*;
4
5 import com.trapezium.vrml.fields.Field;
6 import com.trapezium.vrml.fields.FieldValue;
7 import com.trapezium.vrml.fields.MFFieldValue;
8 import com.trapezium.vrml.node.Node;
9 import java.io.PrintStream;
10
11 public class IFS_Triangulator extends Optimizer {
12 class TriParam {
13 Field color;
14 Field colorIndex;
15 Field normal;
16 Field normalIndex;
17 int rawValueCount;
18
19 TriParam( Field color, Field colorIndex, Field normal, Field normalIndex, int rawValueCount ) {
20 this.color = color;
21 this.colorIndex = colorIndex;
22 this.normal = normal;
23 this.normalIndex = normalIndex;
24 this.rawValueCount = rawValueCount;
25 }
26
27 Field getNormal() {
28 return( normal );
29 }
30
31 Field getNormalIndex() {
32 return( normalIndex );
33 }
34
35 Field getColor() {
36 return( color );
37 }
38
39 Field getColorIndex() {
40 return( colorIndex );
41 }
42
43 int getApproxFaceCount() {
44 return( rawValueCount/4 );
45 }
46 }
47
48 boolean triangulateQuads = true;
49
50 public IFS_Triangulator() {
51 super( "IndexedFaceSet", "Triangulating all faces..." );
52 }
53
54 public void attemptOptimization( Node n ) {
55 Field coordIndex = n.getField( "coordIndex" );
56 if ( coordIndex != null ) {
57 Field colorIndex = n.getField( "colorIndex" );
58 Field color = n.getField( "color" );
59 if ( n.getBoolValue( "colorPerVertex" )) {
60 colorIndex = null;
61 color = null;
62 } else if ( colorIndex != null ) {
63 color = null;
64 }
65 Field normalIndex = n.getField( "normalIndex" );
66 Field normal = n.getField( "normal" );
67 if ( n.getBoolValue( "normalPerVertex" )) {
68 normalIndex = null;
69 normal = null;
70 } else if ( normalIndex != null ) {
71 normal = null;
72 }
73 FieldValue fv = coordIndex.getFieldValue();
74 if (( fv != null ) && ( fv instanceof MFFieldValue )) {
75 MFFieldValue mfv = (MFFieldValue)fv;
76 if ( mfv.getRawValueCount() > 0 ) {
77 replaceRange( coordIndex.getFirstTokenOffset(), coordIndex.getLastTokenOffset(), new TriParam( color, colorIndex, normal, normalIndex, mfv.getRawValueCount() ));
78 }
79 if ( colorIndex != null ) {
80 replaceRange( colorIndex.getFirstTokenOffset(), colorIndex.getLastTokenOffset(), null );
81 }
82 if ( color != null ) {
83 replaceRange( color.getFirstTokenOffset(), color.getLastTokenOffset(), null );
84 }
85 if ( normalIndex != null ) {
86 replaceRange( normalIndex.getFirstTokenOffset(), normalIndex.getLastTokenOffset(), null );
87 }
88 if ( normal != null ) {
89 replaceRange( normal.getFirstTokenOffset(), normal.getLastTokenOffset(), null );
90 }
91 }
92 }
93 }
94
95 class Triangle {
96 int v1;
97 int v2;
98 int v3;
99
100 Triangle() {
101 reset();
102 }
103
104 int getV1() {
105 return( v1 );
106 }
107
108 int getV2() {
109 return( v2 );
110 }
111
112 int getV3() {
113 return( v3 );
114 }
115
116 void reset() {
117 v1 = -1;
118 v2 = -1;
119 v3 = -1;
120 }
121
122 boolean isFull() {
123 return( (v1 != -1) && (v2 != -1) && (v3 != -1) );
124 }
125
126 void add( int value ) {
127 if ( value == -1 ) {
128 reset();
129 } else if ( v1 == -1 ) {
130 v1 = value;
131 } else if ( v2 == -1 ) {
132 v2 = value;
133 } else if ( v3 == -1 ) {
134 v3 = value;
135 }
136 }
137
138 void shiftTriangle() {
139 v2 = v3;
140 v3 = -1;
141 }
142 }
143
144
145 // RangeReplacer calls this when it has a range of tokens to replace
146 public void optimize( TokenPrinter tp, Object param, int startTokenOffset, int endTokenOffset ) {
147 if ( param == null ) {
148 return;
149 }
150 TriParam tparam = (TriParam)param;
151 Field colorIndex = tparam.getColorIndex();
152 Field color = tparam.getColor();
153 Field normalIndex = tparam.getNormalIndex();
154 Field normal = tparam.getNormal();
155 int faceCount = tparam.getApproxFaceCount();
156 int[] faceMultiple = null;
157 if (( colorIndex != null ) || ( color != null ) || ( normalIndex != null ) || ( normal != null )) {
158 faceMultiple = new int[ faceCount ];
159 }
160
161 int scanner = startTokenOffset;
162 dataSource.setState( scanner );
163 Triangle t = new Triangle();
164 int faceNo = 0;
165 while ( scanner != -1 ) {
166 if ( dataSource.isNumber( scanner )) {
167 int value = dataSource.getIntValue( scanner );
168 t.add( value );
169 if ( t.isFull() ) {
170 if ( triangulateQuads ) {
171 tp.print( t.getV1() );
172 tp.print( t.getV2() );
173 tp.print( t.getV3() );
174 tp.print( -1 );
175 t.shiftTriangle();
176 if (( faceNo < faceCount ) && ( faceMultiple != null )) {
177 faceMultiple[ faceNo ] += 1;
178 }
179
180 }
181 }
182 if ( value == -1 ) {
183 faceNo++;
184 }
185 } else {
186 tp.print( dataSource, scanner );
187 }
188 if ( scanner == endTokenOffset ) {
189 break;
190 }
191 scanner = dataSource.getNextToken();
192 }
193
194 // if we have to deal with colors, do it here
195 if ( colorIndex != null ) {
196 replaceIndexFaceMultiple( tp, colorIndex, faceMultiple, faceCount );
197 }
198
199 if ( color != null ) {
200 replaceValueNodeFaceMultiple( tp, color, faceMultiple, faceCount );
201 }
202
203 if ( normalIndex != null ) {
204 replaceIndexFaceMultiple( tp, normalIndex, faceMultiple, faceCount );
205 }
206
207 if ( normal != null ) {
208 replaceValueNodeFaceMultiple( tp, normal, faceMultiple, faceCount );
209 }
210 }
211
212 public void summarize( PrintStream ps ) {
213 }
214 }
215
216