001: /*
002: * $RCSfile: EnvironmentSet.java,v $
003: *
004: * Copyright 1999-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.9 $
028: * $Date: 2008/02/28 20:17:21 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.*;
035: import java.util.*;
036:
037: /**
038: * The LightBin manages a collection of EnvironmentSet objects.
039: * The number of objects managed depends upon the number of Lights
040: * in each EnvironmentSet and the number of lights supported by
041: * the underlying rendering layer.
042: */
043:
044: class EnvironmentSet extends Object implements ObjectUpdate {
045: // A list of pre-defined bits to indicate which component
046: // of the rendermolecule changed
047: static final int LIGHTENABLE_CHANGED = 0x01;
048: static final int AMBIENT_CHANGED = 0x02;
049: static final int FOG_CHANGED = 0x04;
050: static final int MODELCLIP_CHANGED = 0x08;
051:
052: /**
053: * The ArrayList of Lights in this EnvironmentSet
054: */
055: ArrayList lights = new ArrayList();
056:
057: /**
058: * The position of the light in the lightbin that the
059: * lights in this environment set corresponds to
060: */
061: int[] ltPos = null;
062:
063: /**
064: * The arraylist of ambient lights in this env list
065: */
066: ArrayList ambLights = new ArrayList();
067:
068: /**
069: * The LightBin that this EnvironmentSet resides
070: */
071: LightBin lightBin = null;
072:
073: /**
074: * The bitmask of light slots that need to be enabled for this
075: */
076: long enableMask = 0;
077:
078: /**
079: * The cached scene ambient component for this EnvirionmentSet
080: */
081: Color3f sceneAmbient = new Color3f();
082:
083: /**
084: * The RenderBin for this EnvirionmentSet
085: */
086: RenderBin renderBin = null;
087:
088: /**
089: * The fog for this EnvironmentSet
090: */
091: FogRetained fog = null;
092:
093: /**
094: * The model clip for this EnvironmentSet
095: */
096: ModelClipRetained modelClip = null;
097:
098: /**
099: * enable mask for the model clip planes in this environment set
100: */
101: int enableMCMask = 0; // enable mask used in modelClip.update()
102: int enableMCMaskCache = 0; // enable mask computed in renderBin that
103: // is copied into enableMCMask in updateObject
104:
105: /**
106: * The references to the next and previous LightBins in the
107: * list.
108: */
109: EnvironmentSet next = null;
110: EnvironmentSet prev = null;
111:
112: /**
113: * List of attrributeBins to be added next Frame
114: */
115: ArrayList addAttributeBins = new ArrayList();
116:
117: /**
118: * Canvas Dirty Mask for
119: */
120: int canvasDirty = 0;
121:
122: /**
123: * cached value of enable mask
124: */
125: long enableMaskCache = 0;
126:
127: /**
128: *
129: */
130: boolean onUpdateList = false;
131:
132: /**
133: * The list of AttributeBins in this EnvironmentSet
134: */
135: AttributeBin attributeBinList = null;
136:
137: EnvironmentSet(RenderAtom ra, LightRetained[] lightList,
138: FogRetained fog, ModelClipRetained modelClip, RenderBin rb) {
139: renderBin = rb;
140: reset(ra, lightList, fog, modelClip);
141: }
142:
143: private void reset(RenderAtom ra, LightRetained[] lightList,
144: FogRetained fog, ModelClipRetained modelClip) {
145: int i;
146: LightRetained light;
147:
148: prev = null;
149: next = null;
150: onUpdateList = false;
151: attributeBinList = null;
152: lights.clear();
153: ambLights.clear();
154: sceneAmbient.x = 0.0f;
155: sceneAmbient.y = 0.0f;
156: sceneAmbient.z = 0.0f;
157: if (lightList != null) {
158: for (i = 0; i < lightList.length; i++) {
159: light = lightList[i];
160: if (light.nodeType == NodeRetained.AMBIENTLIGHT) {
161: ambLights.add(light);
162: sceneAmbient.x += light.color.x;
163: sceneAmbient.y += light.color.y;
164: sceneAmbient.z += light.color.z;
165: } else {
166: lights.add(light);
167: }
168: }
169: if (sceneAmbient.x > 1.0f) {
170: sceneAmbient.x = 1.0f;
171: }
172: if (sceneAmbient.y > 1.0f) {
173: sceneAmbient.y = 1.0f;
174: }
175: if (sceneAmbient.z > 1.0f) {
176: sceneAmbient.z = 1.0f;
177: }
178: }
179:
180: this .fog = fog;
181:
182: this .modelClip = modelClip;
183: enableMCMaskCache = 0;
184: if (modelClip != null) {
185: for (i = 0; i < 6; i++) {
186: if (modelClip.enables[i])
187: enableMCMaskCache |= 1 << i;
188: }
189: enableMCMask = enableMCMaskCache;
190: }
191:
192: // Allocate the ltPos array
193: ltPos = new int[lights.size()];
194: enableMask = 0;
195:
196: // Issue 466 : add the env set to the light, fog, and model clip
197: // lists only after the newly constructed env set is initialized
198: if (lightList != null) {
199: for (i = 0; i < lightList.length; i++) {
200: lightList[i].environmentSets.add(this );
201: }
202: }
203:
204: if (fog != null) {
205: fog.environmentSets.add(this );
206: }
207:
208: if (modelClip != null) {
209: modelClip.environmentSets.add(this );
210: }
211: }
212:
213: /**
214: * This tests if the qiven lights and fog match this EnviornmentSet
215: */
216: boolean equals(RenderAtom ra, LightRetained[] lights,
217: FogRetained fog, ModelClipRetained modelClip) {
218: int i;
219:
220: // First see if the lights match.
221: if (lights == null && ambLights == null) {
222: if (this .lights.size() == 0) {
223: if (this .fog == fog) {
224: return (true);
225: } else {
226: return (false);
227: }
228: } else {
229: return (false);
230: }
231: }
232:
233: if ((this .lights.size() + this .ambLights.size()) != lights.length) {
234: return (false);
235: }
236:
237: for (i = 0; i < lights.length; i++) {
238: if (lights[i].nodeType == LightRetained.AMBIENTLIGHT) {
239: if (!this .ambLights.contains(lights[i])) {
240: return (false);
241: }
242: } else {
243: if (!this .lights.contains(lights[i])) {
244: return (false);
245: }
246: }
247: }
248:
249: // Now check fog
250: if (this .fog != fog) {
251: return (false);
252: }
253:
254: // Now check model clip
255: if (this .modelClip != modelClip) {
256: return (false);
257: }
258:
259: return (true);
260: }
261:
262: /**
263: * This tests if the qiven lights match this EnviornmentSet
264: */
265: boolean equalLights(LightRetained[] lights) {
266: int i;
267:
268: // First see if the lights match.
269: if (lights == null && ambLights == null) {
270: if (this .lights.size() == 0) {
271: return (true);
272: }
273: }
274:
275: if ((this .lights.size() + this .ambLights.size()) != lights.length) {
276: return (false);
277: }
278:
279: for (i = 0; i < lights.length; i++) {
280: if (lights[i].nodeType == LightRetained.AMBIENTLIGHT) {
281: if (!this .ambLights.contains(lights[i])) {
282: return (false);
283: }
284: } else {
285: if (!this .lights.contains(lights[i])) {
286: return (false);
287: }
288: }
289: }
290:
291: return (true);
292: }
293:
294: public void updateObject() {
295: int i;
296: AttributeBin a;
297:
298: if (addAttributeBins.size() > 0) {
299: a = (AttributeBin) addAttributeBins.get(0);
300: if (attributeBinList == null) {
301: attributeBinList = a;
302:
303: } else {
304: a.next = attributeBinList;
305: attributeBinList.prev = a;
306: attributeBinList = a;
307: }
308: for (i = 1; i < addAttributeBins.size(); i++) {
309: a = (AttributeBin) addAttributeBins.get(i);
310: a.next = attributeBinList;
311: attributeBinList.prev = a;
312: attributeBinList = a;
313: }
314: }
315:
316: addAttributeBins.clear();
317:
318: if (canvasDirty != 0) {
319: Canvas3D canvases[] = renderBin.view.getCanvases();
320:
321: for (i = 0; i < canvases.length; i++) {
322: canvases[i].canvasDirty |= canvasDirty;
323: }
324:
325: if ((canvasDirty & Canvas3D.AMBIENTLIGHT_DIRTY) != 0) {
326: updateSceneAmbient();
327: }
328:
329: if ((canvasDirty & Canvas3D.LIGHTENABLES_DIRTY) != 0) {
330: enableMask = enableMaskCache;
331: }
332:
333: if ((canvasDirty & Canvas3D.MODELCLIP_DIRTY) != 0) {
334: enableMCMask = enableMCMaskCache;
335: }
336:
337: canvasDirty = 0;
338: }
339: onUpdateList = false;
340: }
341:
342: /**
343: * Adds the given AttributeBin to this EnvironmentSet.
344: */
345: void addAttributeBin(AttributeBin a, RenderBin rb) {
346: a.environmentSet = this ;
347: addAttributeBins.add(a);
348: if (!onUpdateList) {
349: rb.objUpdateList.add(this );
350: onUpdateList = true;
351: }
352: }
353:
354: /**
355: * Removes the given AttributeBin from this EnvironmentSet.
356: */
357: void removeAttributeBin(AttributeBin a) {
358: LightRetained light;
359: int i;
360:
361: a.environmentSet = null;
362: // If the attributeBin being remove is contained in addAttributeBins, then
363: // remove the attributeBin from the addList
364: if (addAttributeBins.contains(a)) {
365: addAttributeBins.remove(addAttributeBins.indexOf(a));
366: } else {
367: if (a.prev == null) { // At the head of the list
368: attributeBinList = a.next;
369: if (a.next != null) {
370: a.next.prev = null;
371: }
372: } else { // In the middle or at the end.
373: a.prev.next = a.next;
374: if (a.next != null) {
375: a.next.prev = a.prev;
376: }
377: }
378: }
379: a.prev = null;
380: a.next = null;
381:
382: if (a.definingRenderingAttributes != null
383: && (a.definingRenderingAttributes.changedFrequent != 0))
384: a.definingRenderingAttributes = null;
385: a.onUpdateList &= ~AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST;
386:
387: if (attributeBinList == null && addAttributeBins.size() == 0) {
388: // Now remove this environment set from all the lights and fogs
389: // that use this
390: int sz = lights.size();
391: for (i = 0; i < sz; i++) {
392: ((LightRetained) lights.get(i)).environmentSets
393: .remove(this );
394: }
395: sz = ambLights.size();
396: for (i = 0; i < sz; i++) {
397: ((LightRetained) ambLights.get(i)).environmentSets
398: .remove(this );
399: }
400: if (fog != null) {
401: fog.environmentSets.remove(this );
402: }
403: lightBin.removeEnvironmentSet(this );
404: }
405: }
406:
407: void updateSceneAmbient() {
408: int i;
409: sceneAmbient.x = 0.0f;
410: sceneAmbient.y = 0.0f;
411: sceneAmbient.z = 0.0f;
412: for (i = 0; i < ambLights.size(); i++) {
413: LightRetained aL = (LightRetained) ambLights.get(i);
414: if (aL.lightOn) {
415: sceneAmbient.x += aL.color.x;
416: sceneAmbient.y += aL.color.y;
417: sceneAmbient.z += aL.color.z;
418: }
419: }
420: if (sceneAmbient.x > 1.0f) {
421: sceneAmbient.x = 1.0f;
422: }
423: if (sceneAmbient.y > 1.0f) {
424: sceneAmbient.y = 1.0f;
425: }
426: if (sceneAmbient.z > 1.0f) {
427: sceneAmbient.z = 1.0f;
428: }
429: }
430:
431: /**
432: * Renders this EnvironmentSet
433: */
434: void render(Canvas3D cv) {
435: AttributeBin a;
436:
437: // include this EnvironmentSet to the to-be-updated list in Canvas
438: cv.setStateToUpdate(Canvas3D.ENVIRONMENTSET_BIT, this );
439:
440: a = attributeBinList;
441: while (a != null) {
442: a.render(cv);
443: a = a.next;
444: }
445: }
446:
447: void updateAttributes(Canvas3D cv) {
448: LightRetained light;
449: int i, numLights;
450: float red, green, blue;
451: double scale;
452: boolean updateSceneAmbient = false, updateLightEnables = false;
453: boolean updateModelClip = false, updateFog = false;
454: // within frame
455: if (cv.environmentSet != this ) {
456: if (cv.enableMask != enableMask) {
457: updateLightEnables = true;
458: }
459:
460: if (cv.sceneAmbient.x != sceneAmbient.x
461: || cv.sceneAmbient.y != sceneAmbient.y
462: || cv.sceneAmbient.z != sceneAmbient.z) {
463: updateSceneAmbient = true;
464: }
465:
466: if (cv.fog != fog) {
467: updateFog = true;
468: }
469:
470: if (cv.modelClip != modelClip) {
471: updateModelClip = true;
472: }
473: }
474:
475: // Check for dirtybit.
476: if ((cv.canvasDirty & (Canvas3D.LIGHTENABLES_DIRTY
477: | Canvas3D.AMBIENTLIGHT_DIRTY | Canvas3D.FOG_DIRTY
478: | Canvas3D.MODELCLIP_DIRTY | Canvas3D.VIEW_MATRIX_DIRTY)) != 0) {
479:
480: if ((cv.canvasDirty & Canvas3D.LIGHTENABLES_DIRTY) != 0) {
481: updateLightEnables = true;
482: }
483:
484: if ((cv.canvasDirty & Canvas3D.AMBIENTLIGHT_DIRTY) != 0) {
485: updateSceneAmbient = true;
486: }
487:
488: if ((cv.canvasDirty & Canvas3D.FOG_DIRTY) != 0) {
489: updateFog = true;
490: }
491:
492: if ((cv.canvasDirty & Canvas3D.MODELCLIP_DIRTY) != 0) {
493: updateModelClip = true;
494: }
495:
496: if ((cv.canvasDirty & Canvas3D.VIEW_MATRIX_DIRTY) != 0) {
497: updateFog = true;
498: updateModelClip = true;
499: }
500: }
501:
502: // do states update here.
503: if (updateLightEnables) {
504: cv.setLightEnables(cv.ctx, enableMask, renderBin.maxLights);
505: cv.enableMask = enableMask;
506: }
507:
508: if (updateSceneAmbient) {
509: cv.setSceneAmbient(cv.ctx, sceneAmbient.x, sceneAmbient.y,
510: sceneAmbient.z);
511: cv.sceneAmbient.set(sceneAmbient);
512: }
513:
514: if (updateFog) {
515: if (fog != null) {
516: scale = lightBin.geometryBackground == null ? cv.canvasViewCache
517: .getVworldToCoexistenceScale()
518: : cv.canvasViewCache
519: .getInfVworldToCoexistenceScale();
520: fog.update(cv.ctx, scale);
521: } else {
522: cv.disableFog(cv.ctx);
523: }
524: cv.fog = fog;
525: }
526:
527: if (updateModelClip) {
528: if (modelClip != null) {
529: modelClip.update(cv, enableMCMask);
530: } else {
531: cv.disableModelClip(cv.ctx);
532: }
533: cv.modelClip = modelClip;
534: }
535:
536: cv.canvasDirty &= ~(Canvas3D.LIGHTENABLES_DIRTY
537: | Canvas3D.AMBIENTLIGHT_DIRTY | Canvas3D.FOG_DIRTY
538: | Canvas3D.MODELCLIP_DIRTY | Canvas3D.VIEW_MATRIX_DIRTY);
539:
540: cv.environmentSet = this;
541:
542: }
543: }
|