Source code: com/trapezium/chisel/cleaners/IFS_ColorToDiffuseColor.java
1 /*
2 * @(#)IFS_ColorToDiffuseColor.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.cleaners;
12
13 import com.trapezium.parse.TokenTypes;
14 import com.trapezium.vrml.Value;
15 import com.trapezium.vrml.node.Node;
16 import com.trapezium.vrml.node.IndexedFaceSetVerifier;
17 import com.trapezium.vrml.node.DEFUSENode;
18 import com.trapezium.vrml.fields.Field;
19 import com.trapezium.vrml.fields.FieldValue;
20 import com.trapezium.vrml.fields.MFFieldValue;
21 import com.trapezium.chisel.*;
22
23 import java.util.BitSet;
24
25 /**
26 * This Chisel takes any single colored IFS within a Shape, and modifies it
27 * so that the color is indicated by the "diffuseColor" field of the material
28 * node of the appearance.
29 *
30 * The single color is detected if the IFS colorPerVertex is false, and the color
31 * node contains only one color, or if the colorIndex contains only one index value.
32 */
33
34 public class IFS_ColorToDiffuseColor extends Optimizer {
35
36 static public final int GenAppearance = 0;
37 static public final int GenMaterial = 1;
38 static public final int GenDiffuseColor = 2;
39 static public final int GenDiffuseColorReplacement = 3;
40
41 class GenDiffuse {
42 int type;
43 int c1offset;
44 int c2offset;
45 int c3offset;
46
47 GenDiffuse( Node ifs, int type ) {
48 this.type = type;
49 setColor( ifs );
50 }
51
52 void setColor( Node ifs ) {
53 Field color = ifs.getField( "color" );
54 Field colorIndex = ifs.getField( "colorIndex" );
55 if ( colorIndex != null ) {
56 int scanner = colorIndex.getFirstTokenOffset();
57 dataSource.setState( scanner );
58 scanner = dataSource.skipToNumber( 0 );
59 if (( scanner != -1 ) && ( scanner <= colorIndex.getLastTokenOffset() )) {
60 int value = dataSource.getIntValue( scanner );
61 scanner = color.getFirstTokenOffset();
62 dataSource.setState( scanner );
63 c1offset = dataSource.skipToNumber( value*3 );
64 scanner = dataSource.getNextToken();
65 c2offset = dataSource.skipToNumber( 0 );
66 scanner = dataSource.getNextToken();
67 c3offset = dataSource.skipToNumber( 0 );
68 }
69 } else {
70 int scanner = color.getFirstTokenOffset();
71 dataSource.setState( scanner );
72 c1offset = dataSource.skipToNumber( 0 );
73 scanner = dataSource.getNextToken();
74 c2offset = dataSource.skipToNumber( 0 );
75 scanner = dataSource.getNextToken();
76 c3offset = dataSource.skipToNumber( 0 );
77 }
78 }
79
80 int getType() {
81 return( type );
82 }
83
84 int getc1() {
85 return( c1offset );
86 }
87
88 int getc2() {
89 return( c2offset );
90 }
91
92 int getc3() {
93 return( c3offset );
94 }
95 }
96
97 public IFS_ColorToDiffuseColor() {
98 super( "Shape", "Replace single color with diffuse color..." );
99 }
100
101 public void attemptOptimization( Node n ) {
102 Node ifs = getSingleColorIFS( n );
103 if ( ifs != null ) {
104 // if either the appearance or material are DEF/USE, do nothing
105 Field appearanceF = n.getField( "appearance" );
106 if ( appearanceF != null ) {
107 Node appNode = appearanceF.getNode();
108 if ( appNode instanceof DEFUSENode ) {
109 DEFUSENode dun = (DEFUSENode)appNode;
110 if ( dun.isDEF() && dun.isUsed() ) {
111 return;
112 }
113 }
114 Field materialF = appNode.getField( "material" );
115 if ( materialF != null ) {
116 Node matNode = materialF.getNode();
117 if ( matNode instanceof DEFUSENode ) {
118 DEFUSENode dun = (DEFUSENode)matNode;
119 if ( dun.isDEF() && dun.isUsed() ) {
120 return;
121 }
122 }
123 }
124 }
125 Node appearance = getAppearance( n );
126 Node material = getMaterial( appearance );
127 Field color = ifs.getField( "color" );
128 Field colorIndex = ifs.getField( "colorIndex" );
129 if ( color != null ) {
130 replaceRange( color.getFirstTokenOffset(), color.getLastTokenOffset(), null );
131 }
132 if ( colorIndex != null ) {
133 replaceRange( colorIndex.getFirstTokenOffset(), colorIndex.getLastTokenOffset(), null );
134 }
135 Field colorPerVertex = ifs.getField( "colorPerVertex" );
136 if ( colorPerVertex != null ) {
137 replaceRange( colorPerVertex.getFirstTokenOffset(), colorPerVertex.getLastTokenOffset(), null );
138 }
139 if ( appearance == null ) {
140 int addition = 1;
141 if ( dataSource.sameAs( n.getFirstTokenOffset() + 1, "DEF" )) {
142 addition = 3;
143 }
144 replaceRange( n.getFirstTokenOffset(), n.getFirstTokenOffset() + addition,
145 new GenDiffuse( ifs, GenAppearance ));
146 } else if ( material == null ) {
147 int addition = 1;
148 if ( dataSource.sameAs( appearance.getFirstTokenOffset() + 1, "DEF" )) {
149 addition = 3;
150 }
151 replaceRange( appearance.getFirstTokenOffset(), appearance.getFirstTokenOffset() + addition,
152 new GenDiffuse( ifs, GenMaterial ));
153 } else {
154 Field diffuseColor = material.getField( "diffuseColor" );
155 if ( diffuseColor == null ) {
156 int addition = 1;
157 if ( dataSource.sameAs( material.getFirstTokenOffset() + 1, "DEF" )) {
158 addition = 3;
159 }
160 replaceRange( material.getFirstTokenOffset(), material.getFirstTokenOffset() + addition,
161 new GenDiffuse( ifs, GenDiffuseColor ));
162 } else {
163 replaceRange( diffuseColor.getFirstTokenOffset(), diffuseColor.getLastTokenOffset(),
164 new GenDiffuse( ifs, GenDiffuseColorReplacement ));
165 }
166 }
167 }
168 }
169
170 Node getAppearance( Node n ) {
171 Field appearance = n.getField( "appearance" );
172 if ( appearance != null ) {
173 return( appearance.getNodeValue() );
174 }
175 return( null );
176 }
177
178 Node getMaterial( Node appearance ) {
179 if ( appearance != null ) {
180 Field material = appearance.getField( "material" );
181 if ( material != null ) {
182 return( material.getNodeValue() );
183 }
184 }
185 return( null );
186 }
187
188 /** Return an IndexedFaceSet with a single color in the Shape node provided,
189 * if not found, returns null.
190 *
191 * Single color IFS that is acceptable is one in which color node is not
192 * DEF/USE, or corresponding Appearance or Material node is not DEF/USE
193 */
194 Node getSingleColorIFS( Node n ) {
195 Field geometry = n.getField( "geometry" );
196 if ( geometry != null ) {
197 Node geoNode = geometry.getNodeValue();
198 if ( geoNode != null ) {
199 if ( geoNode.getBaseName().compareTo( "IndexedFaceSet" ) == 0 ) {
200 if ( IndexedFaceSetVerifier.isSingleColor( geoNode, dataSource )) {
201 return( geoNode );
202 }
203 }
204 }
205 }
206 return( null );
207 }
208
209
210 /** Replace the coordIndex, get rid of bad faces, regenerate other fields */
211 public void optimize( TokenPrinter tp, Object param, int startTokenOffset, int endTokenOffset ) {
212 // null param indicates a color or colorIndex being wiped out
213 //System.out.println( "optimize from " + startTokenOffset + " to " + endTokenOffset );
214 if ( param instanceof GenDiffuse ) {
215 GenDiffuse gd = (GenDiffuse)param;
216 int type = gd.getType();
217 if ( type != GenDiffuseColorReplacement ) {
218 for ( int i = startTokenOffset; i <= endTokenOffset; i++ ) {
219 tp.print( dataSource, i );
220 }
221 }
222 if ( type == GenAppearance ) {
223 tp.print( "appearance Appearance { material Material { diffuseColor" );
224 tp.print( dataSource, gd.getc1() );
225 tp.print( dataSource, gd.getc2() );
226 tp.print( dataSource, gd.getc3() );
227 tp.print( " } }" );
228 } else if ( type == GenMaterial ) {
229 tp.print( "material Material { diffuseColor" );
230 tp.print( dataSource, gd.getc1() );
231 tp.print( dataSource, gd.getc2() );
232 tp.print( dataSource, gd.getc3() );
233 tp.print( "}" );
234 } else if (( type == GenDiffuseColor ) || ( type == GenDiffuseColorReplacement )) {
235 tp.print( "diffuseColor" );
236 tp.print( dataSource, gd.getc1() );
237 tp.print( dataSource, gd.getc2() );
238 tp.print( dataSource, gd.getc3() );
239 }
240 }
241 }
242 }
243
244