Source code: com/trapezium/chisel/reorganizers/ShapeConnectivitySplitter.java
1 /*
2 * @(#)ShapeConnectivitySplitter.java
3 *
4 * Copyright (c) 1998 by Trapezium Development LLC. All Rights Reserved.
5 *
6 * The information in this file is the property of Trapezium Development LLC
7 * and may be used only in accordance with the terms of the license granted
8 * by Trapezium.
9 *
10 */
11 package com.trapezium.chisel.reorganizers;
12
13 import com.trapezium.chisel.*;
14 import com.trapezium.chisel.reducers.IFS_SpaceStructureLoader;
15 import com.trapezium.parse.TokenTypes;
16 import com.trapezium.vrml.VrmlElement;
17 import com.trapezium.vrml.Value;
18 import com.trapezium.vrml.node.Node;
19 import com.trapezium.vrml.node.DEFUSENode;
20 import com.trapezium.vrml.node.space.SpaceStructure;
21 import com.trapezium.vrml.node.space.SpacePrimitive;
22 import com.trapezium.vrml.node.space.SpaceEntitySet;
23 import com.trapezium.vrml.fields.Field;
24 import com.trapezium.vrml.fields.FieldValue;
25 import com.trapezium.vrml.fields.MFFieldValue;
26 import java.util.BitSet;
27
28 /**
29 * Splits IndexedFaceSets into connectivity sections, each in its
30 * own IndexedFaceSet.
31 */
32 public class ShapeConnectivitySplitter extends IFS_SpaceStructureLoader {
33 SpaceStructure ss;
34 String[] skipFields;
35
36 public ShapeConnectivitySplitter() {
37 super( "Splitting IndexedFaceSet by connectivity..." );
38 skipFields = new String[ 5 ];
39 skipFields[0] = "coordIndex";
40 skipFields[1] = "color";
41 skipFields[2] = "colorIndex";
42 skipFields[3] = "normal";
43 skipFields[4] = "normalIndex";
44 }
45
46 class ConnectivityInfo {
47 Node shape;
48 Node ifs;
49 SpaceStructure ss;
50
51 public ConnectivityInfo( Node shape, SpaceStructure ss, Node ifs ) {
52 this.shape = shape;
53 this.ss = ss;
54 this.ifs = ifs;
55 }
56
57 public Node getShape() {
58 return( shape );
59 }
60
61 public Node getIFS() {
62 return( ifs );
63 }
64
65 public SpaceStructure getSpaceStructure() {
66 return( ss );
67 }
68 }
69
70 public void setSpaceStructure( SpaceStructure ss ) {
71 this.ss = ss;
72 }
73
74 /** This chisel taks the approach of just replacing entire Shape node.
75 * This approach is a mistake, makes PROTO/IS handling nearly impossible.
76 * Have to rewrite this to use field-by-field replacement technique.
77 */
78 public void attemptOptimization( Node n ) {
79 System.out.println( "ShapeConnectivitySplitter attemptOptimization" );
80 ss = null;
81 super.attemptOptimization( n );
82 if ( ss != null ) {
83 Node shape = n.getParent( "Shape" );
84 if ( shape != null ) {
85 replaceRange( shape.getFirstTokenOffset(), shape.getLastTokenOffset(), new ConnectivityInfo( shape, ss, n ));
86 }
87 }
88 }
89
90
91 public void optimize( TokenPrinter tp, Object param, int startTokenOffset, int endTokenOffset ) {
92 System.out.println( "ShapeConnectivitySplitter optimizing" );
93 if ( param instanceof ConnectivityInfo ) {
94 ConnectivityInfo info = (ConnectivityInfo)param;
95 SpaceStructure ss = info.getSpaceStructure();
96 Node ifs = info.getIFS();
97 System.out.println( "marking connectivity" );
98 ss.markConnectivity();
99 int numberConnected = ss.numberConnectivity();
100 System.out.println( numberConnected + " connected" );
101 if ( numberConnected <= 1 ) {
102 tp.printRange( startTokenOffset, endTokenOffset, false );
103 } else {
104 initOffsets( ifs );
105 for ( int i = 0; i < numberConnected; i++ ) {
106 System.out.println( "Generating shape " + (i+1) + " of " + numberConnected );
107 printHeader( tp, startTokenOffset, endTokenOffset );
108 printSkippingFields( tp, ifs, skipFields );
109 printCoordIndex( tp, ss, i );
110 printColorInfo( tp, ss, i, ifs );
111 printNormalInfo( tp, ss, i, ifs );
112 printTrailer( tp, endTokenOffset );
113 }
114 }
115 }
116 }
117
118 /** Print up to first field in IFS */
119 int firstIFSfieldOffset;
120 int lastIFSfieldOffset;
121 String[] fieldNames;
122 void setFieldOffset( Field f ) {
123 if ( f != null ) {
124 int firstOffset = f.getFirstTokenOffset();
125 int lastOffset = f.getLastTokenOffset();
126 if ( firstOffset != -1 ) {
127 if ( firstIFSfieldOffset == -1 ) {
128 firstIFSfieldOffset = firstOffset;
129 } else if ( firstOffset < firstIFSfieldOffset ) {
130 firstIFSfieldOffset = firstOffset;
131 }
132 }
133 if ( lastOffset != -1 ) {
134 if ( lastIFSfieldOffset == -1 ) {
135 lastIFSfieldOffset = lastOffset;
136 } else if ( lastOffset > lastIFSfieldOffset ) {
137 lastIFSfieldOffset = lastOffset;
138 }
139 }
140 }
141 }
142
143 void initOffsets( Node ifs ) {
144 firstIFSfieldOffset = -1;
145 lastIFSfieldOffset = -1;
146 if ( fieldNames == null ) {
147 fieldNames = ifs.getFieldNames();
148 }
149 for ( int i = 0; i < fieldNames.length; i++ ) {
150 setFieldOffset( ifs.getField( fieldNames[i] ));
151 }
152 }
153
154 void printHeader( TokenPrinter tp, int startTokenOffset, int endTokenOffset ) {
155 printRange( tp, startTokenOffset, firstIFSfieldOffset, endTokenOffset );
156 }
157
158 void printTrailer( TokenPrinter tp, int endTokenOffset ) {
159 printRange( tp, lastIFSfieldOffset + 1, endTokenOffset + 1, endTokenOffset );
160 }
161
162 void printRange( TokenPrinter tp, int firstInRange, int lastInRange, int tokenBoundary ) {
163 int scanner = firstInRange;
164 dataSource.setState( scanner );
165 while ( scanner != -1 ) {
166 if ( scanner > tokenBoundary ) {
167 break;
168 }
169 tp.print( dataSource, scanner );
170 scanner = dataSource.getNextToken();
171 if ( scanner >= lastInRange ) {
172 break;
173 }
174 }
175 }
176
177 /** Print color info for a specific connectivity section */
178 void printColorInfo( TokenPrinter tp, SpaceStructure ss, int offset, Node ifs ) {
179 Field color = ifs.getField( "color" );
180 Field colorIndex = ifs.getField( "colorIndex" );
181 boolean colorPerVertex = ifs.getBoolValue( "colorPerVertex" );
182 if ( colorPerVertex ) {
183 if ( color != null ) {
184 tp.printRange( color.getFirstTokenOffset(), color.getLastTokenOffset(), false );
185 }
186 if ( colorIndex != null ) {
187 tp.printRange( colorIndex.getFirstTokenOffset(), colorIndex.getLastTokenOffset(), false );
188 }
189 } else {
190 if ( colorIndex == null ) {
191 if ( color != null ) {
192 printValues( tp, ss, offset, color.getFirstTokenOffset(),
193 color.getLastTokenOffset(), 3 );
194 }
195 } else {
196 printValues( tp, ss, offset, colorIndex.getFirstTokenOffset(),
197 colorIndex.getLastTokenOffset(), 1 );
198 }
199 }
200 }
201
202 /** Print normal info for a specific connectivity section */
203 void printNormalInfo( TokenPrinter tp, SpaceStructure ss, int offset, Node ifs ) {
204 Field normal = ifs.getField( "normal" );
205 Field normalIndex = ifs.getField( "normalIndex" );
206 boolean normalPerVertex = ifs.getBoolValue( "normalPerVertex" );
207 if ( !normalPerVertex ) {
208 if ( normalIndex == null ) {
209 if ( normal != null ) {
210 printValues( tp, ss, offset, normal.getFirstTokenOffset(),
211 normal.getLastTokenOffset(), 3 );
212 }
213 } else {
214 printValues( tp, ss, offset, normalIndex.getFirstTokenOffset(), normalIndex.getLastTokenOffset(), 1 );
215 }
216 }
217 }
218
219 void printValues( TokenPrinter tp, SpaceStructure ss, int offset,
220 int scanner, int endTokenOffset, int factor ) {
221 dataSource.setState( scanner );
222 while ( true ) {
223 int type = dataSource.getType( scanner );
224 tp.print( dataSource, scanner, type );
225 if ( type == TokenTypes.LeftBracket ) {
226 scanner = dataSource.getNextToken();
227 break;
228 }
229 scanner = dataSource.getNextToken();
230 }
231 SpaceEntitySet faces = ss.getEntitySet( SpacePrimitive.Face );
232 int numberFaces = faces.getNumberEntities();
233 for ( int i = 0; i < numberFaces; i++ ) {
234 if ( ss.getConnectivity( i ) == offset ) {
235 for ( int j = 0; j < factor; j++ ) {
236 scanner = dataSource.skipNonNumbers();
237 tp.print( dataSource, scanner, TokenTypes.NumberToken );
238 scanner = dataSource.getNextToken();
239 }
240 } else {
241 for ( int j = 0; j < factor; j++ ) {
242 scanner = dataSource.skipNonNumbers();
243 scanner = dataSource.getNextToken();
244 }
245 }
246 }
247 while ( true ) {
248 tp.print( dataSource, scanner );
249 if ( scanner == endTokenOffset ) {
250 break;
251 }
252 scanner = dataSource.getNextToken();
253 }
254 }
255
256 void printCoordIndex( TokenPrinter tp, SpaceStructure ss, int offset ) {
257 tp.print( "coordIndex [" );
258 SpaceEntitySet faces = ss.getEntitySet( SpacePrimitive.Face );
259 int numberFaces = faces.getNumberEntities();
260 for ( int i = 0; i < numberFaces; i++ ) {
261 if ( ss.getConnectivity( i ) == offset ) {
262 printFace( tp, ss, faces, faces.getEntity( i ));
263 }
264 }
265 tp.print( "]" );
266 }
267
268 void printFace( TokenPrinter tp, SpaceStructure ss, SpaceEntitySet faces, SpacePrimitive face ) {
269 int numberVertices = faces.getCount( face, SpacePrimitive.Vertex );
270 for ( int i = 0; i < numberVertices; i++ ) {
271 tp.print( faces.getValue( face, SpacePrimitive.Vertex, i ));
272 }
273 tp.print( -1 );
274 }
275
276 void printSkippingFields( TokenPrinter tp, Node ifs, String[] fieldList ) {
277 int[] startFieldOffset = new int[fieldList.length];
278 int[] endFieldOffset = new int[fieldList.length];
279 int scanner = firstIFSfieldOffset;
280 int end = lastIFSfieldOffset+1;
281 dataSource.setState( scanner );
282 if ( end > scanner ) {
283 int range = end - scanner;
284 BitSet unprintable = new BitSet( range );
285 for ( int i = 0; i < fieldList.length; i++ ) {
286 Field f = ifs.getField( fieldList[i] );
287 if ( f != null ) {
288 int firstInRange = f.getFirstTokenOffset() - scanner;
289 int lastInRange = f.getLastTokenOffset() - scanner;
290 if (( firstInRange >= 0 ) && ( firstInRange < range ) &&
291 ( lastInRange >= 0 ) && ( lastInRange < range ) &&
292 ( lastInRange >= firstInRange )) {
293 for ( int j = firstInRange; j <= lastInRange; j++ ) {
294 unprintable.set( j );
295 }
296 }
297 }
298 }
299 while ( scanner < end ) {
300 if ( unprintable.get( scanner - firstIFSfieldOffset )) {
301 scanner = dataSource.getNextToken();
302 continue;
303 }
304 tp.print( dataSource, scanner );
305 scanner = dataSource.getNextToken();
306 }
307 }
308 }
309
310
311
312 public void replaceCoord( TokenPrinter tp, SpaceStructure ss, int startTokenOffset, int endTokenOffset ) {
313 }
314
315 public void replaceCoordIndex( TokenPrinter tp, SpaceStructure ss, int startTokenOffset, int endTokenOffset ) {
316 }
317
318 public void replaceTexCoordIndex( TokenPrinter tp, SpaceStructure ss, int startTokenOffset, int endTokenOffset ) {
319 }
320 }
321
322