001: /*
002: * $RCSfile: PolygonAttributesRetained.java,v $
003: *
004: * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.7 $
028: * $Date: 2008/02/28 20:17:28 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.ArrayList;
035:
036: /**
037: * The PolygonAttributes object defines all rendering state that can be set
038: * as a component object of a Shape3D node.
039: */
040: class PolygonAttributesRetained extends NodeComponentRetained {
041: // A list of pre-defined bits to indicate which component
042: // in this LineAttributesRetained object changed.
043: static final int POLYGON_MODE_CHANGED = 0x01;
044: static final int POLYGON_CULL_CHANGED = 0x02;
045: static final int POLYGON_OFFSET_CHANGED = 0x04;
046: static final int POLYGON_BACKFACENORMALFLIP_CHANGED = 0x08;
047: static final int POLYGON_OFFSETFACTOR_CHANGED = 0x10;
048:
049: // Polygon rasterization mode (point, line, fill)
050: int polygonMode = PolygonAttributes.POLYGON_FILL;
051:
052: // Face culling mode
053: int cullFace = PolygonAttributes.CULL_BACK;
054:
055: // back face normal flip flag
056: boolean backFaceNormalFlip = false;
057:
058: // constant polygon offset
059: float polygonOffset;
060:
061: // polygon offset factor
062: float polygonOffsetFactor;
063:
064: /**
065: * Sets the face culling for this
066: * appearance component object,
067: * @param cullFace the face to be culled, one of:
068: * CULL_NONE, CULL_FRONT, or CULL_BACK
069: */
070: final void initCullFace(int cullFace) {
071: this .cullFace = cullFace;
072: }
073:
074: /**
075: * Sets the face culling for this
076: * appearance component object and sends a message notifying
077: * the interested structures of the change.
078: * @param cullFace the face to be culled, one of:
079: * CULL_NONE, CULL_FRONT, or CULL_BACK
080: */
081: final void setCullFace(int cullFace) {
082: initCullFace(cullFace);
083: sendMessage(POLYGON_CULL_CHANGED, new Integer(cullFace));
084: }
085:
086: /**
087: * Gets the face culling for this
088: * appearance component object.
089: * @return the face to be culled
090: */
091: final int getCullFace() {
092: return cullFace;
093: }
094:
095: /**
096: * Sets the back face normal flip flag to the specified value
097: * This flag indicates whether vertex normals of back facing polygons
098: * should be flipped (negated) prior to lighting. When this flag
099: * is set to true and back face culling is disabled, polygons are
100: * rendered as if the polygon had two sides with opposing normals.
101: * This feature is disabled by default
102: * @param backFaceNormalFlip the back face normal flip flag
103: */
104: final void initBackFaceNormalFlip(boolean backFaceNormalFlip) {
105: this .backFaceNormalFlip = backFaceNormalFlip;
106: }
107:
108: /**
109: * Sets the back face normal flip flag to the specified value
110: * and sends a message notifying
111: * the interested structures of the change.
112: * This flag indicates whether vertex normals of back facing polygons
113: * should be flipped (negated) prior to lighting. When this flag
114: * is set to true and back face culling is disabled, polygons are
115: * rendered as if the polygon had two sides with opposing normals.
116: * This feature is disabled by default
117: * @param backFaceNormalFlip the back face normal flip flag
118: */
119: final void setBackFaceNormalFlip(boolean backFaceNormalFlip) {
120: initBackFaceNormalFlip(backFaceNormalFlip);
121: sendMessage(POLYGON_BACKFACENORMALFLIP_CHANGED,
122: (backFaceNormalFlip ? Boolean.TRUE : Boolean.FALSE));
123: }
124:
125: /**
126: * Gets the back face normal flip flag.
127: * @return the back face normal flip flag
128: */
129: final boolean getBackFaceNormalFlip() {
130: return backFaceNormalFlip;
131: }
132:
133: /**
134: * Sets the polygon rasterization mode for this
135: * appearance component object.
136: * @param polygonMode the polygon rasterization mode to be used; one of
137: * POLYGON_FILL, POLYGON_LINE, or POLYGON_POINT
138: */
139: final void initPolygonMode(int polygonMode) {
140: this .polygonMode = polygonMode;
141: }
142:
143: /**
144: * Sets the polygon rasterization mode for this
145: * appearance component object and sends a message notifying
146: * the interested structures of the change.
147: * @param polygonMode the polygon rasterization mode to be used; one of
148: * POLYGON_FILL, POLYGON_LINE, or POLYGON_POINT
149: */
150: final void setPolygonMode(int polygonMode) {
151: initPolygonMode(polygonMode);
152: sendMessage(POLYGON_MODE_CHANGED, new Integer(polygonMode));
153: }
154:
155: /**
156: * Gets the polygon rasterization mode for this
157: * appearance component object.
158: * @return polygonMode the polygon rasterization mode
159: */
160: final int getPolygonMode() {
161: return polygonMode;
162: }
163:
164: /**
165: * Sets the polygon offset to the specified value and sends a
166: * message notifying the interested structures of the change.
167: * This screen space offset is added to the final, device
168: * coordinate Z value of polygon primitives.
169: * @param polygonOffset the polygon offset
170: */
171: final void initPolygonOffset(float polygonOffset) {
172: this .polygonOffset = polygonOffset;
173: }
174:
175: /**
176: * Sets the polygon offset to the specified value and sends a
177: * message notifying the interested structures of the change.
178: * This screen space offset is added to the final, device
179: * coordinate Z value of polygon primitives.
180: * @param polygonOffset the polygon offset
181: */
182: final void setPolygonOffset(float polygonOffset) {
183: initPolygonOffset(polygonOffset);
184: sendMessage(POLYGON_OFFSET_CHANGED, new Float(polygonOffset));
185: }
186:
187: /**
188: * Gets the polygon offset.
189: * @return polygonOffset the polygon offset
190: */
191: final float getPolygonOffset() {
192: return polygonOffset;
193: }
194:
195: /**
196: * Sets the polygon offset factor to the specified value and sends a
197: * message notifying the interested structures of the change.
198: * This factor is multiplied by the slope of the polygon, and
199: * then added to the final, device coordinate Z value of polygon
200: * primitives.
201: * @param polygonOffsetFactor the polygon offset factor
202: */
203: final void initPolygonOffsetFactor(float polygonOffsetFactor) {
204: this .polygonOffsetFactor = polygonOffsetFactor;
205: }
206:
207: /**
208: * Sets the polygon offset factor to the specified value and sends a
209: * message notifying the interested structures of the change.
210: * This factor is multiplied by the slope of the polygon, and
211: * then added to the final, device coordinate Z value of polygon
212: * primitives.
213: * @param polygonOffsetFactor the polygon offset
214: */
215: final void setPolygonOffsetFactor(float polygonOffsetFactor) {
216: initPolygonOffsetFactor(polygonOffsetFactor);
217: sendMessage(POLYGON_OFFSETFACTOR_CHANGED, new Float(
218: polygonOffsetFactor));
219: }
220:
221: /**
222: * Gets the polygon offset factor.
223: * @return polygonOffset the polygon offset factor
224: */
225: final float getPolygonOffsetFactor() {
226: return polygonOffsetFactor;
227: }
228:
229: /**
230: * Creates and initializes a mirror object, point the mirror object
231: * to the retained object if the object is not editable
232: */
233: synchronized void createMirrorObject() {
234: if (mirror == null) {
235: // Check the capability bits and let the mirror object
236: // point to itself if is not editable
237: if (isStatic()) {
238: mirror = this ;
239: } else {
240: PolygonAttributesRetained mirrorPa = new PolygonAttributesRetained();
241: mirrorPa.set(this );
242: mirrorPa.source = source;
243: mirror = mirrorPa;
244: }
245: } else {
246: ((PolygonAttributesRetained) mirror).set(this );
247: }
248: }
249:
250: /**
251: * Updates the native context
252: */
253: void updateNative(Context ctx) {
254: Pipeline.getPipeline().updatePolygonAttributes(ctx,
255: polygonMode, cullFace, backFaceNormalFlip,
256: polygonOffset, polygonOffsetFactor);
257: }
258:
259: /**
260: * Initializes a mirror object, point the mirror object to the retained
261: * object if the object is not editable
262: */
263: synchronized void initMirrorObject() {
264: ((PolygonAttributesRetained) mirror).set(this );
265: }
266:
267: /**
268: * Update the "component" field of the mirror object with the
269: * given "value"
270: */
271: synchronized void updateMirrorObject(int component, Object value) {
272:
273: PolygonAttributesRetained mirrorPa = (PolygonAttributesRetained) mirror;
274:
275: if ((component & POLYGON_MODE_CHANGED) != 0) {
276: mirrorPa.polygonMode = ((Integer) value).intValue();
277: } else if ((component & POLYGON_CULL_CHANGED) != 0) {
278: mirrorPa.cullFace = ((Integer) value).intValue();
279: } else if ((component & POLYGON_BACKFACENORMALFLIP_CHANGED) != 0) {
280: mirrorPa.backFaceNormalFlip = ((Boolean) value)
281: .booleanValue();
282: } else if ((component & POLYGON_OFFSET_CHANGED) != 0) {
283: mirrorPa.polygonOffset = ((Float) value).floatValue();
284: } else if ((component & POLYGON_OFFSETFACTOR_CHANGED) != 0) {
285: mirrorPa.polygonOffsetFactor = ((Float) value).floatValue();
286: }
287: }
288:
289: boolean equivalent(PolygonAttributesRetained pr) {
290: return ((pr != null) && (pr.cullFace == cullFace)
291: && (pr.backFaceNormalFlip == backFaceNormalFlip)
292: && (pr.polygonOffset == polygonOffset)
293: && (pr.polygonMode == polygonMode) && (pr.polygonOffsetFactor == polygonOffsetFactor));
294: }
295:
296: protected void set(PolygonAttributesRetained pr) {
297: super .set(pr);
298: cullFace = pr.cullFace;
299: backFaceNormalFlip = pr.backFaceNormalFlip;
300: polygonMode = pr.polygonMode;
301: polygonOffset = pr.polygonOffset;
302: polygonOffsetFactor = pr.polygonOffsetFactor;
303: }
304:
305: final void sendMessage(int attrMask, Object attr) {
306: ArrayList univList = new ArrayList();
307: ArrayList gaList = Shape3DRetained.getGeomAtomsList(
308: mirror.users, univList);
309:
310: // Send to rendering attribute structure, regardless of
311: // whether there are users or not (alternate appearance case ..)
312: J3dMessage createMessage = new J3dMessage();
313: createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
314: createMessage.type = J3dMessage.POLYGONATTRIBUTES_CHANGED;
315: createMessage.universe = null;
316: createMessage.args[0] = this ;
317: createMessage.args[1] = new Integer(attrMask);
318: createMessage.args[2] = attr;
319: createMessage.args[3] = new Integer(changedFrequent);
320: VirtualUniverse.mc.processMessage(createMessage);
321:
322: // System.err.println("univList.size is " + univList.size());
323: for (int i = 0; i < univList.size(); i++) {
324: createMessage = new J3dMessage();
325: createMessage.threads = J3dThread.UPDATE_RENDER;
326: createMessage.type = J3dMessage.POLYGONATTRIBUTES_CHANGED;
327:
328: createMessage.universe = (VirtualUniverse) univList.get(i);
329: createMessage.args[0] = this ;
330: createMessage.args[1] = new Integer(attrMask);
331: createMessage.args[2] = attr;
332:
333: ArrayList gL = (ArrayList) gaList.get(i);
334: GeometryAtom[] gaArr = new GeometryAtom[gL.size()];
335: gL.toArray(gaArr);
336: createMessage.args[3] = gaArr;
337:
338: VirtualUniverse.mc.processMessage(createMessage);
339: }
340:
341: }
342:
343: void handleFrequencyChange(int bit) {
344: if (bit == PolygonAttributes.ALLOW_CULL_FACE_WRITE
345: || bit == PolygonAttributes.ALLOW_NORMAL_FLIP_WRITE
346: || bit == PolygonAttributes.ALLOW_MODE_WRITE
347: || bit == PolygonAttributes.ALLOW_OFFSET_WRITE) {
348: setFrequencyChangeMask(bit, 0x1);
349: }
350: }
351:
352: }
|