diff options
Diffstat (limited to 'src/classes/share')
202 files changed, 21444 insertions, 5686 deletions
diff --git a/src/classes/share/javax/media/j3d/AlternateAppearance.java b/src/classes/share/javax/media/j3d/AlternateAppearance.java index e6d160c..fccc203 100644 --- a/src/classes/share/javax/media/j3d/AlternateAppearance.java +++ b/src/classes/share/javax/media/j3d/AlternateAppearance.java @@ -92,7 +92,13 @@ public class AlternateAppearance extends Leaf { public static final int ALLOW_SCOPE_WRITE = CapabilityBits.ALTERNATE_APPEARANCE_ALLOW_SCOPE_WRITE; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_INFLUENCING_BOUNDS_READ, + ALLOW_APPEARANCE_READ, + ALLOW_SCOPE_READ + }; + /** * Constructs an AlternateAppearance node with default * parameters. The default values are as follows: @@ -106,28 +112,30 @@ public class AlternateAppearance extends Leaf { */ public AlternateAppearance() { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } - - /** - * Creates the retained mode AlternateAppearanceRetained object that this - * Alternate Appearance component object will point to. - */ - void createRetained() { - this.retained = new AlternateAppearanceRetained(); - this.retained.setSource(this); - } - - /** * Constructs an AlternateAppearance node with the specified appearance. * @param appearance the appearance that is used for those nodes affected * by this AlternateAppearance node. */ public AlternateAppearance(Appearance appearance) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); ((AlternateAppearanceRetained)retained).initAppearance(appearance); } + /** + * Creates the retained mode AlternateAppearanceRetained object that this + * Alternate Appearance component object will point to. + */ + void createRetained() { + this.retained = new AlternateAppearanceRetained(); + this.retained.setSource(this); + } /** * Sets the appearance of this AlternateAppearance node. diff --git a/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java b/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java index 0b88951..b7d17bf 100644 --- a/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java +++ b/src/classes/share/javax/media/j3d/AlternateAppearanceRetained.java @@ -803,7 +803,7 @@ class AlternateAppearanceRetained extends LeafRetained { // AlternateAppearance alternate appearance = (AlternateAppearance) originalNode; -// // TODO: clone appearance +// // XXXX: clone appearance // setInfluencingBounds(alternate appearance.getInfluencingBounds()); diff --git a/src/classes/share/javax/media/j3d/Appearance.java b/src/classes/share/javax/media/j3d/Appearance.java index cb24eba..88aea7b 100644 --- a/src/classes/share/javax/media/j3d/Appearance.java +++ b/src/classes/share/javax/media/j3d/Appearance.java @@ -285,7 +285,21 @@ public class Appearance extends NodeComponent { public static final int ALLOW_TEXTURE_UNIT_STATE_WRITE = CapabilityBits.APPEARANCE_ALLOW_TEXTURE_UNIT_STATE_WRITE; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_COLORING_ATTRIBUTES_READ, + ALLOW_LINE_ATTRIBUTES_READ, + ALLOW_MATERIAL_READ, + ALLOW_POINT_ATTRIBUTES_READ, + ALLOW_POLYGON_ATTRIBUTES_READ, + ALLOW_RENDERING_ATTRIBUTES_READ, + ALLOW_TEXGEN_READ, + ALLOW_TEXTURE_ATTRIBUTES_READ, + ALLOW_TEXTURE_READ, + ALLOW_TEXTURE_UNIT_STATE_READ, + ALLOW_TRANSPARENCY_ATTRIBUTES_READ + }; + /** * Constructs an Appearance component object using defaults for all * state variables. All component object references are initialized @@ -293,6 +307,8 @@ public class Appearance extends NodeComponent { */ public Appearance() { // Just use default values + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -919,7 +935,7 @@ public class Appearance extends NodeComponent { if ((nc != null) && nc.getDuplicateOnCloneTree()) return true; - // TODO: TextureUnitState + // XXXX: TextureUnitState return false; } diff --git a/src/classes/share/javax/media/j3d/AppearanceRetained.java b/src/classes/share/javax/media/j3d/AppearanceRetained.java index cc0489e..215c8eb 100644 --- a/src/classes/share/javax/media/j3d/AppearanceRetained.java +++ b/src/classes/share/javax/media/j3d/AppearanceRetained.java @@ -83,9 +83,6 @@ class AppearanceRetained extends NodeComponentRetained { static final int POINT = 0x0200; static final int TEXTURE_UNIT_STATE = 0x0400; - static final int ALL_COMPONENTS = (MATERIAL|TEXTURE|TEXCOORD_GEN|TEXTURE_ATTR|COLOR|TRANSPARENCY| - RENDERING|POLYGON|LINE|POINT|TEXTURE_UNIT_STATE); - static final int ALL_SOLE_USERS = 0; // A pointer to the scene graph appearance object @@ -876,11 +873,18 @@ class AppearanceRetained extends NodeComponentRetained { } + void setLive(boolean backgroundGroup, int refCount) { + // System.out.println("AppearceRetained.setLive()"); + doSetLive(backgroundGroup, refCount); + markAsLive(); + } + /** - * This setLive routine first calls the superclass's method, then - * it adds itself to the list of lights + * This method calls the setLive method of all appearance bundle + * objects. */ - void setLive(boolean backgroundGroup, int refCount) { + void doSetLive(boolean backgroundGroup, int refCount) { + // System.out.println("AppearceRetained.doSetLive()"); if (material != null) { @@ -938,12 +942,11 @@ class AppearanceRetained extends NodeComponentRetained { // Increment the reference count and initialize the appearance // mirror object super.doSetLive(backgroundGroup, refCount); - super.markAsLive(); } /** - * This clearLive routine first calls the superclass's method, then - * it removes itself to the list of lights + * This method calls the clearLive method of all appearance bundle + * objects. */ void clearLive(int refCount) { super.clearLive(refCount); diff --git a/src/classes/share/javax/media/j3d/AttributeBin.java b/src/classes/share/javax/media/j3d/AttributeBin.java index 8e98708..cc1afd4 100644 --- a/src/classes/share/javax/media/j3d/AttributeBin.java +++ b/src/classes/share/javax/media/j3d/AttributeBin.java @@ -28,6 +28,11 @@ class AttributeBin extends Object implements ObjectUpdate { RenderingAttributesRetained definingRenderingAttributes = null; /** + * The RenderBin for this object + */ + RenderBin renderBin = null; + + /** * The EnvirionmentSet that this AttributeBin resides */ EnvironmentSet environmentSet = null; @@ -40,21 +45,14 @@ class AttributeBin extends Object implements ObjectUpdate { AttributeBin prev = null; /** - * The list of TextureBins in this AttributeBin + * The list of ShaderBins in this AttributeBin */ - TextureBin textureBinList = null; - + ShaderBin shaderBinList = null; /** - * The list of TextureBins to be added for the next frame + * List of shaderBins to be added next frame */ - ArrayList addTextureBins = new ArrayList(); - - /** - * List of TextureBins to be added next frame - */ - ArrayList addTBs = new ArrayList(); - + ArrayList addShaderBins = new ArrayList(); /** * If the RenderingAttribute component of the appearance will be changed @@ -63,11 +61,6 @@ class AttributeBin extends Object implements ObjectUpdate { boolean soleUser = false; AppearanceRetained app = null; - /** - * List of TextureBins to be removeded next frame - */ - ArrayList removeTBs = new ArrayList(); - int onUpdateList = 0; static int ON_OBJ_UPDATE_LIST = 0x1; static int ON_CHANGED_FREQUENT_UPDATE_LIST = 0x2; @@ -76,44 +69,45 @@ class AttributeBin extends Object implements ObjectUpdate { // for whether the definingRendering attrs is non-null; boolean ignoreVertexColors = false; - // TODO: use definingMaterial etc. instead of these + // XXXX: use definingMaterial etc. instead of these // when sole user is completely implement RenderingAttributesRetained renderingAttrs; - int numEditingTextureBins = 0; - - + int numEditingShaderBins = 0; AttributeBin(AppearanceRetained app, RenderingAttributesRetained renderingAttributes, RenderBin rBin) { + reset(app, renderingAttributes, rBin); } void reset(AppearanceRetained app, RenderingAttributesRetained renderingAttributes, RenderBin rBin) { prev = null; next = null; - textureBinList = null; + shaderBinList = null; onUpdateList = 0; - numEditingTextureBins = 0; + numEditingShaderBins = 0; renderingAttrs = renderingAttributes; + renderBin = rBin; + if (app != null) { soleUser = ((app.changedFrequent & AppearanceRetained.RENDERING) != 0); } else { soleUser = false; } - // System.out.println("soleUser = "+soleUser+" renderingAttributes ="+renderingAttributes); + //System.out.println("soleUser = "+soleUser+" renderingAttributes ="+renderingAttributes); // Set the appearance only for soleUser case if (soleUser) this.app = app; else app = null; - + if (renderingAttributes != null) { if (renderingAttributes.changedFrequent != 0) { definingRenderingAttributes = renderingAttributes; if ((onUpdateList & ON_CHANGED_FREQUENT_UPDATE_LIST) == 0 ) { - rBin.aBinUpdateList.add(this); + renderBin.aBinUpdateList.add(this); onUpdateList |= AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST; } } @@ -140,10 +134,9 @@ class AttributeBin extends Object implements ObjectUpdate { // If the any reference to the appearance components that is cached renderMolecule // can change frequently, make a separate bin - // If the any reference to the appearance components that is cached renderMolecule - // can change frequently, make a separate bin if (soleUser || (ra.geometryAtom.source.appearance != null && - ((ra.geometryAtom.source.appearance.changedFrequent & AppearanceRetained.RENDERING) != 0))) { + ((ra.geometryAtom.source.appearance.changedFrequent & + AppearanceRetained.RENDERING) != 0))) { if (app == (Object)ra.geometryAtom.source.appearance) { // if this AttributeBin is currently on a zombie state, @@ -156,9 +149,9 @@ class AttributeBin extends Object implements ObjectUpdate { // attributes reference change would not have reflected to // the AttributeBin - if (numEditingTextureBins == 0) { + if (numEditingShaderBins == 0) { if ((onUpdateList & ON_CHANGED_FREQUENT_UPDATE_LIST) == 0) { - environmentSet.renderBin.aBinUpdateList.add(this); + renderBin.aBinUpdateList.add(this); onUpdateList |= AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST; } @@ -180,7 +173,7 @@ class AttributeBin extends Object implements ObjectUpdate { if (definingRenderingAttributes == renderingAttributes) { if (definingRenderingAttributes.compChanged != 0) { if ((onUpdateList & ON_CHANGED_FREQUENT_UPDATE_LIST) == 0 ) { - environmentSet.renderBin.aBinUpdateList.add(this); + renderBin.aBinUpdateList.add(this); onUpdateList |= AttributeBin.ON_CHANGED_FREQUENT_UPDATE_LIST; } } @@ -196,127 +189,56 @@ class AttributeBin extends Object implements ObjectUpdate { return false; } - - return (true); } - public void updateObject() { + ShaderBin sb; TextureBin t; - int i; + int i, size; - if (addTBs.size() > 0) { - t = (TextureBin)addTBs.get(0); - if (textureBinList == null) { - textureBinList = t; - + size = addShaderBins.size(); + if (size > 0) { + sb = (ShaderBin)addShaderBins.get(0); + if (shaderBinList == null) { + shaderBinList = sb; } else { - // Look for a TextureBin that has the same texture - insertTextureBin(t); - } - for (i = 1; i < addTBs.size() ; i++) { - t = (TextureBin)addTBs.get(i); - // Look for a TextureBin that has the same texture - insertTextureBin(t); - + sb.next = shaderBinList; + shaderBinList.prev = sb; + shaderBinList = sb; } - } - addTBs.clear(); - onUpdateList &= ~ON_OBJ_UPDATE_LIST; - } - - void insertTextureBin(TextureBin t) { - TextureBin tb; - int i; - TextureRetained texture = null; - - if (t.texUnitState != null && t.texUnitState.length > 0) { - if (t.texUnitState[0] != null) { - texture = t.texUnitState[0].texture; + + for (i = 1; i < size ; i++) { + sb = (ShaderBin)addShaderBins.get(i); + sb.next = shaderBinList; + shaderBinList.prev = sb; + shaderBinList = sb; } } - - // use the texture in the first texture unit as the sorting criteria - if (texture != null) { - tb = textureBinList; - while (tb != null) { - if (tb.texUnitState == null || tb.texUnitState[0] == null || - tb.texUnitState[0].texture != texture) { - tb = tb.next; - } else { - // put it here - t.next = tb; - t.prev = tb.prev; - if (tb.prev == null) { - textureBinList = t; - } - else { - tb.prev.next = t; - } - tb.prev = t; - return; - } - } - } - // Just put it up front - t.prev = null; - t.next = textureBinList; - textureBinList.prev = t; - textureBinList = t; - - t.tbFlag &= ~TextureBin.RESORT; + addShaderBins.clear(); + onUpdateList &= ~ON_OBJ_UPDATE_LIST; } /** - * reInsert textureBin if the first texture is different from - * the previous bin and different from the next bin + * Adds the given shaderBin to this AttributeBin. */ - void reInsertTextureBin(TextureBin tb) { - - TextureRetained texture = null, - prevTexture = null, - nextTexture = null; - - if (tb.texUnitState != null && tb.texUnitState[0] != null) { - texture = tb.texUnitState[0].texture; - } - - if (tb.prev != null && tb.prev.texUnitState != null) { - prevTexture = tb.prev.texUnitState[0].texture; - } - - if (texture != prevTexture) { - if (tb.next != null && tb.next.texUnitState != null) { - nextTexture = tb.next.texUnitState[0].texture; - } - if (texture != nextTexture) { - if (tb.prev != null && tb.next != null) { - tb.prev.next = tb.next; - tb.next.prev = tb.prev; - insertTextureBin(tb); - } - } - } - } + void addShaderBin(ShaderBin sb, RenderBin rb, ShaderAppearanceRetained sApp) { + sb.attributeBin = this; - /** - * Adds the given TextureBin to this AttributeBin. - */ - void addTextureBin(TextureBin t, RenderBin rb, RenderAtom ra) { - int i; - t.attributeBin = this; - AppearanceRetained raApp = ra.geometryAtom.source.appearance; - RenderingAttributesRetained rAttrs = - (raApp == null)? null : raApp.renderingAttributes; - if (!soleUser && renderingAttrs != rAttrs) { - // no longer sole user - renderingAttrs = definingRenderingAttributes; + if(sApp != null) { + // ShaderBin should reference to the mirror components. -- JADA. + // System.out.println("AttributeBin : sApp.isMirror = " + sApp.isMirror); + assert(sApp.isMirror); + sb.shaderProgram = sApp.shaderProgram; + sb.shaderAttributeSet = sApp.shaderAttributeSet; } - addTBs.add(t); + sb.shaderAppearance = sApp; + + // TODO : JADA - sort by ShaderProgram to avoid state trashing. + addShaderBins.add(sb); if ((onUpdateList & ON_OBJ_UPDATE_LIST) == 0) { onUpdateList |= ON_OBJ_UPDATE_LIST; rb.objUpdateList.add(this); @@ -324,41 +246,35 @@ class AttributeBin extends Object implements ObjectUpdate { } + /** - * Removes the given TextureBin from this AttributeBin. + * Removes the given shaderBin from this AttributeBin. */ - void removeTextureBin(TextureBin t) { - - int i; - TextureRetained tex; + void removeShaderBin(ShaderBin sb) { - t.attributeBin = null; - // If the TextureBin being remove is contained in addTBs, then - // remove the TextureBin from the addList - if (addTBs.contains(t)) { - addTBs.remove(addTBs.indexOf(t)); + // If the shaderBin being remove is contained in addShaderBins, + // then remove the shadereBin from the addList + if (addShaderBins.contains(sb)) { + addShaderBins.remove(addShaderBins.indexOf(sb)); } else { - if (t.prev == null) { // At the head of the list - textureBinList = t.next; - if (t.next != null) { - t.next.prev = null; + if (sb.prev == null) { // At the head of the list + shaderBinList = sb.next; + if (sb.next != null) { + sb.next.prev = null; } } else { // In the middle or at the end. - t.prev.next = t.next; - if (t.next != null) { - t.next.prev = t.prev; + sb.prev.next = sb.next; + if (sb.next != null) { + sb.next.prev = sb.prev; } } } - t.prev = null; - t.next = null; - t.clear(); + sb.clear(); + renderBin.shaderBinFreelist.add(sb); - environmentSet.renderBin.textureBinFreelist.add(t); - - if (textureBinList == null && addTBs.size() == 0 ) { + if (shaderBinList == null && addShaderBins.size() == 0 ) { // Note: Removal of this attributebin as a user of the rendering // atttrs is done during removeRenderAtom() in RenderMolecule.java environmentSet.removeAttributeBin(this); @@ -370,14 +286,14 @@ class AttributeBin extends Object implements ObjectUpdate { */ void render(Canvas3D cv) { - TextureBin t; + ShaderBin sb; boolean visible = (definingRenderingAttributes == null || definingRenderingAttributes.visible); - if ( (environmentSet.renderBin.view.viewCache.visibilityPolicy + if ( (renderBin.view.viewCache.visibilityPolicy == View.VISIBILITY_DRAW_VISIBLE && !visible) || - (environmentSet.renderBin.view.viewCache.visibilityPolicy + (renderBin.view.viewCache.visibilityPolicy == View.VISIBILITY_DRAW_INVISIBLE && visible)) { return; } @@ -386,15 +302,16 @@ class AttributeBin extends Object implements ObjectUpdate { // include this AttributeBin to the to-be-updated list in Canvas cv.setStateToUpdate(Canvas3D.ATTRIBUTEBIN_BIT, this); - t = textureBinList; - while (t != null) { - t.render(cv); - t = t.next; + sb = shaderBinList; + while (sb != null) { + sb.render(cv); + sb = sb.next; } } void updateAttributes(Canvas3D cv) { + if ((cv.canvasDirty & Canvas3D.ATTRIBUTEBIN_DIRTY) != 0) { // Update Attribute Bundles if (definingRenderingAttributes == null) { @@ -403,7 +320,7 @@ class AttributeBin extends Object implements ObjectUpdate { cv.depthBufferEnableOverride); } else { definingRenderingAttributes.updateNative( - cv.ctx, + cv, cv.depthBufferWriteEnableOverride, cv.depthBufferEnableOverride); } @@ -420,7 +337,7 @@ class AttributeBin extends Object implements ObjectUpdate { cv.depthBufferEnableOverride); } else { definingRenderingAttributes.updateNative( - cv.ctx, + cv, cv.depthBufferWriteEnableOverride, cv.depthBufferEnableOverride); } @@ -465,11 +382,23 @@ class AttributeBin extends Object implements ObjectUpdate { onUpdateList &= ~ON_CHANGED_FREQUENT_UPDATE_LIST; } - void incrActiveTextureBin() { - numEditingTextureBins++; + void incrActiveShaderBin() { + numEditingShaderBins++; } - void decrActiveTextureBin() { - numEditingTextureBins--; + void decrActiveShaderBin() { + numEditingShaderBins--; + } + + void updateFromShaderBin(RenderAtom ra) { + + AppearanceRetained raApp = ra.geometryAtom.source.appearance; + RenderingAttributesRetained rAttrs = + (raApp == null)? null : raApp.renderingAttributes; + + if (!soleUser && renderingAttrs != rAttrs) { + // no longer sole user + renderingAttrs = definingRenderingAttributes; + } } } diff --git a/src/classes/share/javax/media/j3d/AuralAttributes.java b/src/classes/share/javax/media/j3d/AuralAttributes.java index 89384e6..289383f 100644 --- a/src/classes/share/javax/media/j3d/AuralAttributes.java +++ b/src/classes/share/javax/media/j3d/AuralAttributes.java @@ -473,6 +473,24 @@ public class AuralAttributes extends NodeComponent { public static final int ALLOW_VELOCITY_SCALE_FACTOR_WRITE = CapabilityBits.AURAL_ATTRIBUTES_ALLOW_VELOCITY_SCALE_FACTOR_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_ATTRIBUTE_GAIN_READ, + ALLOW_DECAY_FILTER_READ, + ALLOW_DECAY_TIME_READ, + ALLOW_DENSITY_READ, + ALLOW_DIFFUSION_READ, + ALLOW_DISTANCE_FILTER_READ, + ALLOW_FREQUENCY_SCALE_FACTOR_READ, + ALLOW_REFLECTION_COEFFICIENT_READ, + ALLOW_REFLECTION_DELAY_READ, + ALLOW_REVERB_COEFFICIENT_READ, + ALLOW_REVERB_DELAY_READ, + ALLOW_REVERB_ORDER_READ, + ALLOW_ROLLOFF_READ, + ALLOW_VELOCITY_SCALE_FACTOR_READ + }; + /** ***************** * * Constructors @@ -501,6 +519,8 @@ public class AuralAttributes extends NodeComponent { */ public AuralAttributes() { // Just use default values + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -523,6 +543,9 @@ public class AuralAttributes extends NodeComponent { Point2f[] distanceFilter, float frequencyScaleFactor, float velocityScaleFactor) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((AuralAttributesRetained)this.retained).setAttributeGain(gain); ((AuralAttributesRetained)this.retained).setRolloff(rolloff); ((AuralAttributesRetained)this.retained).setReflectionCoefficient( @@ -558,6 +581,9 @@ public class AuralAttributes extends NodeComponent { float[] frequencyCutoff, float frequencyScaleFactor, float velocityScaleFactor) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((AuralAttributesRetained)this.retained).setAttributeGain(gain); ((AuralAttributesRetained)this.retained).setRolloff(rolloff); ((AuralAttributesRetained)this.retained).setReflectionCoefficient( @@ -606,6 +632,9 @@ public class AuralAttributes extends NodeComponent { float[] frequencyCutoff, float frequencyScaleFactor, float velocityScaleFactor) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((AuralAttributesRetained)this.retained).setAttributeGain(gain); ((AuralAttributesRetained)this.retained).setRolloff(rolloff); ((AuralAttributesRetained)this.retained).setReflectionCoefficient( diff --git a/src/classes/share/javax/media/j3d/AuralAttributesRetained.java b/src/classes/share/javax/media/j3d/AuralAttributesRetained.java index 3b23c51..eb88987 100644 --- a/src/classes/share/javax/media/j3d/AuralAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/AuralAttributesRetained.java @@ -642,7 +642,7 @@ class AuralAttributesRetained extends NodeComponentRetained { else if (debugFlag) debugPrint("reset aa; aa.frequencyCutoff = null"); - // TODO: (Enhancement) Why are these dirtyFlag cleared rather than aa->this + // XXXX: (Enhancement) Why are these dirtyFlag cleared rather than aa->this this.aaDirty = false; aa.aaDirty = false; } diff --git a/src/classes/share/javax/media/j3d/Background.java b/src/classes/share/javax/media/j3d/Background.java index f50a9b3..c9a2bdd 100644 --- a/src/classes/share/javax/media/j3d/Background.java +++ b/src/classes/share/javax/media/j3d/Background.java @@ -228,6 +228,16 @@ public class Background extends Leaf { */ public static final int SCALE_NONE_CENTER = 5; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_APPLICATION_BOUNDS_READ, + ALLOW_COLOR_READ, + ALLOW_GEOMETRY_READ, + ALLOW_IMAGE_READ, + ALLOW_IMAGE_SCALE_MODE_READ + }; + + /** * Constructs a Background node with default parameters. The default * values are as follows: @@ -242,6 +252,8 @@ public class Background extends Leaf { */ public Background () { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -250,7 +262,10 @@ public class Background extends Leaf { * objects in the scene. */ public Background(Color3f color) { - ((BackgroundRetained)this.retained).setColor(color); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((BackgroundRetained)this.retained).setColor(color); } /** @@ -259,7 +274,10 @@ public class Background extends Leaf { * objects in the scene. */ public Background(float r, float g, float b) { - ((BackgroundRetained)this.retained).setColor(r, g, b); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((BackgroundRetained)this.retained).setColor(r, g, b); } /** @@ -273,7 +291,10 @@ public class Background extends Leaf { * @param image pixel array object used as the background image */ public Background(ImageComponent2D image) { - ((BackgroundRetained)this.retained).setImage(image); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((BackgroundRetained)this.retained).setImage(image); } /** @@ -290,7 +311,10 @@ public class Background extends Leaf { * contains an illegal node. */ public Background(BranchGroup branch) { - ((BackgroundRetained)this.retained).setGeometry(branch); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((BackgroundRetained)this.retained).setGeometry(branch); } /** diff --git a/src/classes/share/javax/media/j3d/BehaviorStructure.java b/src/classes/share/javax/media/j3d/BehaviorStructure.java index a8e9389..24a56c2 100644 --- a/src/classes/share/javax/media/j3d/BehaviorStructure.java +++ b/src/classes/share/javax/media/j3d/BehaviorStructure.java @@ -667,7 +667,7 @@ class BehaviorStructure extends J3dStructure { if (awtCond.AwtId != 0) { if (awtCond.AwtId == id) { - // TODO: how do we clone this event (do we need to?) + // XXXX: how do we clone this event (do we need to?) // Bug: 4181321 awtCond.addAWTEvent(evt); } diff --git a/src/classes/share/javax/media/j3d/BoundingBox.java b/src/classes/share/javax/media/j3d/BoundingBox.java index 7e4e88a..3bd5e15 100644 --- a/src/classes/share/javax/media/j3d/BoundingBox.java +++ b/src/classes/share/javax/media/j3d/BoundingBox.java @@ -215,7 +215,7 @@ public class BoundingBox extends Bounds { else if(bounds[i].boundId == BOUNDING_POLYTOPE) { BoundingPolytope polytope = (BoundingPolytope)bounds[i]; - for(i=0;i<polytope.nVerts;i++) { // TODO handle polytope with no verts + for(i=0;i<polytope.nVerts;i++) { // XXXX: handle polytope with no verts if( polytope.verts[i].x < lower.x ) lower.x = polytope.verts[i].x; if( polytope.verts[i].y < lower.y ) diff --git a/src/classes/share/javax/media/j3d/BoundingLeaf.java b/src/classes/share/javax/media/j3d/BoundingLeaf.java index 9015202..80c35a1 100644 --- a/src/classes/share/javax/media/j3d/BoundingLeaf.java +++ b/src/classes/share/javax/media/j3d/BoundingLeaf.java @@ -50,10 +50,18 @@ public class BoundingLeaf extends Leaf { public static final int ALLOW_REGION_WRITE = CapabilityBits.BOUNDING_LEAF_ALLOW_REGION_WRITE; - /** + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_REGION_READ + }; + + /** * Constructs a BoundingLeaf node with a null (empty) bounding region. */ public BoundingLeaf() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((BoundingLeafRetained)this.retained).createBoundingLeaf(); } @@ -62,6 +70,9 @@ public class BoundingLeaf extends Leaf { * @param region the bounding region of this leaf node */ public BoundingLeaf(Bounds region) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((BoundingLeafRetained)this.retained).createBoundingLeaf(); ((BoundingLeafRetained)this.retained).initRegion(region); } diff --git a/src/classes/share/javax/media/j3d/BoundingPolytope.java b/src/classes/share/javax/media/j3d/BoundingPolytope.java index 491f85a..fbed7f3 100644 --- a/src/classes/share/javax/media/j3d/BoundingPolytope.java +++ b/src/classes/share/javax/media/j3d/BoundingPolytope.java @@ -76,7 +76,7 @@ public class BoundingPolytope extends Bounds { planes[i].z*invMag, planes[i].w*invMag ); } - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } /** @@ -111,7 +111,7 @@ public class BoundingPolytope extends Bounds { mag[4] = 1.0; mag[5] = 1.0; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } @@ -131,7 +131,7 @@ public class BoundingPolytope extends Bounds { boundsIsEmpty = true; boundsIsInfinite = false; initEmptyPolytope(); - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate return; } @@ -156,7 +156,7 @@ public class BoundingPolytope extends Bounds { mag[3] = 1.0; mag[4] = 1.0; mag[5] = 1.0; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } else if( boundsObject.boundId == BOUNDING_BOX ){ BoundingBox box = (BoundingBox)boundsObject; @@ -176,7 +176,7 @@ public class BoundingPolytope extends Bounds { mag[3] = 1.0; mag[4] = 1.0; mag[5] = 1.0; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } else if( boundsObject.boundId == BOUNDING_POLYTOPE ) { BoundingPolytope polytope = (BoundingPolytope)boundsObject; @@ -215,7 +215,7 @@ public class BoundingPolytope extends Bounds { boundsIsEmpty = true; boundsIsInfinite = false; initEmptyPolytope(); - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate return; } // find first non empty bounds object @@ -227,7 +227,7 @@ public class BoundingPolytope extends Bounds { boundsIsEmpty = true; boundsIsInfinite = false; initEmptyPolytope(); - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate return; } @@ -253,7 +253,7 @@ public class BoundingPolytope extends Bounds { mag[4] = 1.0; mag[5] = 1.0; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } else if( boundsObjects[i].boundId == BOUNDING_BOX ){ BoundingBox box = (BoundingBox)boundsObjects[i]; planes = new Vector4d[6]; @@ -273,7 +273,7 @@ public class BoundingPolytope extends Bounds { mag[4] = 1.0; mag[5] = 1.0; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } else if( boundsObjects[i].boundId == BOUNDING_POLYTOPE ) { BoundingPolytope polytope = (BoundingPolytope)boundsObjects[i]; planes = new Vector4d[polytope.planes.length]; @@ -320,7 +320,7 @@ public class BoundingPolytope extends Bounds { if( planes.length <= 0 ) { boundsIsEmpty = true; boundsIsInfinite = false; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate return; } @@ -332,7 +332,7 @@ public class BoundingPolytope extends Bounds { this.planes[i] = new Vector4d( planes[i].x*invMag, planes[i].y*invMag, planes[i].z*invMag, planes[i].w*invMag ); } - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } @@ -373,7 +373,7 @@ public class BoundingPolytope extends Bounds { if( boundsObject == null ) { boundsIsEmpty = true; boundsIsInfinite = false; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate }else if( boundsObject.boundId == BOUNDING_SPHERE ) { BoundingSphere sphere = (BoundingSphere)boundsObject; @@ -391,7 +391,7 @@ public class BoundingPolytope extends Bounds { boundsIsEmpty = boundsObject.boundsIsEmpty; boundsIsInfinite = boundsObject.boundsIsInfinite; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } else if( boundsObject.boundId == BOUNDING_BOX){ BoundingBox box = (BoundingBox)boundsObject; @@ -422,7 +422,7 @@ public class BoundingPolytope extends Bounds { boundsIsEmpty = boundsObject.boundsIsEmpty; boundsIsInfinite = boundsObject.boundsIsInfinite; - computeAllVerts(); // TODO lazy evaluate + computeAllVerts(); // XXXX: lazy evaluate } else if(boundsObject.boundId == BOUNDING_POLYTOPE) { BoundingPolytope polytope = (BoundingPolytope)boundsObject; @@ -1627,7 +1627,7 @@ public class BoundingPolytope extends Bounds { } } } - // TODO correctly compute centroid + // XXXX: correctly compute centroid x=y=z=0.0; Point3d newVerts[] = new Point3d[nVerts]; diff --git a/src/classes/share/javax/media/j3d/BoundingSphere.java b/src/classes/share/javax/media/j3d/BoundingSphere.java index 79dd8fb..67b9d5c 100644 --- a/src/classes/share/javax/media/j3d/BoundingSphere.java +++ b/src/classes/share/javax/media/j3d/BoundingSphere.java @@ -1073,7 +1073,7 @@ public class BoundingSphere extends Bounds { Point3d dir = new Point3d(); // normalized direction of ray Point3d oc = new Point3d(); // vector from sphere center to ray origin - oc.x = center.x - origin.x; // TODO check if this method is still needed + oc.x = center.x - origin.x; // XXXX: check if this method is still needed oc.y = center.y - origin.y; oc.z = center.z - origin.z; diff --git a/src/classes/share/javax/media/j3d/BranchGroup.java b/src/classes/share/javax/media/j3d/BranchGroup.java index 92004fd..1c58feb 100644 --- a/src/classes/share/javax/media/j3d/BranchGroup.java +++ b/src/classes/share/javax/media/j3d/BranchGroup.java @@ -86,22 +86,63 @@ public class BranchGroup extends Group { * Detaches this BranchGroup from its parent. */ public void detach() { - Group parent; - - if (isLiveOrCompiled()) { - if(!this.getCapability(ALLOW_DETACH)) - throw new CapabilityNotSetException(J3dI18N.getString("BranchGroup1")); - - if (((BranchGroupRetained)this.retained).parent != null) { - parent = (Group)((BranchGroupRetained)this.retained).parent.source; - if(!parent.getCapability(Group.ALLOW_CHILDREN_WRITE)) - throw new CapabilityNotSetException(J3dI18N.getString("BranchGroup2")); - } - } + Group parent; + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_DETACH)) + throw new CapabilityNotSetException(J3dI18N.getString("BranchGroup1")); + + if (((BranchGroupRetained)this.retained).parent != null) { + parent = (Group)((BranchGroupRetained)this.retained).parent.source; + if(!parent.getCapability(Group.ALLOW_CHILDREN_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("BranchGroup2")); + } + } + + ((BranchGroupRetained)this.retained).detach(); + } + + + void validateModeFlagAndPickShape(int mode, int flags, PickShape pickShape) { - ((BranchGroupRetained)this.retained).detach(); - } + if(isLive()==false) { + throw new IllegalStateException(J3dI18N.getString("BranchGroup3")); + } + + if((mode != PickInfo.PICK_BOUNDS) && (mode != PickInfo.PICK_GEOMETRY)) { + + throw new IllegalArgumentException(J3dI18N.getString("BranchGroup4")); + } + + if((pickShape instanceof PickPoint) && (mode == PickInfo.PICK_GEOMETRY)) { + throw new IllegalArgumentException(J3dI18N.getString("BranchGroup5")); + } + + if(((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) && + ((flags & PickInfo.ALL_GEOM_INFO) != 0)) { + throw new IllegalArgumentException(J3dI18N.getString("BranchGroup6")); + } + + if((mode == PickInfo.PICK_BOUNDS) && + (((flags & (PickInfo.CLOSEST_GEOM_INFO | + PickInfo.ALL_GEOM_INFO | + PickInfo.CLOSEST_DISTANCE | + PickInfo.CLOSEST_INTERSECTION_POINT)) != 0))) { + + throw new IllegalArgumentException(J3dI18N.getString("BranchGroup7")); + } + + if((pickShape instanceof PickBounds) && + (((flags & (PickInfo.CLOSEST_GEOM_INFO | + PickInfo.ALL_GEOM_INFO | + PickInfo.CLOSEST_DISTANCE | + PickInfo.CLOSEST_INTERSECTION_POINT)) != 0))) { + + throw new IllegalArgumentException(J3dI18N.getString("BranchGroup8")); + } + } + /** * Returns an array referencing all the items that are pickable below this * <code>BranchGroup</code> that intersect with PickShape. @@ -116,12 +157,91 @@ public class BranchGroup extends Group { * */ public SceneGraphPath[] pickAll( PickShape pickShape ) { + if(isLive()==false) throw new IllegalStateException(J3dI18N.getString("BranchGroup3")); + + return ((BranchGroupRetained)this.retained).pickAll(pickShape); + + } - return Picking.pickAll( this, pickShape ); + /** + * Returns an array unsorted references to all the PickInfo objects that are + * pickable below this <code>BranchGroup</code> that intersect with PickShape. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if BranchGroup is not live. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see Locale#pickAll(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + + public PickInfo[] pickAll( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + return ((BranchGroupRetained)this.retained).pickAll(mode, flags, pickShape); + } + /** * Returns a sorted array of references to all the Pickable items that * intersect with the pickShape. Element [0] references the item closest @@ -139,10 +259,90 @@ public class BranchGroup extends Group { * */ public SceneGraphPath[] pickAllSorted( PickShape pickShape ) { + if(isLive()==false) - throw new IllegalStateException(J3dI18N.getString("BranchGroup3")); - - return Picking.pickAllSorted( this, pickShape ); + throw new IllegalStateException(J3dI18N.getString("BranchGroup3")); + + return ((BranchGroupRetained)this.retained).pickAllSorted(pickShape); + + } + + + /** + * Returns a sorted array of PickInfo references to all the pickable + * items that intersect with the pickShape. Element [0] references + * the item closest to <i>origin</i> of PickShape successive array + * elements are further from the <i>origin</i> + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if BranchGroup is not live. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see Locale#pickAllSorted(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo[] pickAllSorted( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + return ((BranchGroupRetained)this.retained).pickAllSorted(mode, flags, pickShape); + } /** @@ -160,17 +360,95 @@ public class BranchGroup extends Group { * */ public SceneGraphPath pickClosest( PickShape pickShape ) { + if(isLive()==false) throw new IllegalStateException(J3dI18N.getString("BranchGroup3")); - return Picking.pickClosest( this, pickShape ); + return ((BranchGroupRetained)this.retained).pickClosest(pickShape); + } + /** + * Returns a PickInfo which references the pickable item + * which is closest to the origin of <code>pickShape</code>. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if BranchGroup is not live. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see Locale#pickClosest(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo pickClosest( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + return ((BranchGroupRetained)this.retained).pickClosest(mode, flags, pickShape); + + } + + /** * Returns a reference to any item that is Pickable below this BranchGroup that * intersects with <code>pickShape</code>. - * * @param pickShape the PickShape object + * * @see SceneGraphPath * @see Locale#pickAny * @see PickShape @@ -178,12 +456,88 @@ public class BranchGroup extends Group { * */ public SceneGraphPath pickAny( PickShape pickShape ) { + if(isLive()==false) throw new IllegalStateException(J3dI18N.getString("BranchGroup3")); + + return ((BranchGroupRetained)this.retained).pickAny(pickShape); - return Picking.pickAny( this, pickShape ); } + /** + * Returns a PickInfo which references the pickable item below this + * BranchGroup that intersects with <code>pickShape</code>. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if BranchGroup is not live. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see Locale#pickAny(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo pickAny( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + return ((BranchGroupRetained)this.retained).pickAny(mode, flags, pickShape); + + } /** * Creates a new instance of the node. This routine is called @@ -200,8 +554,11 @@ public class BranchGroup extends Group { * @see NodeComponent#setDuplicateOnCloneTree */ public Node cloneNode(boolean forceDuplicate) { + BranchGroup bg = new BranchGroup(); bg.duplicateNode(this, forceDuplicate); return bg; + } + } diff --git a/src/classes/share/javax/media/j3d/BranchGroupRetained.java b/src/classes/share/javax/media/j3d/BranchGroupRetained.java index 5d1aa84..696ba49 100644 --- a/src/classes/share/javax/media/j3d/BranchGroupRetained.java +++ b/src/classes/share/javax/media/j3d/BranchGroupRetained.java @@ -58,11 +58,18 @@ class BranchGroupRetained extends GroupRetained { if (universe != null) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { - if (source.isLive()) { + boolean isLive = source.isLive(); + if (isLive) { notifySceneGraphChanged(true); } + GroupRetained oldParent = (GroupRetained)parent; do_detach(); universe.setLiveState.clear(); + if (isLive) + if (oldParent==null) + universe.notifyStructureChangeListeners(false,locale,(BranchGroup)this.source); + else + universe.notifyStructureChangeListeners(false,oldParent.source, (BranchGroup)this.source); } universe.waitForMC(); } else { // Not live yet, just do it. @@ -106,7 +113,7 @@ class BranchGroupRetained extends GroupRetained { setAuxData(s, j, hkIndex); } else { - // TODO: change this to an assertion exception + // XXXX: change this to an assertion exception System.out.println("Can't Find matching hashKey in setNodeData."); System.out.println("We're in TROUBLE!!!"); } @@ -206,4 +213,145 @@ class BranchGroupRetained extends GroupRetained { // without any capabilities set mergeFlag = SceneGraphObjectRetained.DONT_MERGE; } + + SceneGraphPath[] pickAll(PickShape pickShape) { + + PickInfo[] pickInfoArr = pickAll(PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfoArr == null) { + return null; + } + + SceneGraphPath[] sgpArr = new SceneGraphPath[pickInfoArr.length]; + for( int i=0; i<sgpArr.length; i++) { + sgpArr[i] = pickInfoArr[i].getSceneGraphPath(); + } + + return sgpArr; + } + + PickInfo[] pickAll( int mode, int flags, PickShape pickShape ) { + + if (inSharedGroup) { + throw new RestrictedAccessException(J3dI18N.getString("BranchGroup9")); + } + + GeometryAtom geomAtoms[] = + locale.universe.geometryStructure.pickAll(locale, pickShape); + + return PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ALL); + + } + + SceneGraphPath[] pickAllSorted(PickShape pickShape) { + + PickInfo[] pickInfoArr = pickAllSorted(PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfoArr == null) { + return null; + } + + SceneGraphPath[] sgpArr = new SceneGraphPath[pickInfoArr.length]; + for( int i=0; i<sgpArr.length; i++) { + sgpArr[i] = pickInfoArr[i].getSceneGraphPath(); + } + + return sgpArr; + + } + + PickInfo[] pickAllSorted( int mode, int flags, PickShape pickShape ) { + + if (inSharedGroup) { + throw new RestrictedAccessException(J3dI18N.getString("BranchGroup9")); + } + + GeometryAtom geomAtoms[] = + locale.universe.geometryStructure.pickAll(locale, pickShape); + + PickInfo[] pickInfoArr = null; + + + if ((geomAtoms == null) || (geomAtoms.length == 0)) { + return null; + } + + if (mode == PickInfo.PICK_GEOMETRY) { + // Need to have closestDistance set + flags |= PickInfo.CLOSEST_DISTANCE; + pickInfoArr= PickInfo.pick(this, geomAtoms, mode, flags, + pickShape, PickInfo.PICK_ALL); + if (pickInfoArr != null) { + PickInfo.sortPickInfoArray(pickInfoArr); + } + } + else { + PickInfo.sortGeomAtoms(geomAtoms, pickShape); + pickInfoArr= PickInfo.pick(this, geomAtoms, mode, flags, + pickShape, PickInfo.PICK_ALL); + } + + return pickInfoArr; + + } + + SceneGraphPath pickClosest( PickShape pickShape ) { + + PickInfo pickInfo = pickClosest( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfo == null) { + return null; + } + + return pickInfo.getSceneGraphPath(); + + } + + PickInfo pickClosest( int mode, int flags, PickShape pickShape ) { + + PickInfo[] pickInfoArr = null; + + pickInfoArr = pickAllSorted( mode, flags, pickShape ); + + if(pickInfoArr == null) { + return null; + } + + return pickInfoArr[0]; + + } + + SceneGraphPath pickAny( PickShape pickShape ) { + + PickInfo pickInfo = pickAny( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfo == null) { + return null; + } + return pickInfo.getSceneGraphPath(); + } + + PickInfo pickAny( int mode, int flags, PickShape pickShape ) { + + if (inSharedGroup) { + throw new RestrictedAccessException(J3dI18N.getString("BranchGroup9")); + } + + GeometryAtom geomAtoms[] = + locale.universe.geometryStructure.pickAll(locale, pickShape); + + PickInfo[] pickInfoArr = PickInfo.pick(this, geomAtoms, mode, + flags, pickShape, PickInfo.PICK_ANY); + + if(pickInfoArr == null) { + return null; + } + + return pickInfoArr[0]; + + } } diff --git a/src/classes/share/javax/media/j3d/Canvas3D.java b/src/classes/share/javax/media/j3d/Canvas3D.java index 597fbd3..6d887b9 100644 --- a/src/classes/share/javax/media/j3d/Canvas3D.java +++ b/src/classes/share/javax/media/j3d/Canvas3D.java @@ -300,6 +300,7 @@ public class Canvas3D extends Canvas { static final int FOG_DIRTY = 0x2000; static final int MODELCLIP_DIRTY = 0x4000; static final int VIEW_MATRIX_DIRTY = 0x8000; + // static final int SHADER_DIRTY = 0x10000; Not ready for this yet -- JADA // Use to notify D3D Canvas when window change static final int RESIZE = 1; @@ -373,6 +374,18 @@ public class Canvas3D extends Canvas { // int monoscopicViewPolicy = View.CYCLOPEAN_EYE_VIEW; + // User requested stencil size + int requestedStencilSize; + + // Actual stencil size return for this canvas + int actualStencilSize; + + // True if stencil buffer is available for user + boolean userStencilAvailable; + + // True if stencil buffer is available for system ( decal ) + boolean systemStencilAvailable; + // // Read-only flag that indicates whether double buffering is supported // for this canvas. This is always false for off-screen canvases. @@ -409,17 +422,11 @@ public class Canvas3D extends Canvas { // int textureColorTableSize; - - boolean multiTexAccelerated = false; - - // number of simultaneous Texture unit support for this canvas. - int numTexUnitSupported = 1; - - // number of texture coords unit support for multi-texture. - int numTexCoordSupported = 1; - // a mapping between underlying graphics library texture unit and // texture unit state in j3d + // + // TODO: This mapping is now required to be 1-to-1, and it should be + // removed entirely in Java 3D 1.5 int[] texUnitStateMap = null; // number of active/enabled texture unit @@ -428,6 +435,10 @@ public class Canvas3D extends Canvas { // index iof last enabled texture unit int lastActiveTexUnit = -1; + // True if shadingLanguage is supported, otherwise false. + boolean shadingLanguageGLSL = false; + boolean shadingLanguageCg = false; + // Query properties J3dQueryProps queryProps; @@ -454,7 +465,10 @@ public class Canvas3D extends Canvas { // View cache for this canvas and its associated view. // CanvasViewCache canvasViewCache = null; - + + // Issue 109: View cache for this canvas, for computing view frustum planes + CanvasViewCache canvasViewCacheFrustum = null; + // Since multiple renderAtomListInfo, share the same vecBounds // we want to do the intersection test only once per renderAtom // this flag is set to true after the first intersect and set to @@ -488,7 +502,14 @@ public class Canvas3D extends Canvas { BACKGROUND_DIRTY | BACKGROUND_IMAGE_DIRTY); - int cvDirtyMask = VIEW_INFO_DIRTY; + // Issue 163: Array of dirty bits is used because the Renderer and + // RenderBin run asynchronously. Now that they each have a separate + // instance of CanvasViewCache (due to the fix for Issue 109), they + // need separate dirty bits. Array element 0 is used for the Renderer and + // element 1 is used for the RenderBin. + static final int RENDERER_DIRTY_IDX = 0; + static final int RENDER_BIN_DIRTY_IDX = 1; + int[] cvDirtyMask = new int[2]; // This boolean informs the J3DGraphics2DImpl that the window is resized boolean resizeGraphics2D = true; @@ -574,7 +595,8 @@ public class Canvas3D extends Canvas { // PixelFormat structure ( see also gldef.h ) to allow value such // as offScreen's pixelformat, and ARB function pointers to be stored. long fbConfig = 0; - + GraphicsConfigInfo gcInfo = null; + // offScreenBufferInfo is a pointer to additional information about the // offScreenBuffer in this Canvas. // @@ -587,6 +609,7 @@ public class Canvas3D extends Canvas { // doesn't exist at the time getBestConfiguration() is called, and // X11GraphicsConfig neither maintains this pointer nor provides a public // constructor to allow Java 3D to extend it. + // static Hashtable fbConfigInfoTable = new Hashtable(); -- Chien static Hashtable fbConfigTable = new Hashtable(); // The native graphics version, vendor, and renderer information @@ -631,6 +654,7 @@ public class Canvas3D extends Canvas { LightBin lightBin = null; EnvironmentSet environmentSet = null; AttributeBin attributeBin = null; + ShaderBin shaderBin = null; RenderMolecule renderMolecule = null; PolygonAttributesRetained polygonAttributes = null; LineAttributesRetained lineAttributes = null; @@ -641,7 +665,7 @@ public class Canvas3D extends Canvas { ColoringAttributesRetained coloringAttributes = null; Transform3D modelMatrix = null; TextureBin textureBin = null; - + /** * cached RenderBin states for lazy native states update @@ -652,7 +676,7 @@ public class Canvas3D extends Canvas { FogRetained fog = null; ModelClipRetained modelClip = null; Color3f sceneAmbient = new Color3f(); - TextureUnitStateRetained texUnitState[] = null; + TextureUnitStateRetained[] texUnitState = null; /** * cached View states for lazy native states update @@ -669,6 +693,8 @@ public class Canvas3D extends Canvas { TexCoordGenerationRetained texCoordGeneration = null; RenderingAttributesRetained renderingAttrs = null; AppearanceRetained appearance = null; + + ShaderProgramRetained shaderProgram = null; // only used in Mixed Mode rendering Object appHandle = null; @@ -678,6 +704,8 @@ public class Canvas3D extends Canvas { * Texture Generation linear mode. This is used for D3D * temporary turn displayList off and do its own coordinate * generation since D3D don't support it. + * + * TODO aces : is this still true in DX9? */ boolean texLinearMode = false; @@ -701,7 +729,9 @@ public class Canvas3D extends Canvas { // an unique bit to identify this canvas int canvasBit = 0; - + // an unique number to identify this canvas : ( canvasBit = 1 << canvasId) + int canvasId = 0; + // Avoid using this as lock, it cause deadlock Object cvLock = new Object(); Object evaluateLock = new Object(); @@ -757,10 +787,10 @@ public class Canvas3D extends Canvas { static final int ARB_MULTISAMPLE = 0x200; static final int EXT_COMPILED_VERTEX_ARRAYS = 0x400; static final int SUN_VIDEO_RESIZE = 0x800; - static final int STENCIL_BUFFER = 0x1000; - // The following three variables are set by - // createNewContext()/createQueryContext() callback + // The following 10 variables are set by the native + // createNewContext()/createQueryContext() methods + // Supported Extensions int extensionsSupported = 0; @@ -770,6 +800,33 @@ public class Canvas3D extends Canvas { // Texture Boundary Width Max int textureBoundaryWidthMax = 0; + boolean multiTexAccelerated = false; + + // Max number of texture coordinate sets + int maxTexCoordSets = 1; + + // Max number of fixed-function texture units + int maxTextureUnits = 1; + + // Max number of fragment shader texture units + int maxTextureImageUnits = 0; + + // Max number of vertex shader texture units + int maxVertexTextureImageUnits = 0; + + // Max number of combined shader texture units + int maxCombinedTextureImageUnits = 0; + + // Max number of vertex attrs (not counting coord, etc.) + int maxVertexAttrs = 0; + + // End of variables set by createNewContext()/createQueryContext() + + // The total available number of texture units used by either the + // fixed-function or programmable shader pipeline. + // This is computed as: max(maxTextureUnits, maxTextureImageUnits) + int maxAvailableTextureUnits; + // Texture Width, Height Max int textureWidthMax = 0; int textureHeightMax = 0; @@ -802,29 +859,31 @@ public class Canvas3D extends Canvas { static final int TEXTUREBIN_BIT = 0x3; static final int RENDERMOLECULE_BIT = 0x4; static final int TRANSPARENCY_BIT = 0x5; + static final int SHADERBIN_BIT = 0x6; // bitmask to specify if the corresponding "bin" needs to be updated int stateUpdateMask = 0; // the set of current "bins" that is to be updated, the stateUpdateMask // specifies if each bin in this set is updated or not. - Object curStateToUpdate[] = new Object[6]; - + Object curStateToUpdate[] = new Object[7]; - // Native method for determining the number of texture unit supported - native int getTextureUnitCount(long ctx); // Native method for determining the texture color table size // in the underlying API for this Canvas3D. /* native int getTextureColorTableSize(long ctx); */ // This is the native method for creating the underlying graphics context. - native long createNewContext(long display, int window, int vid, long fbConfig, - long shareCtx, boolean isSharedCtx, - boolean offScreen); + private native long createNewContext(long display, int window, int vid, + long fbConfig, long shareCtx, boolean isSharedCtx, + boolean offScreen, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable); - native void createQueryContext(long display, int window, int vid, long fbConfig, - boolean offScreen, int width, int height); + private native void createQueryContext(long display, int window, int vid, + long fbConfig, boolean offScreen, int width, int height, + boolean glslLibraryAvailable, + boolean cgLibraryAvailable); native static void destroyContext(long display, int window, long context); @@ -863,9 +922,6 @@ public class Canvas3D extends Canvas { // The following three methods are used in multi-pass case - // Native method for setting the depth func - native void setDepthFunc(long ctx, int func); - // native method for setting blend color native void setBlendColor(long ctx, float red, float green, float blue, float alpha); @@ -1001,7 +1057,7 @@ public class Canvas3D extends Canvas { // native method for updating the texture unit state map - native void updateTexUnitStateMap(long ctx, int numActiveTexUnit, + private native void updateTexUnitStateMap(long ctx, int numActiveTexUnit, int[] texUnitStateMap); /** @@ -1082,7 +1138,7 @@ public class Canvas3D extends Canvas { public Canvas3D(GraphicsConfiguration graphicsConfiguration) { this(checkForValidGraphicsConfig(graphicsConfiguration), false); - // TODO 1.4: remove call to checkForValidGraphicsConfig. + // XXXX: ENHANCEMENT -- remove call to checkForValidGraphicsConfig. // Call should then be: // this(graphicsConfiguration, false); } @@ -1135,14 +1191,22 @@ public class Canvas3D extends Canvas { // Needed for Win32-D3D only. vid = nativeWSobj.getCanvasVid(graphicsConfiguration); + // Issue 163 : Set dirty bits for both Renderer and RenderBin + cvDirtyMask[0] = VIEW_INFO_DIRTY; + cvDirtyMask[1] = VIEW_INFO_DIRTY; + // Fix for issue 20. // Needed for Linux and Solaris. - Object fbConfigObject; - fbConfigObject = fbConfigTable.get(graphicsConfiguration); - if ((fbConfigObject != null) && - (fbConfigObject instanceof Long)) { - fbConfig = ((Long)fbConfigObject).longValue(); - /* System.out.println("Canvas3D creation FBConfig = " + fbConfig + + GraphicsConfigInfo gcInfo; + gcInfo = (GraphicsConfigInfo) fbConfigTable.get(graphicsConfiguration); + if (gcInfo != null) { + fbConfig = gcInfo.getFBConfig(); + requestedStencilSize = gcInfo.getRequestedStencilSize(); + + /* + System.out.println("Canvas3D : requestedStencilSize is " + + requestedStencilSize); + System.out.println("Canvas3D creation FBConfig = " + fbConfig + " offScreen is " + offScreen ); */ // This check is needed for Unix and Win-ogl only. fbConfig should @@ -1151,8 +1215,8 @@ public class Canvas3D extends Canvas { throw new IllegalArgumentException (J3dI18N.getString("Canvas3D23")); } - } - + } + if (offScreen) { screen = new Screen3D(graphicsConfiguration, offScreen); @@ -1164,7 +1228,8 @@ public class Canvas3D extends Canvas { // callback from AWT, set the added flag here added = true; synchronized(dirtyMaskLock) { - cvDirtyMask |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + cvDirtyMask[0] |= MOVED_OR_RESIZED_DIRTY; + cvDirtyMask[1] |= MOVED_OR_RESIZED_DIRTY; } // this canvas will not receive the paint callback either, @@ -1343,11 +1408,14 @@ public class Canvas3D extends Canvas { } synchronized(dirtyMaskLock) { - cvDirtyMask |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + cvDirtyMask[0] |= MOVED_OR_RESIZED_DIRTY; + cvDirtyMask[1] |= MOVED_OR_RESIZED_DIRTY; } - canvasBit = VirtualUniverse.mc.getCanvasBit(); - validCanvas = true; + canvasId = VirtualUniverse.mc.getCanvasId(); + canvasBit = 1 << canvasId; + + validCanvas = true; added = true; // In case the same canvas is removed and add back, @@ -1436,8 +1504,9 @@ public class Canvas3D extends Canvas { screen.removeUser(this); evaluateActive(); - VirtualUniverse.mc.freeCanvasBit(canvasBit); + VirtualUniverse.mc.freeCanvasId(canvasId); canvasBit = 0; + canvasId = 0; ra = null; graphicsContext3D = null; @@ -1812,7 +1881,7 @@ public class Canvas3D extends Canvas { width = height = 0; } - // TODO: illegalSharing + // XXXX: illegalSharing if ((offScreenCanvasSize.width != width) || (offScreenCanvasSize.height != height)) { @@ -1842,7 +1911,8 @@ public class Canvas3D extends Canvas { offScreenBuffer = buffer; synchronized(dirtyMaskLock) { - cvDirtyMask |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + cvDirtyMask[0] |= MOVED_OR_RESIZED_DIRTY; + cvDirtyMask[1] |= MOVED_OR_RESIZED_DIRTY; } } @@ -2033,7 +2103,7 @@ public class Canvas3D extends Canvas { screen.renderer.doWork(0); } else { - // TODO: + // XXXX: // Now we are in trouble, this will cause deadlock if // waitForOffScreenRendering() is invoked J3dMessage createMessage = VirtualUniverse.mc.getMessage(); @@ -2347,6 +2417,23 @@ public class Canvas3D extends Canvas { } /** + * Wrapper for native createNewContext method. + */ + long createNewContext(long shareCtx, boolean isSharedCtx) { + long retVal = createNewContext(this.screen.display, + this.window, + this.vid, + this.fbConfig, + shareCtx, isSharedCtx, + this.offScreen, + VirtualUniverse.mc.glslLibraryAvailable, + VirtualUniverse.mc.cgLibraryAvailable); + // compute the max available texture units + maxAvailableTextureUnits = Math.max(maxTextureUnits, maxTextureImageUnits); + return retVal; + } + + /** * Make the context associated with the specified canvas current. */ final void makeCtxCurrent() { @@ -2447,7 +2534,8 @@ public class Canvas3D extends Canvas { this.leftManualEyeInImagePlate.set(position); synchronized(dirtyMaskLock) { - cvDirtyMask |= Canvas3D.EYE_IN_IMAGE_PLATE_DIRTY; + cvDirtyMask[0] |= EYE_IN_IMAGE_PLATE_DIRTY; + cvDirtyMask[1] |= EYE_IN_IMAGE_PLATE_DIRTY; } redraw(); } @@ -2468,7 +2556,8 @@ public class Canvas3D extends Canvas { this.rightManualEyeInImagePlate.set(position); synchronized(dirtyMaskLock) { - cvDirtyMask |= Canvas3D.EYE_IN_IMAGE_PLATE_DIRTY; + cvDirtyMask[0] |= EYE_IN_IMAGE_PLATE_DIRTY; + cvDirtyMask[1] |= EYE_IN_IMAGE_PLATE_DIRTY; } redraw(); } @@ -2542,7 +2631,7 @@ public class Canvas3D extends Canvas { * @param position the object that will receive the position * @see #setMonoscopicViewPolicy */ - // TODO: This might not make sense for field-sequential HMD. + // XXXX: This might not make sense for field-sequential HMD. public void getCenterEyeInImagePlate(Point3d position) { if (canvasViewCache != null) { synchronized(canvasViewCache) { @@ -2851,17 +2940,22 @@ public class Canvas3D extends Canvas { synchronized(cvLock) { if (view == null) { canvasViewCache = null; + canvasViewCacheFrustum = null; } else { canvasViewCache = new CanvasViewCache(this, screen.screenViewCache, - view.viewCache); + view.viewCache); + // Issue 109 : construct a separate canvasViewCache for + // computing view frustum + canvasViewCacheFrustum = new CanvasViewCache(this, + screen.screenViewCache, + view.viewCache); synchronized (dirtyMaskLock) { - cvDirtyMask = (STEREO_DIRTY | MONOSCOPIC_VIEW_POLICY_DIRTY - | EYE_IN_IMAGE_PLATE_DIRTY | - MOVED_OR_RESIZED_DIRTY); + cvDirtyMask[0] = VIEW_INFO_DIRTY; + cvDirtyMask[1] = VIEW_INFO_DIRTY; } - } + } } } @@ -2904,7 +2998,8 @@ public class Canvas3D extends Canvas { stereoEnable = flag; useStereo = stereoEnable && stereoAvailable; synchronized(dirtyMaskLock) { - cvDirtyMask |= Canvas3D.STEREO_DIRTY; + cvDirtyMask[0] |= STEREO_DIRTY; + cvDirtyMask[1] |= STEREO_DIRTY; } redraw(); } @@ -2956,7 +3051,8 @@ public class Canvas3D extends Canvas { monoscopicViewPolicy = policy; synchronized(dirtyMaskLock) { - cvDirtyMask |= Canvas3D.MONOSCOPIC_VIEW_POLICY_DIRTY; + cvDirtyMask[0] |= MONOSCOPIC_VIEW_POLICY_DIRTY; + cvDirtyMask[1] |= MONOSCOPIC_VIEW_POLICY_DIRTY; } redraw(); } @@ -3044,6 +3140,36 @@ public class Canvas3D extends Canvas { /** + * Returns a flag indicating whether or not the specified shading + * language is supported. A ShaderError will be generated if an + * unsupported shading language is used. + * + * @param shadingLanguage the shading language being queried, one of: + * <code>Shader.SHADING_LANGUAGE_GLSL</code> or + * <code>Shader.SHADING_LANGUAGE_CG</code>. + * + * @return true if the specified shading language is supported, + * false otherwise. + * + * @since Java 3D 1.4 + */ + public boolean isShadingLanguageSupported(int shadingLanguage) { + // Call queryProperties to ensure that the shading language flags are valid + queryProperties(); + + // Return flag for specified shading language + switch (shadingLanguage) { + case Shader.SHADING_LANGUAGE_GLSL: + return shadingLanguageGLSL; + case Shader.SHADING_LANGUAGE_CG: + return shadingLanguageCg; + } + + return false; + } + + + /** * Returns a read-only Map object containing key-value pairs that define * various properties for this Canvas3D. All of the keys are * String objects. The values are key-specific, but most will be @@ -3060,6 +3186,14 @@ public class Canvas3D extends Canvas { * <td><b>Value Type</b></td> * </tr> * <tr> + * <td><code>shadingLanguageCg</code></td> + * <td>Boolean</td> + * </tr> + * <tr> + * <td><code>shadingLanguageGLSL</code></td> + * <td>Boolean</td> + * </tr> + * <tr> * <td><code>doubleBufferAvailable</code></td> * <td>Boolean</td> * </tr> @@ -3076,6 +3210,10 @@ public class Canvas3D extends Canvas { * <td>Integer</td> * </tr> * <tr> + * <td><code>stencilSize</code></td> + * <td>Integer</td> + * </tr> + * <tr> * <td><code>texture3DAvailable</code></td> * <td>Boolean</td> * </tr> @@ -3116,10 +3254,26 @@ public class Canvas3D extends Canvas { * <td>Boolean</td> * </tr> * <tr> + * <td><code>textureCoordSetsMax</code></td> + * <td>Integer</td> + * </tr> + * <tr> * <td><code>textureUnitStateMax</code></td> * <td>Integer</td> * </tr> * <tr> + * <td><code>textureImageUnitsMax</code></td> + * <td>Integer</td> + * </tr> + * <tr> + * <td><code>textureImageUnitsVertexMax</code></td> + * <td>Integer</td> + * </tr> + * <tr> + * <td><code>textureImageUnitsCombinedMax</code></td> + * <td>Integer</td> + * </tr> + * <tr> * <td><code>textureCubeMapAvailable</code></td> * <td>Boolean</td> * </tr> @@ -3140,6 +3294,10 @@ public class Canvas3D extends Canvas { * <td>Float</td> * </tr> * <tr> + * <td><code>vertexAttrsMax</code></td> + * <td>Integer</td> + * </tr> + * <tr> * <td><code>compressedGeometry.majorVersionNumber</code></td> * <td>Integer</td> * </tr> @@ -3164,6 +3322,22 @@ public class Canvas3D extends Canvas { * <p> * <ul> * <li> + * <code>shadingLanguageCg</code> + * <ul> + * A Boolean indicating whether or not Cg shading Language + * is available for this Canvas3D. + * </ul> + * </li> + * + * <li> + * <code>shadingLanguageGLSL</code> + * <ul> + * A Boolean indicating whether or not GLSL shading Language + * is available for this Canvas3D. + * </ul> + * </li> + * + * <li> * <code>doubleBufferAvailable</code> * <ul> * A Boolean indicating whether or not double buffering @@ -3195,7 +3369,6 @@ public class Canvas3D extends Canvas { * </ul> * </li> * - * * <li> * <code>sceneAntialiasingNumPasses</code> * <ul> @@ -3209,6 +3382,14 @@ public class Canvas3D extends Canvas { * </li> * * <li> + * <code>stencilSize</code> + * <ul> + * An Integer indicating the number of stencil bits that are available + * for this Canvas3D. + * </ul> + * </li> + * + * <li> * <code>texture3DAvailable</code> * <ul> * A Boolean indicating whether or not 3D Texture mapping @@ -3329,14 +3510,48 @@ public class Canvas3D extends Canvas { * </li> * * <li> + * <code>textureCoordSetsMax</code> + * <ul> + * An Integer indicating the maximum number of texture coordinate sets + * supported by the underlying rendering layer. + * </ul> + * </li> + * + * <li> * <code>textureUnitStateMax</code> * <ul> - * An Integer indicating the maximum number of texture unit states - * supported by the underlying rendering layer. Java3D allows an - * application to specify number of texture unit states more than - * what the underlying rendering layer supports; in this case, Java3D - * will use multi-pass to support the specified number of texture - * unit states. + * An Integer indicating the maximum number of fixed-function texture units + * supported by the underlying rendering layer. If the number of + * application-sepcified texture unit states exceeds the maximum number + * for a Canvas3D, and the fixed-function rendering pipeline is used, then + * the texture will be effectively disabled for that Canvas3D. + * </ul> + * </li> + * + * <li> + * <code>textureImageUnitsMax</code> + * <ul> + * An Integer indicating the maximum number of texture image units + * that can be accessed by the fragment shader when programmable shaders + * are used. + * </ul> + * </li> + * + * <li> + * <code>textureImageUnitsVertexMax</code> + * <ul> + * An Integer indicating the maximum number of texture image units + * that can be accessed by the vertex shader when programmable shaders + * are used. + * </ul> + * </li> + * + * <li> + * <code>textureImageUnitsCombinedMax</code> + * <ul> + * An Integer indicating the combined maximum number of texture image units + * that can be accessed by the vertex shader and the fragment shader when + * programmable shaders are used. * </ul> * </li> * @@ -3401,6 +3616,15 @@ public class Canvas3D extends Canvas { * </li> * * <li> + * <code>vertexAttrsMax</code> + * <ul> + * An Integer indicating the maximum number of vertex attributes + * supported by the underlying rendering layer. This is in addition to + * the vertex coordinate (position), color, normal, and so forth. + * </ul> + * </li> + * + * <li> * <code>compressedGeometry.majorVersionNumber</code><br> * <code>compressedGeometry.minorVersionNumber</code><br> * <code>compressedGeometry.minorMinorVersionNumber</code> @@ -3451,7 +3675,11 @@ public class Canvas3D extends Canvas { // inside the native code after setting the various // fields in this object createQueryContext(screen.display, window, vid, - fbConfig, offScreen, 1, 1); + fbConfig, offScreen, 1, 1, + VirtualUniverse.mc.glslLibraryAvailable, + VirtualUniverse.mc.cgLibraryAvailable); + // compute the max available texture units + maxAvailableTextureUnits = Math.max(maxTextureUnits, maxTextureImageUnits); } /** @@ -3480,8 +3708,12 @@ public class Canvas3D extends Canvas { 1: Renderer.NUM_ACCUMULATION_SAMPLES); } values.add(new Integer(pass)); - - keys.add("compressedGeometry.majorVersionNumber"); + + keys.add("stencilSize"); + // Return the actual stencil size. + values.add(new Integer(actualStencilSize)); + + keys.add("compressedGeometry.majorVersionNumber"); values.add(new Integer(GeometryDecompressor.majorVersionNumber)); keys.add("compressedGeometry.minorVersionNumber"); values.add(new Integer(GeometryDecompressor.minorVersionNumber)); @@ -3552,8 +3784,29 @@ public class Canvas3D extends Canvas { values.add(new Boolean( (textureExtendedFeatures & TEXTURE_LOD_OFFSET) != 0)); + keys.add("textureCoordSetsMax"); + values.add(new Integer(maxTexCoordSets)); + keys.add("textureUnitStateMax"); - values.add(new Integer(numTexUnitSupported)); + values.add(new Integer(maxTextureUnits)); + + keys.add("textureImageUnitsMax"); + values.add(new Integer(maxTextureImageUnits)); + + keys.add("textureImageUnitsVertexMax"); + values.add(new Integer(maxVertexTextureImageUnits)); + + keys.add("textureImageUnitsCombinedMax"); + values.add(new Integer(maxCombinedTextureImageUnits)); + + keys.add("vertexAttrsMax"); + values.add(new Integer(maxVertexAttrs)); + + keys.add("shadingLanguageGLSL"); + values.add(new Boolean(shadingLanguageGLSL)); + + keys.add("shadingLanguageCg"); + values.add(new Boolean(shadingLanguageCg)); keys.add("native.version"); values.add(nativeGraphicsVersion); @@ -3587,12 +3840,21 @@ public class Canvas3D extends Canvas { void updateViewCache(boolean flag, CanvasViewCache cvc, BoundingBox frustumBBox, boolean doInfinite) { + assert cvc == null; synchronized(cvLock) { - if (firstPaintCalled && (canvasViewCache != null)) { - canvasViewCache.snapshot(); - canvasViewCache.computeDerivedData(flag, cvc, frustumBBox, - doInfinite); - } + if (firstPaintCalled && (canvasViewCache != null)) { + assert canvasViewCacheFrustum != null; + // Issue 109 : choose the appropriate cvCache + if (frustumBBox != null) { + canvasViewCacheFrustum.snapshot(true); + canvasViewCacheFrustum.computeDerivedData(flag, null, + frustumBBox, doInfinite); + } else { + canvasViewCache.snapshot(false); + canvasViewCache.computeDerivedData(flag, null, + null, doInfinite); + } + } } } @@ -3736,7 +3998,10 @@ public class Canvas3D extends Canvas { reset(); - cvDirtyMask |= VIEW_INFO_DIRTY; + synchronized (dirtyMaskLock) { + cvDirtyMask[0] |= VIEW_INFO_DIRTY; + cvDirtyMask[1] |= VIEW_INFO_DIRTY; + } needToRebuildDisplayList = true; ctxTimeStamp = VirtualUniverse.mc.getContextTimeStamp(); @@ -3754,6 +4019,7 @@ public class Canvas3D extends Canvas { lightBin = null; environmentSet = null; attributeBin = null; + shaderBin = null; textureBin = null; renderMolecule = null; polygonAttributes = null; @@ -3763,6 +4029,7 @@ public class Canvas3D extends Canvas { enableLighting = false; transparency = null; coloringAttributes = null; + shaderProgram = null; texture = null; texAttrs = null; if (texUnitState != null) { @@ -3849,7 +4116,10 @@ public class Canvas3D extends Canvas { updateMaterial(ctx, 1.0f, 1.0f, 1.0f, 1.0f); resetRendering(NOCHANGE); makeCtxCurrent(); - cvDirtyMask |= VIEW_INFO_DIRTY; + synchronized (dirtyMaskLock) { + cvDirtyMask[0] |= VIEW_INFO_DIRTY; + cvDirtyMask[1] |= VIEW_INFO_DIRTY; + } needToRebuildDisplayList = true; ctxTimeStamp = VirtualUniverse.mc.getContextTimeStamp(); @@ -3978,7 +4248,7 @@ public class Canvas3D extends Canvas { } else { if (rightStereoPass) { // Only set cache in right stereo pass, otherwise - // if the left stero pass set the cache value, + // if the left stereo pass set the cache value, // setModelViewMatrix() in right stereo pass will not // perform in RenderMolecules. this.modelMatrix = mTrans; @@ -3991,10 +4261,6 @@ public class Canvas3D extends Canvas { setDepthBufferWriteEnable(ctx, mode); } - void setTexUnitStateMap(int texUnitStateIndex, int texUnitIndex) { - texUnitStateMap[texUnitIndex] = texUnitStateIndex; - } - void setNumActiveTexUnit(int n) { numActiveTexUnit = n; } @@ -4011,6 +4277,29 @@ public class Canvas3D extends Canvas { return lastActiveTexUnit; } + // Create the texture state array + void createTexUnitState() { + texUnitState = new TextureUnitStateRetained[maxAvailableTextureUnits]; + for (int t = 0; t < maxAvailableTextureUnits; t++) { + texUnitState[t] = new TextureUnitStateRetained(); + texUnitState[t].texture = null; + texUnitState[t].mirror = null; + } + } + + // Create the texture unit state map + void createTexUnitStateMap() { + // Create the texture unit state map array, which is a mapping from + // texture unit state to the actual underlying texture unit + // NOTE: since this is now required to be a 1-to-1 mapping, we will + // initialize it as such + + texUnitStateMap = new int[maxAvailableTextureUnits]; + for (int t = 0; t < maxAvailableTextureUnits; t++) { + texUnitStateMap[t] = t; + } + } + // update the underlying layer of the current texture unit state map void updateTexUnitStateMap() { updateTexUnitStateMap(ctx, numActiveTexUnit, texUnitStateMap); @@ -4164,12 +4453,13 @@ public class Canvas3D extends Canvas { curStateToUpdate[bit] = bin; } - // update LightBin, EnvironmentSet, & AttributeBin if neccessary + // update LightBin, EnvironmentSet, AttributeBin & ShaderBin if neccessary // according to the stateUpdateMask static int ENV_STATE_MASK = (1 << LIGHTBIN_BIT) | - (1 << ENVIRONMENTSET_BIT) | - (1 << ATTRIBUTEBIN_BIT); + (1 << ENVIRONMENTSET_BIT) | + (1 << ATTRIBUTEBIN_BIT) | + (1 << SHADERBIN_BIT); void updateEnvState() { @@ -4190,6 +4480,12 @@ public class Canvas3D extends Canvas { curStateToUpdate[ATTRIBUTEBIN_BIT]).updateAttributes(this); } + if ((stateUpdateMask & (1 << SHADERBIN_BIT)) != 0) { + ((ShaderBin) + curStateToUpdate[SHADERBIN_BIT]).updateAttributes(this); + } + + // reset the state update mask for those environment state bits stateUpdateMask &= ~ENV_STATE_MASK; } @@ -4317,7 +4613,7 @@ public class Canvas3D extends Canvas { // it so there is no need to do so in // Renderer.freeContextResources() if (rdr.objectId > 0) { - Canvas3D.freeTexture(ctx, rdr.objectId); + freeTexture(ctx, rdr.objectId); VirtualUniverse.mc.freeTexture2DId(rdr.objectId); rdr.objectId = -1; @@ -4325,7 +4621,7 @@ public class Canvas3D extends Canvas { // Free Graphics2D Texture if ((graphics2D != null) && (graphics2D.objectId != -1)) { - Canvas3D.freeTexture(ctx, graphics2D.objectId); + freeTexture(ctx, graphics2D.objectId); VirtualUniverse.mc.freeTexture2DId(graphics2D.objectId); graphics2D.objectId = -1; } diff --git a/src/classes/share/javax/media/j3d/CanvasViewCache.java b/src/classes/share/javax/media/j3d/CanvasViewCache.java index 7e0ba88..db55ebc 100644 --- a/src/classes/share/javax/media/j3d/CanvasViewCache.java +++ b/src/classes/share/javax/media/j3d/CanvasViewCache.java @@ -342,10 +342,19 @@ class CanvasViewCache extends Object { * NOTE: This is probably not needed, but we'll do it for symmetry * with the ScreenViewCache and ViewCache objects. */ - synchronized void snapshot() { - cvcDirtyMask = canvas.cvDirtyMask; - canvas.cvDirtyMask = 0; - useStereo = canvas.useStereo; + synchronized void snapshot(boolean computeFrustum) { + // Issue 109 : determine the the correct index to use -- either the + // Renderer or RenderBin + int dirtyIndex = computeFrustum ? + Canvas3D.RENDER_BIN_DIRTY_IDX : Canvas3D.RENDERER_DIRTY_IDX; + + synchronized (canvas.dirtyMaskLock) { + // Issue 109 : read/clear the dirty bits for the correct index + cvcDirtyMask = canvas.cvDirtyMask[dirtyIndex]; + canvas.cvDirtyMask[dirtyIndex] = 0; + } + + useStereo = canvas.useStereo; monoscopicViewPolicy = canvas.monoscopicViewPolicy; leftManualEyeInImagePlate.set(canvas.leftManualEyeInImagePlate); rightManualEyeInImagePlate.set(canvas.rightManualEyeInImagePlate); @@ -384,13 +393,29 @@ class CanvasViewCache extends Object { private void doComputeDerivedData(boolean currentFlag, CanvasViewCache cvc, BoundingBox frustumBBox, boolean doInfinite) { - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { + // Issue 109 : determine the the correct index to use -- either the + // Renderer or RenderBin + int dirtyIndex = (frustumBBox != null) ? + Canvas3D.RENDER_BIN_DIRTY_IDX : Canvas3D.RENDERER_DIRTY_IDX; + int scrvcDirtyMask; + + // Issue 109 : read/clear the dirty bits for the correct index + synchronized (screenViewCache) { + scrvcDirtyMask = screenViewCache.scrvcDirtyMask[dirtyIndex]; + // reset screen view dirty mask if canvas is offScreen. Note: + // there is only one canvas per offscreen, so it is ok to + // do the reset here. + if (canvas.offScreen) { + screenViewCache.scrvcDirtyMask[dirtyIndex] = 0; + } + } + + if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_2)) { if(cvcDirtyMask != 0) System.out.println("cvcDirtyMask : " + cvcDirtyMask); - if(screenViewCache.scrvcDirtyMask != 0) - System.out.println("scrvcDirtyMask : "+ - screenViewCache.scrvcDirtyMask); + if(scrvcDirtyMask != 0) + System.out.println("scrvcDirtyMask : "+ scrvcDirtyMask); if(viewCache.vcDirtyMask != 0) System.out.println("vcDirtyMask : " + viewCache.vcDirtyMask); @@ -406,13 +431,13 @@ class CanvasViewCache extends Object { // This flag is use to force a computation when a ViewPlatformTransform // is detected. No sync. needed. We're doing a read of t/f. - // TODO: Peeking at the dirty flag is a hack. Need to revisit this. + // XXXX: Peeking at the dirty flag is a hack. Need to revisit this. boolean vprNotDirty = (viewCache.vpRetained.vprDirtyMask == 0); if(!canvas.offScreen && (vprNotDirty) && (cvcDirtyMask == 0) && - (screenViewCache.scrvcDirtyMask == 0) && + (scrvcDirtyMask == 0) && (viewCache.vcDirtyMask == 0) && !(updateLastTime && (doInfinite != lastDoInfinite))) { if(frustumBBox != null) @@ -439,7 +464,7 @@ class CanvasViewCache extends Object { // System.out.println("vpcToVworld is \n" + vpcToVworld); - try { + try { vworldToVpc.invert(vpcToVworld); } catch (SingularMatrixException e) { @@ -484,19 +509,13 @@ class CanvasViewCache extends Object { if (frustumBBox != null) computefrustumBBox(frustumBBox); - // Copy the computed data into cvc. + // Issue 109: cvc should *always* be null + assert cvc == null; if(cvc != null) copyComputedCanvasViewCache(cvc, doInfinite); canvas.canvasDirty |= Canvas3D.VIEW_MATRIX_DIRTY; - // reset screen view dirty mask if canvas is offScreen. Note: - // there is only one canvas per offscreen, so it is ok to - // do the reset here. - if (canvas.offScreen) { - screenViewCache.scrvcDirtyMask = 0; - } - if((J3dDebug.devPhase) && (J3dDebug.canvasViewCache >= J3dDebug.LEVEL_1)) { // Print some data : System.out.println("useStereo = " + useStereo); @@ -908,7 +927,7 @@ class CanvasViewCache extends Object { */ private void cacheEyePosition() { if (viewCache.compatibilityModeEnable) { - // TODO: Compute compatibility mode eye position in ImagePlate??? + // XXXX: Compute compatibility mode eye position in ImagePlate??? cacheEyePosScreenRelative(leftManualEyeInImagePlate, rightManualEyeInImagePlate); } @@ -965,7 +984,7 @@ class CanvasViewCache extends Object { private void computePlateToVworld() { if (viewCache.compatibilityModeEnable) { - // TODO: implement this correctly for compat mode + // XXXX: implement this correctly for compat mode leftPlateToVworld.setIdentity(); vworldToLeftPlate.setIdentity(); } @@ -1027,7 +1046,7 @@ class CanvasViewCache extends Object { // Concatenate headToLeftImagePlate with leftPlateToVworld if (viewCache.compatibilityModeEnable) { - // TODO: implement this correctly for compat mode + // XXXX: implement this correctly for compat mode headToVworld.setIdentity(); } else { @@ -1054,7 +1073,7 @@ class CanvasViewCache extends Object { // Create a transform with the view platform to coexistence scale tMat1.set(viewPlatformScale); - // TODO: Is this really correct to ignore HMD? + // XXXX: Is this really correct to ignore HMD? if (viewCache.viewPolicy != View.HMD_VIEW) { switch (viewCache.coexistenceCenterInPworldPolicy) { @@ -1161,7 +1180,7 @@ class CanvasViewCache extends Object { private void computeCoexistenceToPlate() { if (viewCache.compatibilityModeEnable) { - // TODO: implement this correctly + // XXXX: implement this correctly coexistenceToLeftPlate.setIdentity(); return; } @@ -1334,7 +1353,7 @@ class CanvasViewCache extends Object { B = scale * -backClipDistance; } - // TODO: Can optimize for HMD case. + // XXXX: Can optimize for HMD case. if (true /*viewCache.viewPolicy != View.HMD_VIEW*/) { // Call buildProjView to build the projection and view matrices. @@ -1392,7 +1411,7 @@ class CanvasViewCache extends Object { } } } - // TODO: The following code has never been ported + // XXXX: The following code has never been ported // else { // Point3d cen_eye; // @@ -1467,14 +1486,14 @@ class CanvasViewCache extends Object { ecToCc.setIdentity(); - // TODO: we have no concept of glass correction in the Java 3D API + // XXXX: we have no concept of glass correction in the Java 3D API // // Correction in apparent 3D position of window due to glass/CRT // and spherical/cylinderical curvarure of CRT. // This boils down to producing modified values of Lx Ly Hx Hy // and is different for hot spot vs. window center corrections. // - /* TODO: + /* XXXX: double cx, cy; if(viewPolicy != HMD_VIEW && enable_crt_glass_correction) { if (correction_point == CORRECTION_POINT_WINDOW_CENTER) { @@ -1812,20 +1831,20 @@ class CanvasViewCache extends Object { } Transform3D getImagePlateToVworld() { - // TODO: Document -- This will return the transform of left plate. + // XXXX: Document -- This will return the transform of left plate. return leftPlateToVworld; } Transform3D getLastVworldToImagePlate() { - // TODO: Document -- This will return the transform of left plate. + // XXXX: Document -- This will return the transform of left plate. return lastVworldToLeftPlate; } Transform3D getVworldToImagePlate() { - // TODO: Document -- This will return the transform of left plate. + // XXXX: Document -- This will return the transform of left plate. return vworldToLeftPlate; } diff --git a/src/classes/share/javax/media/j3d/CanvasViewEventCatcher.java b/src/classes/share/javax/media/j3d/CanvasViewEventCatcher.java index 74dc617..2b723e0 100644 --- a/src/classes/share/javax/media/j3d/CanvasViewEventCatcher.java +++ b/src/classes/share/javax/media/j3d/CanvasViewEventCatcher.java @@ -42,7 +42,10 @@ class CanvasViewEventCatcher extends ComponentAdapter { System.out.println("It is canvas!"); } synchronized(canvas) { - canvas.cvDirtyMask |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + synchronized (canvas.dirtyMaskLock) { + canvas.cvDirtyMask[0] |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + canvas.cvDirtyMask[1] |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + } canvas.resizeGraphics2D = true; } @@ -60,9 +63,12 @@ class CanvasViewEventCatcher extends ComponentAdapter { System.out.println("Component moved " + e); } - synchronized(canvas) { - canvas.cvDirtyMask |= Canvas3D.MOVED_OR_RESIZED_DIRTY; - } + synchronized(canvas) { + synchronized (canvas.dirtyMaskLock) { + canvas.cvDirtyMask[0] |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + canvas.cvDirtyMask[1] |= Canvas3D.MOVED_OR_RESIZED_DIRTY; + } + } // Can't sync. with canvas lock since canvas.getLocationOnScreen() // required Component lock. The order is reverse of // removeNotify() lock sequence which required Component lock diff --git a/src/classes/share/javax/media/j3d/CapabilityBits.java b/src/classes/share/javax/media/j3d/CapabilityBits.java index c7844ae..0b7b41b 100644 --- a/src/classes/share/javax/media/j3d/CapabilityBits.java +++ b/src/classes/share/javax/media/j3d/CapabilityBits.java @@ -23,7 +23,7 @@ class CapabilityBits extends Object { // Node extends SceneGraphObject static final int NODE_ENABLE_COLLISION_REPORTING = 0; static final int NODE_ENABLE_PICK_REPORTING = 1; - static final int NODE_ALLOW_PICK = 2; + private static final int NODE_UNUSED_BIT = 2; static final int NODE_ALLOW_BOUNDS_READ = 3; static final int NODE_ALLOW_BOUNDS_WRITE = 4; static final int NODE_ALLOW_PICKABLE_READ = 5; @@ -241,6 +241,11 @@ class CapabilityBits extends Object { static final int ALTERNATE_APPEARANCE_ALLOW_SCOPE_READ = 16; static final int ALTERNATE_APPEARANCE_ALLOW_SCOPE_WRITE = 17; + // Additional Node bits (must go after all existing Node subclass bits) + static final int NODE_ALLOW_PARENT_READ = 46; + static final int NODE_ALLOW_LOCALE_READ = 47; + + // NodeComponent extends SceneGraphObject // Appearance extends NodeComponent @@ -267,6 +272,12 @@ class CapabilityBits extends Object { static final int APPEARANCE_ALLOW_TEXTURE_UNIT_STATE_READ = 20; static final int APPEARANCE_ALLOW_TEXTURE_UNIT_STATE_WRITE = 21; + // ShaderAppearance extends Appearance + static final int SHADER_APPEARANCE_ALLOW_SHADER_PROGRAM_READ = 22; + static final int SHADER_APPEARANCE_ALLOW_SHADER_PROGRAM_WRITE = 23; + static final int SHADER_APPEARANCE_ALLOW_SHADER_ATTRIBUTE_SET_READ = 24; + static final int SHADER_APPEARANCE_ALLOW_SHADER_ATTRIBUTE_SET_WRITE = 25; + // AuralAttributes extends NodeComponent static final int AURAL_ATTRIBUTES_ALLOW_ATTRIBUTE_GAIN_READ = 0; static final int AURAL_ATTRIBUTES_ALLOW_ATTRIBUTE_GAIN_WRITE = 1; @@ -362,6 +373,10 @@ class CapabilityBits extends Object { static final int RENDERING_ATTRIBUTES_ALLOW_IGNORE_VERTEX_COLORS_WRITE = 10; static final int RENDERING_ATTRIBUTES_ALLOW_DEPTH_ENABLE_WRITE = 11; + static final int RENDERING_ATTRIBUTES_ALLOW_DEPTH_TEST_FUNCTION_READ = 12; + static final int RENDERING_ATTRIBUTES_ALLOW_DEPTH_TEST_FUNCTION_WRITE = 13; + static final int RENDERING_ATTRIBUTES_ALLOW_STENCIL_ATTRIBUTES_READ = 14; + static final int RENDERING_ATTRIBUTES_ALLOW_STENCIL_ATTRIBUTES_WRITE = 15; // TexCoordGeneration extends NodeComponent static final int TEX_COORD_GENERATION_ALLOW_ENABLE_READ = 0; @@ -415,6 +430,20 @@ class CapabilityBits extends Object { static final int TEXTURE_UNIT_STATE_ALLOW_STATE_READ = 0; static final int TEXTURE_UNIT_STATE_ALLOW_STATE_WRITE = 1; + // ShaderProgram extends NodeComponent + static final int SHADER_PROGRAM_ALLOW_SHADERS_READ = 0; + static final int SHADER_PROGRAM_ALLOW_NAMES_READ = 1; + + // ShaderAttributeSet extends NodeComponent + static final int SHADER_ATTRIBUTE_SET_ALLOW_ATTRIBUTES_READ = 0; + static final int SHADER_ATTRIBUTE_SET_ALLOW_ATTRIBUTES_WRITE = 1; + + // ShaderAttribute extends NodeComponent + + // ShaderAttributeObject extends ShaderAttribute + static final int SHADER_ATTRIBUTE_OBJECT_ALLOW_VALUE_READ = 0; + static final int SHADER_ATTRIBUTE_OBJECT_ALLOW_VALUE_WRITE = 1; + // Geometry extends NodeComponent // NOTE: additional bits are below the subclasses @@ -445,6 +474,12 @@ class CapabilityBits extends Object { static final int GEOMETRY_ARRAY_ALLOW_REF_DATA_WRITE = 19; static final int GEOMETRY_ARRAY_ALLOW_COUNT_WRITE = 20; static final int GEOMETRY_ARRAY_ALLOW_REF_DATA_READ = 21; + static final int GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_READ = 22; + static final int GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_WRITE = 23; + + // Additional GeometryArray bits (must go after IndexedGeometryArray bits) + static final int INDEXED_GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_INDEX_READ = 24; + static final int INDEXED_GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_INDEX_WRITE = 25; // CompressedGeometry extends Geometry static final int COMPRESSED_GEOMETRY_ALLOW_COUNT_READ = 0; diff --git a/src/classes/share/javax/media/j3d/CgShaderProgram.java b/src/classes/share/javax/media/j3d/CgShaderProgram.java new file mode 100644 index 0000000..c531073 --- /dev/null +++ b/src/classes/share/javax/media/j3d/CgShaderProgram.java @@ -0,0 +1,173 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The CgShaderProgram object is a concrete implementation of a + * ShaderProgram node component for NVIDIA's Cg shader language. + * + * @see SourceCodeShader + * + * @since Java 3D 1.4 + */ + +public class CgShaderProgram extends ShaderProgram { + + /** + * Constructs a Cg shader program node component. + * + * <br> + * TODO: ADD MORE DOCUMENTATION HERE. + */ + public CgShaderProgram() { + } + + // Implement abstract setVertexAttrNames method (inherit javadoc from parent class) + public void setVertexAttrNames(String[] vertexAttrNames) { + checkForLiveOrCompiled(); + + if (vertexAttrNames != null) { + for (int i = 0; i < vertexAttrNames.length; i++) { + if (vertexAttrNames[i] == null) { + throw new NullPointerException(); + } + } + } + + ((CgShaderProgramRetained)this.retained).setVertexAttrNames(vertexAttrNames); + } + + // Implement abstract getVertexAttrNames method (inherit javadoc from parent class) + public String[] getVertexAttrNames() { + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_NAMES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("CgShaderProgram0")); + } + } + + return ((CgShaderProgramRetained)this.retained).getVertexAttrNames(); + } + + // Implement abstract setShaderAttrNames method (inherit javadoc from parent class) + public void setShaderAttrNames(String[] shaderAttrNames) { + checkForLiveOrCompiled(); + + if (shaderAttrNames != null) { + for (int i = 0; i < shaderAttrNames.length; i++) { + if (shaderAttrNames[i] == null) { + throw new NullPointerException(); + } + } + } + + ((CgShaderProgramRetained)this.retained).setShaderAttrNames(shaderAttrNames); + } + + // Implement abstract getShaderAttrNames method (inherit javadoc from parent class) + public String[] getShaderAttrNames() { + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_NAMES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("CgShaderProgram0")); + } + } + + return ((CgShaderProgramRetained)this.retained).getShaderAttrNames(); + } + + /** + * Copies the specified array of shaders into this shader + * program. This method makes a shallow copy of the array. The + * array of shaders may be null or empty (0 length), but the + * elements of the array must be non-null. The shading language of + * each shader in the array must be + * <code>SHADING_LANGUAGE_CG</code>. Each shader in the array must + * be a SourceCodeShader. There must be no more than one vertex shader + * and one fragment shader in the array. + * + * @param shaders array of Shader objects to be copied into this + * ShaderProgram + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalArgumentException if the shading language of + * any shader in the shaders array is <em>not</em> + * <code>SHADING_LANGUAGE_CG</code>. + * + * @exception IllegalArgumentException if there are more than one + * vertex shader or more than one fragment shader in the shaders + * array. + * + * @exception ClassCastException if any shader in the shaders + * array is <em>not</em> a SourceCodeShader. + */ + public void setShaders(Shader[] shaders) { + checkForLiveOrCompiled(); + + if (shaders != null) { + // Check shaders for valid shading language, class type, etc. + for (int i = 0; i < shaders.length; i++) { + boolean hasVertexShader = false; + boolean hasFragmentShader = false; + + // Check shading language + if (shaders[i].getShadingLanguage() != Shader.SHADING_LANGUAGE_CG) { + throw new IllegalArgumentException(J3dI18N.getString("CgShaderProgram2")); + } + + // Check for more than one vertex shader or fragment shader + if (shaders[i].getShaderType() == Shader.SHADER_TYPE_VERTEX) { + if (hasVertexShader) { + throw new IllegalArgumentException(J3dI18N.getString("CgShaderProgram3")); + } + hasVertexShader = true; + } + else { // Shader.SHADER_TYPE_FRAGMENT + if (hasFragmentShader) { + throw new IllegalArgumentException(J3dI18N.getString("CgShaderProgram4")); + } + hasFragmentShader = true; + } + + // Try to cast shader to SourceCodeShader; it will throw + // ClassCastException if it isn't. + SourceCodeShader shad = (SourceCodeShader)shaders[i]; + } + } + + ((CgShaderProgramRetained)this.retained).setShaders(shaders); + } + + // Implement abstract getShaders method (inherit javadoc from parent class) + public Shader[] getShaders() { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_SHADERS_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("CgShaderProgram1")); + } + } + + return ((CgShaderProgramRetained)this.retained).getShaders(); + } + + /** + * Creates a retained mode CgShaderProgramRetained object that this + * CgShaderProgram component object will point to. + */ + void createRetained() { + this.retained = new CgShaderProgramRetained(); + this.retained.setSource(this); + } + +} diff --git a/src/classes/share/javax/media/j3d/CgShaderProgramRetained.java b/src/classes/share/javax/media/j3d/CgShaderProgramRetained.java new file mode 100644 index 0000000..eed2484 --- /dev/null +++ b/src/classes/share/javax/media/j3d/CgShaderProgramRetained.java @@ -0,0 +1,283 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The CgShaderProgram object is a concrete implementation of a + * ShaderProgram node component for NVIDIA's Cg shader language. + * + * @see SourceCodeShader + * + * @since Java 3D 1.4 + */ + +class CgShaderProgramRetained extends ShaderProgramRetained { + + /** + * Constructs a Cg shader program node component. + * + * <br> + * TODO: ADD MORE DOCUMENTATION HERE. + */ + CgShaderProgramRetained() { + } + + synchronized void createMirrorObject() { + // System.out.println("CgShaderProgramRetained : createMirrorObject"); + // This method should only call by setLive(). + if (mirror == null) { + CgShaderProgramRetained mirrorCgSP = new CgShaderProgramRetained(); + mirror = mirrorCgSP; + } + initMirrorObject(); + } + + // ShaderAttributeValue methods + + native ShaderError setUniform1i(long ctx, + long shaderProgramId, + long uniformLocation, + int value); + + native ShaderError setUniform1f(long ctx, + long shaderProgramId, + long uniformLocation, + float value); + + native ShaderError setUniform2i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + native ShaderError setUniform2f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniform3i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + native ShaderError setUniform3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniform4i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + native ShaderError setUniform4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniformMatrix3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniformMatrix4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + // ShaderAttributeArray methods + + native ShaderError setUniform1iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform1fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniform2iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform2fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniform3iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniform4iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniformMatrix3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniformMatrix4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + + + /* New native interfaces */ + private native ShaderError createNativeShader(long ctx, int shaderType, long[] shaderId); + private native ShaderError destroyNativeShader(long ctx, long shaderId); + private native ShaderError compileNativeShader(long ctx, long shaderId, String program); + + private native ShaderError createNativeShaderProgram(long ctx, long[] shaderProgramId); + private native ShaderError destroyNativeShaderProgram(long ctx, long shaderProgramId); + private native ShaderError linkNativeShaderProgram(long ctx, long shaderProgramId, + long[] shaderId); + private native void lookupNativeVertexAttrNames(long ctx, long shaderProgramId, + int numAttrNames, String[] attrNames, boolean[] errArr); + private native void lookupNativeShaderAttrNames(long ctx, long shaderProgramId, + int numAttrNames, String[] attrNames, long[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr); + + private native ShaderError useShaderProgram(long ctx, long shaderProgramId); + + /** + * Method to return a flag indicating whether this + * ShaderProgram is supported on the specified Canvas. + */ + boolean isSupported(Canvas3D cv) { + return cv.shadingLanguageCg; + } + + /** + * Method to create the native shader. + */ + ShaderError createShader(long ctx, ShaderRetained shader, long[] shaderIdArr) { + return createNativeShader(ctx, shader.shaderType, shaderIdArr); + } + + /** + * Method to destroy the native shader. + */ + ShaderError destroyShader(long ctx, long shaderId) { + return destroyNativeShader(ctx, shaderId); + } + + /** + * Method to compile the native shader. + */ + ShaderError compileShader(long ctx, long shaderId, String source) { + return compileNativeShader(ctx, shaderId, source ); + } + + /** + * Method to create the native shader program. + */ + ShaderError createShaderProgram(long ctx, long[] shaderProgramIdArr) { + return createNativeShaderProgram(ctx, shaderProgramIdArr); + } + + /** + * Method to destroy the native shader program. + */ + ShaderError destroyShaderProgram(long ctx, long shaderProgramId) { + return destroyNativeShaderProgram(ctx, shaderProgramId); + } + + /** + * Method to link the native shader program. + */ + ShaderError linkShaderProgram(long ctx, long shaderProgramId, long[] shaderIds) { + return linkNativeShaderProgram(ctx, shaderProgramId, shaderIds); + } + + ShaderError bindVertexAttrName(long ctx, long shaderProgramId, String attrName, int attrIndex) { + // This is a no-op for Cg + return null; + } + + void lookupVertexAttrNames(long ctx, long shaderProgramId, String[] attrNames, boolean[] errArr) { + lookupNativeVertexAttrNames(ctx, shaderProgramId, attrNames.length, attrNames, errArr); + } + + void lookupShaderAttrNames(long ctx, long shaderProgramId, + String[] attrNames, AttrNameInfo[] attrNameInfoArr) { + + int numAttrNames = attrNames.length; + + long[] locArr = new long[numAttrNames]; + int[] typeArr = new int[numAttrNames]; + int[] sizeArr = new int[numAttrNames]; // currently unused + boolean[] isArrayArr = new boolean[numAttrNames]; + + // Initialize loc array to -1 (indicating no location) + for (int i = 0; i < numAttrNames; i++) { + locArr[i] = -1; + } + + lookupNativeShaderAttrNames(ctx, shaderProgramId, + numAttrNames, attrNames, locArr, typeArr, sizeArr, isArrayArr); + + for (int i = 0; i < numAttrNames; i++) { + attrNameInfoArr[i] = new AttrNameInfo(); + attrNameInfoArr[i].setLocation(locArr[i]); + attrNameInfoArr[i].setArray(isArrayArr[i]); + attrNameInfoArr[i].setType(typeArr[i]); + System.err.println(attrNames[i] + + " : loc = " + locArr[i] + + ", type = " + typeArr[i] + + ", isArray = " + isArrayArr[i] + + ", size = " + sizeArr[i]); + } + } + + /** + * Method to enable the native shader program. + */ + ShaderError enableShaderProgram(long ctx, long shaderProgramId) { + return useShaderProgram(ctx, shaderProgramId); + } + + /** + * Method to disable the native shader program. + */ + ShaderError disableShaderProgram(long ctx) { + return useShaderProgram(ctx, 0); + } + + +} diff --git a/src/classes/share/javax/media/j3d/Clip.java b/src/classes/share/javax/media/j3d/Clip.java index b32342b..e374ec3 100644 --- a/src/classes/share/javax/media/j3d/Clip.java +++ b/src/classes/share/javax/media/j3d/Clip.java @@ -61,6 +61,12 @@ public class Clip extends Leaf { public static final int ALLOW_BACK_DISTANCE_WRITE = CapabilityBits.CLIP_ALLOW_BACK_DISTANCE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_APPLICATION_BOUNDS_READ, + ALLOW_BACK_DISTANCE_READ + }; + /** * Constructs a Clip node with default parameters. The default * values are as follows: @@ -72,12 +78,17 @@ public class Clip extends Leaf { */ public Clip () { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** * Constructs a Clip node with the specified back clip distance. */ public Clip(double backDistance) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ClipRetained)this.retained).initBackDistance(backDistance); } diff --git a/src/classes/share/javax/media/j3d/ColoringAttributes.java b/src/classes/share/javax/media/j3d/ColoringAttributes.java index 996edf1..6858829 100644 --- a/src/classes/share/javax/media/j3d/ColoringAttributes.java +++ b/src/classes/share/javax/media/j3d/ColoringAttributes.java @@ -115,6 +115,12 @@ public class ColoringAttributes extends NodeComponent { */ public static final int SHADE_GOURAUD = 3; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_COLOR_READ, + ALLOW_SHADE_MODEL_READ + }; + /** * Constructs a ColoringAttributes node with default parameters. * The default values are as follows: @@ -125,6 +131,8 @@ public class ColoringAttributes extends NodeComponent { */ public ColoringAttributes() { // Just use default attributes + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -134,7 +142,10 @@ public class ColoringAttributes extends NodeComponent { * SHADE_FLAT, or SHADE_GOURAUD */ public ColoringAttributes(Color3f color, int shadeModel) { - ((ColoringAttributesRetained)this.retained).initColor(color); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((ColoringAttributesRetained)this.retained).initColor(color); ((ColoringAttributesRetained)this.retained).initShadeModel(shadeModel); } @@ -149,7 +160,10 @@ public class ColoringAttributes extends NodeComponent { */ public ColoringAttributes(float red, float green, float blue, int shadeModel) { - ((ColoringAttributesRetained)this.retained).initColor(red, green,blue); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((ColoringAttributesRetained)this.retained).initColor(red, green,blue); ((ColoringAttributesRetained)this.retained).initShadeModel(shadeModel); } @@ -315,7 +329,8 @@ public class ColoringAttributes extends NodeComponent { * Capability read bit set will be displayed. */ public String toString() { - StringBuffer str=new StringBuffer("ColoringAttributes:"); + StringBuffer str = new StringBuffer(getNamePrefix()); + str.append("javax.media.j3d.ColoringAttributes: "); String shadingModes[] = { "FASTEST", "NICEST", "SHADE_FLAT", "SHADE_GOURAUD" }; diff --git a/src/classes/share/javax/media/j3d/CompressedGeometry.java b/src/classes/share/javax/media/j3d/CompressedGeometry.java index 60541f9..8609349 100644 --- a/src/classes/share/javax/media/j3d/CompressedGeometry.java +++ b/src/classes/share/javax/media/j3d/CompressedGeometry.java @@ -14,11 +14,10 @@ package javax.media.j3d; /** * The compressed geometry object is used to store geometry in a - * compressed format. Using compressed geometry reduces the amount - * of memory needed by a Java 3D application and increases the speed - * objects can be sent over the network. Once geometry decompression - * hardware support becomes available, increased rendering performance - * will also result from the use of compressed geometry. + * compressed format. Using compressed geometry may increase the speed + * objects can be sent over the network. Note that the geometry will + * be decompressed in memory, so the application will not see any + * memory savings. * <p> * Compressed geometry may be passed to this CompressedGeometry object * in one of two ways: by copying the data into this object using the @@ -49,6 +48,8 @@ package javax.media.j3d; * the results are undefined. * </li> * </ul> + * + * @deprecated As of Java 3D version 1.4. */ public class CompressedGeometry extends Geometry { @@ -87,10 +88,21 @@ public class CompressedGeometry extends Geometry { ALLOW_REF_DATA_READ = CapabilityBits.COMPRESSED_GEOMETRY_ALLOW_REF_DATA_READ; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_COUNT_READ, + ALLOW_HEADER_READ, + ALLOW_GEOMETRY_READ, + ALLOW_REF_DATA_READ + }; + /** * Package scoped default constructor for use by cloneNodeComponent. */ CompressedGeometry() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -156,6 +168,9 @@ public class CompressedGeometry extends Geometry { throw new IllegalArgumentException (J3dI18N.getString("CompressedGeometry0")) ; + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + // Create a separate copy of the given header. cgHeader = new CompressedGeometryHeader() ; hdr.copy(cgHeader) ; @@ -174,33 +189,10 @@ public class CompressedGeometry extends Geometry { } /** - * Creates a new CompressedGeometry NodeComponent. The - * specified compressed geometry data is accessed by reference - * from the specified buffer. - * If the version number of compressed geometry, as specified by - * the CompressedGeometryHeader, is incompatible with the - * supported version of compressed geometry in the current version - * of Java 3D, the compressed geometry object will not be - * rendered. - * - * @param hdr the compressed geometry header. This is copied - * into the CompressedGeometry NodeComponent. - * - * @param compressedGeometry a buffer containing an NIO byte buffer - * of compressed geometry data. The - * geometry must conform to the format described in Appendix B of - * the <i>Java 3D API Specification</i>. + * This constructor is not implemented. * - * @exception UnsupportedOperationException this method is not - * yet implemented - * - * @exception IllegalArgumentException if a problem is detected with the - * header, - * or if the java.nio.Buffer contained in the specified J3DBuffer - * is not a java.nio.ByteBuffer object. - * - * @see CompressedGeometryHeader - * @see Canvas3D#queryProperties + * @exception UnsupportedOperationException this constructor is not + * implemented * * @since Java 3D 1.3 */ @@ -323,7 +315,6 @@ public class CompressedGeometry extends Geometry { // the same number of Shape3D objects as TriangleArray using 1/2 // to 2/3 of the vertices, with only a marginal performance penalty. // - // TODO revisit this return decompressor.toTriangleStripArrays(cgr) ; } @@ -345,9 +336,7 @@ public class CompressedGeometry extends Geometry { /** * Gets the compressed geometry data reference. * - * @return the current compressed geometry data reference; - * null is returned if this compressed geometry object was created - * with a J3DBuffer reference rather than a byte array. + * @return the current compressed geometry data reference. * * @exception IllegalStateException if the data access mode for this * object is not by-reference. @@ -372,14 +361,11 @@ public class CompressedGeometry extends Geometry { /** - * Gets the compressed geometry data buffer reference. + * Gets the compressed geometry data buffer reference, which is + * always null since NIO buffers are not supported for + * CompressedGeometry objects. * - * @return the current compressed geometry data buffer reference; - * null is returned if this compressed geometry object was created - * with a byte array reference rather than a J3DBuffer. - * - * @exception IllegalStateException if the data access mode for this - * object is not by-reference. + * @return null * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph @@ -392,11 +378,6 @@ public class CompressedGeometry extends Geometry { throw new CapabilityNotSetException (J3dI18N.getString("CompressedGeometry6")) ; - if (!isByReference()) - throw new IllegalStateException - (J3dI18N.getString("CompressedGeometry8")) ; - - // TODO: implement this when NIO buffer support is added return null; } diff --git a/src/classes/share/javax/media/j3d/CompressedGeometryHeader.java b/src/classes/share/javax/media/j3d/CompressedGeometryHeader.java index 39f409a..38876a9 100644 --- a/src/classes/share/javax/media/j3d/CompressedGeometryHeader.java +++ b/src/classes/share/javax/media/j3d/CompressedGeometryHeader.java @@ -25,6 +25,8 @@ import javax.vecmath.*; * provided. * * @see CompressedGeometry + * + * @deprecated As of Java 3D version 1.4. */ public class CompressedGeometryHeader extends Object { diff --git a/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java b/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java index 6bd7164..737fa4d 100644 --- a/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java +++ b/src/classes/share/javax/media/j3d/CompressedGeometryRetained.java @@ -81,23 +81,31 @@ class CompressedGeometryRetained extends GeometryRetained { private GeometryRetained pickGeometry = null ; /** - * Native method that returns availability of a native by-reference + * Formerly native method that returns availability of a native by-reference * rendering API for compressed geometry. */ - native boolean decompressByRef(long ctx) ; + private boolean decompressByRef(long ctx) { + return false; + } /** - * Native method that returns availability of hardware acceleration for - * compressed geometry of the given version. + * Formerly native method that returns availability of hardware + * rendering (and acceleration) for compressed geometry of the + * given version. */ - native boolean decompressHW(long ctx, int majorVersion, int minorVersion) ; + private boolean decompressHW(long ctx, int majorVersion, int minorVersion) { + return false; + } /** - * Native method that does the rendering + * Formerly native method that does HW compressed geometry rendering */ - native void execute(long ctx, int version, int bufferType, - int bufferContents, int renderFlags, - int offset, int size, byte[] geometry) ; + private void execute(long ctx, int version, int bufferType, + int bufferContents, int renderFlags, + int offset, int size, byte[] geometry) { + + assert false : "This method should never be called!"; + } /** * Method for calling native execute() method on behalf of the J3D renderer. @@ -107,7 +115,7 @@ class CompressedGeometryRetained extends GeometryRetained { boolean multiScreen, int screen, boolean ignoreVertexColors, int pass) { - // TODO: alpha udpate + // XXXX: alpha udpate execute(cv.ctx, packedVersion, bufferType, bufferContents, renderFlags, offset, size, compressedGeometry) ; } @@ -313,12 +321,12 @@ class CompressedGeometryRetained extends GeometryRetained { // The following intersect() methods are used to implement geometry-based // picking and collision. // - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { GeometryRetained geom = getPickGeometry() ; return (geom != null ? - geom.intersect(pickShape, dist, iPnt) : false); + geom.intersect(pickShape, iInfo, flags, iPnt) : false); } - + boolean intersect(Bounds targetBound) { GeometryRetained geom = getPickGeometry() ; return (geom != null ? geom.intersect(targetBound) : false); diff --git a/src/classes/share/javax/media/j3d/ConeSound.java b/src/classes/share/javax/media/j3d/ConeSound.java index 8b57d27..424195b 100644 --- a/src/classes/share/javax/media/j3d/ConeSound.java +++ b/src/classes/share/javax/media/j3d/ConeSound.java @@ -147,6 +147,12 @@ public class ConeSound extends PointSound { public static final int ALLOW_ANGULAR_ATTENUATION_WRITE = CapabilityBits.CONE_SOUND_ALLOW_ANGULAR_ATTENUATION_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_DIRECTION_READ, + ALLOW_ANGULAR_ATTENUATION_READ + }; + /** * Constructs and initializes a new ConeSound node using default * parameters. The following default values are used: @@ -159,6 +165,8 @@ public class ConeSound extends PointSound { public ConeSound() { // Uses default values defined in ConeSoundRetained.java super(); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -177,6 +185,10 @@ public class ConeSound extends PointSound { Vector3f direction) { super(soundData, initialGain, position ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setDirection(direction); } @@ -201,6 +213,10 @@ public class ConeSound extends PointSound { float dirX, float dirY, float dirZ) { super(soundData, initialGain, posX, posY, posZ ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setDirection(dirX, dirY, dirZ); } @@ -248,6 +264,10 @@ public class ConeSound extends PointSound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority, position, frontDistanceAttenuation ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setBackDistanceGain( backDistanceAttenuation); ((ConeSoundRetained)this.retained).setDirection(direction); @@ -301,6 +321,10 @@ public class ConeSound extends PointSound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority, posX, posY, posZ, frontDistance, frontDistanceGain ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setDirection(dirX, dirY, dirZ); ((ConeSoundRetained)this.retained).setBackDistanceGain( backDistance, backDistanceGain ); @@ -346,6 +370,10 @@ public class ConeSound extends PointSound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority, position, distanceAttenuation ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setDirection(direction); ((ConeSoundRetained)this.retained).setAngularAttenuation( angularAttenuation); @@ -402,6 +430,10 @@ public class ConeSound extends PointSound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority, posX, posY, posZ, distance, distanceGain ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setDirection(dirX, dirY, dirZ); ((ConeSoundRetained)this.retained).setAngularAttenuation(angle, angularGain, frequencyCutoff); @@ -444,6 +476,10 @@ public class ConeSound extends PointSound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority, position, frontDistanceAttenuation ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setBackDistanceGain( backDistanceAttenuation); ((ConeSoundRetained)this.retained).setDirection(direction); @@ -497,6 +533,10 @@ public class ConeSound extends PointSound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority, posX, posY, posZ, frontDistance, frontDistanceGain ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ConeSoundRetained)this.retained).setBackDistanceGain( backDistance, backDistanceGain ); ((ConeSoundRetained)this.retained).setDirection(dirX, dirY, dirZ); diff --git a/src/classes/share/javax/media/j3d/DepthComponent.java b/src/classes/share/javax/media/j3d/DepthComponent.java index 97f6af1..ad3212d 100644 --- a/src/classes/share/javax/media/j3d/DepthComponent.java +++ b/src/classes/share/javax/media/j3d/DepthComponent.java @@ -31,10 +31,18 @@ public abstract class DepthComponent extends NodeComponent { public static final int ALLOW_DATA_READ = CapabilityBits.DEPTH_COMPONENT_ALLOW_DATA_READ; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SIZE_READ, + ALLOW_DATA_READ + }; + /** * default constructor */ DepthComponent() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** diff --git a/src/classes/share/javax/media/j3d/DirectionalLight.java b/src/classes/share/javax/media/j3d/DirectionalLight.java index 987e014..a858cd1 100644 --- a/src/classes/share/javax/media/j3d/DirectionalLight.java +++ b/src/classes/share/javax/media/j3d/DirectionalLight.java @@ -41,6 +41,11 @@ public class DirectionalLight extends Light { public static final int ALLOW_DIRECTION_WRITE = CapabilityBits.DIRECTIONAL_LIGHT_ALLOW_DIRECTION_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_DIRECTION_READ + }; + /** * Constructs a DirectionalLight node with default parameters. * The default values are as follows: @@ -49,6 +54,8 @@ public class DirectionalLight extends Light { * </ul> */ public DirectionalLight() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -59,6 +66,10 @@ public class DirectionalLight extends Light { */ public DirectionalLight(Color3f color, Vector3f direction) { super(color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((DirectionalLightRetained)this.retained).initDirection(direction); } @@ -71,6 +82,10 @@ public class DirectionalLight extends Light { */ public DirectionalLight(boolean lightOn, Color3f color, Vector3f direction) { super(lightOn, color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((DirectionalLightRetained)this.retained).initDirection(direction); } diff --git a/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java b/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java index 012f30a..b3f8625 100644 --- a/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java +++ b/src/classes/share/javax/media/j3d/DisplayListRenderMethod.java @@ -155,7 +155,7 @@ class DisplayListRenderMethod implements RenderMethod { Transform3D staticNormalTransform; if ((rm.primaryRenderAtomList != null) && - (rm.texCoordSetMapLen <= cv.numTexCoordSupported)) { + (rm.texCoordSetMapLen <= cv.maxTexCoordSets)) { cv.newDisplayList(cv.ctx, rm.displayListId); @@ -195,7 +195,7 @@ class DisplayListRenderMethod implements RenderMethod { geo = (GeometryArrayRetained)ra.geometry(); if ((geo.texCoordSetMap != null) && - (geo.texCoordSetMap.length > cv.numTexCoordSupported)) { + (geo.texCoordSetMap.length > cv.maxTexCoordSets)) { return; } @@ -224,7 +224,7 @@ class DisplayListRenderMethod implements RenderMethod { geo = (GeometryArrayRetained)ra.geometry(); if ((rm.primaryRenderAtomList != null) && - (rm.texCoordSetMapLen <= cv.numTexCoordSupported)) { + (rm.texCoordSetMapLen <= cv.maxTexCoordSets)) { id = ra.renderAtom.dlistIds[ra.index]; cv.newDisplayList(cv.ctx, id); diff --git a/src/classes/share/javax/media/j3d/ExceptionStrings.properties b/src/classes/share/javax/media/j3d/ExceptionStrings.properties index c3e8674..b1541ba 100644 --- a/src/classes/share/javax/media/j3d/ExceptionStrings.properties +++ b/src/classes/share/javax/media/j3d/ExceptionStrings.properties @@ -153,6 +153,12 @@ BranchGroup0=Cannot compile a live BranchGroup BranchGroup1=BranchGroup: no capability to detach BranchGroup2=Group: no capability to write children BranchGroup3=Picking can only work if BranchGroup is alive +BranchGroup4=BranchGroup: Mode has to be either PickInfo.PICK_BOUNDS or PickInfo.PICK_GEOMETRY +BranchGroup5=BranchGroup: Mode can't be PickInfo.PICK_GEOMETRY if PickShape is PickPoint +BranchGroup6=BranchGroup: CLOSEST_GEOM_INFO and ALL_GEOM_INFO can't be set together. +BranchGroup7=BranchGroup: Mode can't be PICK_BOUNDS if geometry information is needed +BranchGroup8=BranchGroup: PickShape can't be PickBounds if geometry information is needed +BranchGroup9=BranchGroup: Cannot call picking under a SharedGroup node CachedFrustum0=Frustum must have aleast 6 planes CachedFrustum1=Frustum must have 6 planes Clip0=Clip: no capability to set back distance @@ -172,7 +178,7 @@ CompressedGeometry5=CompressedGeometry: no capability to get geometry CompressedGeometry6=CompressedGeometry: no capability to get data reference CompressedGeometry7=CompressedGeometry: cannot directly access data in byReference mode CompressedGeometry8=CompressedGeometry: must be in byReference mode to use this method -CompressedGeometry9=CompressedGeometry: NIO buffer support is not currently implemented +CompressedGeometry9=CompressedGeometry: NIO buffer support is not implemented ClipRetained0=Clip: Immediate mode clip may not be in scene graph ClipRetained1=Clip: illegal node under Background geometry Branch ClipRetained2=Clip: illegal node under SharedGroup Branch @@ -268,7 +274,7 @@ GeometryArray103=GeometryArray: initial tex coord index + valid vertex count > v GeometryArray104=GeometryArray: initial coord index + valid vertex count > vertex count GeometryArray105=GeometryArray: must not be in BY_REFERENCE mode to use this method GeometryArray106=GeometryArray: texCoord set mapping is not specified -GeometryArray107=GeometryArray: must specify at least one set of tex coord +GeometryArray107=GeometryArray: must specify at least one set of texture coordinates GeometryArray108=GeometryArray: invalid texCoord set mapping GeometryArray109=GeometryArray: must be in TEXTURE_COORDINATE_4 mode to use this method GeometryArray110=GeometryArray: validVertexCount should be greater than or equal to zero @@ -285,6 +291,18 @@ GeometryArray120=GeometryArray: must be direct nio buffer GeometryArray121=GeometryArray: None of the TEXTURE_COORDINATE bits are set in vertexFormat GeometryArray122=GeometryArray: NORMALS bit is not set in vertexFormat GeometryArray123=GeometryArray: None of the COLOR bits are set in vertexFormat +GeometryArray124=GeometryArray: texCoordSetCount < 0 +GeometryArray125=GeometryArray: vertexAttrCount < 0 +GeometryArray126=GeometryArray: no capability to set vertex attributes +GeometryArray127=GeometryArray: no capability to read vertex attributes +GeometryArray128=GeometryArray: VERTEX_ATTRIBUTES flag must not be set in INTERLEAVED mode +GeometryArray129=GeometryArray: vertex attr array length is incorrect +GeometryArray130=GeometryArray: initial vertex attr index + valid vertex count > vertex count +GeometryArray131=GeometryArray: vertexAttrCount > 0, but VERTEX_ATTRIBUTES flag is not set +GeometryArray132=GeometryArray: vertexAttrCount != vertexAttrSizes.length +GeometryArray133=GeometryArray: vertexAttrSize value out of range +GeometryArray134=GeometryArray: vertexAttrSize invalid for this method +GeometryArray135=GeometryArray: USE_COORD_INDEX_ONLY bit cannot be set for non-indexed geometry GeometryDecompressor0=GeometryDecompressor: start+length > data array size GeometryDecompressor1=GeometryDecompressor: bad delta normal in compressed buffer GeometryDecompressorRetained0=GeometryDecompressorRetained: bad buffer data type @@ -318,6 +336,7 @@ GeometryStripArray4=GeometryStripArray: initial color index + valid vertex count GeometryStripArray5=GeometryStripArray: initial normal index + valid vertex count > vertex count GeometryStripArray6=GeometryStripArray: initial tex coord index + valid vertex count > vertex count GeometryStripArray7=GeometryStripArray: initial coord index + valid vertex count > vertex count +GeometryStripArray8=GeometryStripArray: initial vertex attr index + valid vertex count > vertex count GraphicsContext3D11=Background: Scene Graph background may not be in immediate mode GraphicsContext3D12=Fog: Scene Graph fog may not be in immediate mode GraphicsContext3D13=GraphicsContext3D: Light object is null @@ -358,6 +377,11 @@ Locale0=Locale.addBranchGraph: Branch Group already has a parent Locale1=Locale: no capability to detach BranchGroup Locale3=Locale.replaceBranchGraph: Branch Group already has a parent Locale4=Locale has been removed from its VirtualUniverse +Locale5=Locale: Mode has to be either PickInfo.PICK_BOUNDS or PickInfo.PICK_GEOMETRY +Locale6=Locale: Mode can't be PickInfo.PICK_GEOMETRY if PickShape is PickPoint +Locale7=Locale: CLOSEST_GEOM_INFO and ALL_GEOM_INFO can't be set together. +Locale8=Locale: Mode can't be PICK_BOUNDS if geometry information is needed +Locale9=Locale: PickShape can't be PickBounds if geometry information is needed IndexedLineStripArray0=IndexedLineStripArray: illegal vertexCount IndexedLineStripArray1=IndexedLineStripArray: illegal indexCount IndexedGeometryArray0=IndexedGeometryArray: no capability to get index count @@ -381,12 +405,11 @@ IndexedGeometryArray24=IndexedGeometryArray: index color value greater than the IndexedGeometryArray25=IndexedGeometryArray: index texcoord value greater than the array length IndexedGeometryArray26=IndexedGeometryArray: index normal value greater than the array length IndexedGeometryArray27=IndexedGeometryArray: index value less than zero +IndexedGeometryArray28=IndexedGeometryArray: no capability to set vertex attribute index +IndexedGeometryArray29=IndexedGeometryArray: no capability to get vertex attribute index +IndexedGeometryArray30=IndexedGeometryArray: index vertexAttr value greater than the array length IndexedLineArray0=IndexedLineArray: illegal vertexCount IndexedLineArray1=IndexedLineArray: illegal indexCount -IndexedGeometryArrayRetained0=execute() called on indexed geometry -IndexedGeometryArrayRetained1=WARNING: Memory redundantly allocated for Color Indices array since the USE_COORD_INDEX_ONLY flag has been specified. This will throw a NPE in a subsequent version -IndexedGeometryArrayRetained2=WARNING: Memory redundantly allocated for Normal Indices array since the USE_COORD_INDEX_ONLY flag has been specified. This will throw a NPE in a subsequent version -IndexedGeometryArrayRetained3=WARNING: Memory redundantly allocated for TextureCoordinate Indices array since the USE_COORD_INDEX_ONLY flag has been specified. This will throw a NPE in a subsequent version IndexedGeometryStripArray0=IndexedGeometryStripArray: no capability to get number of strips IndexedGeometryStripArray1=IndexedGeometryStripArray: no capability to get strip index counts IndexedGeometryStripArray2=IndexedGeometryStripArray: no capability to set strip index counts @@ -466,14 +489,15 @@ MorphRetained2=Morph: All GeometryArrays must be of same type MorphRetained5=Invalid SceneGraphPath encountered : localToVworld is null. MorphRetained7=Morph: number of weights not same as number of GeometryArrays MorphRetained8=Morph: sum of all weights is NOT 1.0 -Node0=Cannot get the parent of a live or compiled node +MorphRetained9=Morph: vertex attributes are not supported +Node0=Node: no capability to read parent Node1=Node: no capability to set bounds Node2=Node: no capability to read user bounds Node3=Node: no capability to read Pickable Node4=Node: no capability to set Collidable Node5=Node: no capability to set user auto compute bounds Node6=Node: no capability to read user auto compute bounds -Node7=Node: local to vworld transform is undefined for a node that is not part of a live scene graph +Node7=Node: local to vworld transform is undefined for a node that is compiled but not live Node8=Node: no capability to read local to vworld transform Node9=Node: Invalid geometric bounds Node11=cloneTree: should be overridden in child @@ -482,6 +506,14 @@ Node13=Node: Cannot clone a live or compiled scenegraph Node14=Node: no capability to set Pickable Node15=Node: Cannot compile, clone or getBounds on a scene graph that contains a cycle. Node16=Node: no capability to read Collidable +Node17=Node: no capability to read locale +PickInfo0=PickInfo: PICK_GEOMETRY mode - no capability to ALLOW_GEOMETRY_READ +PickInfo1=PickInfo: PICK_GEOMETRY mode - no capability to ALLOW_INTERSECT +PickInfo2=PickInfo: PICK_GEOMETRY mode - no capability to ALLOW_COORDINATE_READ +PickInfo3=PickInfo: PICK_GEOMETRY mode - no capability to ALLOW_COUNT_READ +PickInfo4=PickInfo: PICK_GEOMETRY mode - no capability to ALLOW_FORMAT_READ +PickInfo5=PickInfo: PICK_GEOMETRY mode - no capability to ALLOW_COORDINATE_INDEX_READ +PickInfo6=PickInfo: PICK_GEOMETRY mode - no capability to ALLOW_GEOMETRY_ARRAY_READ Picking0=Cannot call picking under a SharedGroup node Picking2=Picking: Node has no parent and locale. This is illegal! NodeComponent0=NodeComponent:cloneNodeComponent must be defined in subclass @@ -572,6 +604,10 @@ RenderingAttributes10=RenderingAttributes: no capability to set raster op RenderingAttributes11=RenderingAttributes: no capability to get raster op RenderingAttributes12=RenderingAttributes: no capability to set ignore vertex colors flag RenderingAttributes13=RenderingAttributes: no capability to get ignore vertex colors flag +RenderingAttributes14=RenderingAttributes: no capability to set depth test function +RenderingAttributes15=RenderingAttributes: no capability to get depth test function +RenderingAttributes16=RenderingAttributes: no capability to set stencil attributes +RenderingAttributes17=RenderingAttributes: no capability to get stencil attributes TriangleStripArrayRetained0=PickPoint doesn't make sense for geometry-based picking. Java 3D doesn't have spatial information of the surface. Should use PickBounds with BoundingSphere and set radius to a epsilon tolerance. TriangleStripArrayRetained1=stripVertexCounts element less than 3 RotationPathInterpolator0=RotationPathInterpolator: length of knots and quats must be of the same length @@ -891,6 +927,26 @@ ModelClip14=ModelClip: no capability to read influencing bounding leaf ModelClipRetained1=ModelClip: illegal node under SharedGroup Branch MasterControl0=OpenGL is not MT safe MasterControl1=Green threads are not supported +MasterControl2=NOTE: simulated multi-texture will not work for programmable shaders +MasterControl3=and will be removed entirely in the next release of Java 3D J3DBuffer0=Native access to NIO buffer not supported J3DBuffer1=NIO buffer must be a direct buffer J3DBuffer2=NIO buffer must match native byte order of underlying platform +GLSLShaderProgram0=GLSLShaderProgram: no capability to read names +GLSLShaderProgram1=GLSLShaderProgram: no capability to read shaders +GLSLShaderProgram2=GLSLShaderProgram: Shader has incompatible shading language +CgShaderProgram0=CgShaderProgram: no capability to read names +CgShaderProgram1=CgShaderProgram: no capability to read shaders +CgShaderProgram2=CgShaderProgram: Shader has incompatible shading language +CgShaderProgram3=CgShaderProgram: must not specify more than one vertex shader +CgShaderProgram4=CgShaderProgram: must not specify more than one fragment shader +ShaderAppearance0=ShaderAppearance: no capability to set shader program +ShaderAppearance1=ShaderAppearance: no capability to get shader program +ShaderAppearance2=ShaderAppearance: no capability to set shader attribute set +ShaderAppearance3=ShaderAppearance: no capability to get shader attribute set +ShaderAttributeBinding0=ShaderAttributeBinding is not supported +ShaderProgramRetained0=Shading language not supported +ShaderAttributeObject0=ShaderAttributeObject: no capability to get value +ShaderAttributeObject1=ShaderAttributeObject: no capability to set value +ShaderAttributeSet0=ShaderAttributeSet: no capability to get attribute +ShaderAttributeSet1=ShaderAttributeSet: no capability to set attribute diff --git a/src/classes/share/javax/media/j3d/ExponentialFog.java b/src/classes/share/javax/media/j3d/ExponentialFog.java index 75b17e1..9d95a32 100644 --- a/src/classes/share/javax/media/j3d/ExponentialFog.java +++ b/src/classes/share/javax/media/j3d/ExponentialFog.java @@ -46,6 +46,11 @@ public class ExponentialFog extends Fog { public static final int ALLOW_DENSITY_WRITE = CapabilityBits.EXPONENTIAL_FOG_ALLOW_DENSITY_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_DENSITY_READ + }; + /** * Constructs an ExponentialFog node with default parameters. * The default values are as follows: @@ -55,6 +60,8 @@ public class ExponentialFog extends Fog { */ public ExponentialFog() { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -63,6 +70,9 @@ public class ExponentialFog extends Fog { */ public ExponentialFog(Color3f color) { super(color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -73,6 +83,10 @@ public class ExponentialFog extends Fog { */ public ExponentialFog(Color3f color, float density) { super(color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ExponentialFogRetained)this.retained).initDensity(density); } @@ -84,6 +98,9 @@ public class ExponentialFog extends Fog { */ public ExponentialFog(float r, float g, float b) { super(r, g, b); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -96,6 +113,10 @@ public class ExponentialFog extends Fog { */ public ExponentialFog(float r, float g, float b, float density) { super(r, g, b); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ExponentialFogRetained)this.retained).initDensity(density); } diff --git a/src/classes/share/javax/media/j3d/ExponentialFogRetained.java b/src/classes/share/javax/media/j3d/ExponentialFogRetained.java index 512e521..b82efd9 100644 --- a/src/classes/share/javax/media/j3d/ExponentialFogRetained.java +++ b/src/classes/share/javax/media/j3d/ExponentialFogRetained.java @@ -21,7 +21,10 @@ import java.util.ArrayList; */ class ExponentialFogRetained extends FogRetained { // Fog density - float density = 1.0f; + private float density = 1.0f; + + // Issue 144: density in Eye Coordinates (EC) + private float densityInEc; // dirty bits for ExponentialFog static final int DENSITY_CHANGED = FogRetained.LAST_DEFINED_BIT << 1; @@ -108,7 +111,9 @@ class ExponentialFogRetained extends FogRetained { native void update(long ctx, float red, float green, float blue, float density); void update(long ctx, double scale) { - update(ctx, color.x, color.y, color.z, density); + // Issue 144: recompute the density in EC, and send it to native code + validateDistancesInEc(scale); + update(ctx, color.x, color.y, color.z, densityInEc); } @@ -128,6 +133,8 @@ class ExponentialFogRetained extends FogRetained { ((ExponentialFogRetained)mirrorFog).density = ((Float)((Object[])objs[4])[4]).floatValue(); } + // Issue 144: store the local to vworld scale used to transform the density + ((ExponentialFogRetained)mirrorFog).setLocalToVworldScale(getLastLocalToVworld().getDistanceScale()); super.updateMirrorObject(objs); } @@ -142,6 +149,18 @@ class ExponentialFogRetained extends FogRetained { return efr; } - + + // Issue 144: method to recompute the density in EC by multiplying the specified + // density by the inverse of the local to EC scale + /** + * Scale distances from local to eye coordinate. + */ + protected void validateDistancesInEc(double vworldToCoexistenceScale) { + // vworldToCoexistenceScale can be used here since + // CoexistenceToEc has a unit scale + double localToEcScale = getLocalToVworldScale() * vworldToCoexistenceScale; + + densityInEc = (float)(density / localToEcScale); + } } diff --git a/src/classes/share/javax/media/j3d/Fog.java b/src/classes/share/javax/media/j3d/Fog.java index cb5e517..ffd2292 100644 --- a/src/classes/share/javax/media/j3d/Fog.java +++ b/src/classes/share/javax/media/j3d/Fog.java @@ -77,6 +77,13 @@ public abstract class Fog extends Leaf { public static final int ALLOW_SCOPE_WRITE = CapabilityBits.FOG_ALLOW_SCOPE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_INFLUENCING_BOUNDS_READ, + ALLOW_COLOR_READ, + ALLOW_SCOPE_READ + }; + /** * Constructs a Fog node with default parameters. The default * values are as follows: @@ -89,6 +96,8 @@ public abstract class Fog extends Leaf { */ public Fog() { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -96,7 +105,10 @@ public abstract class Fog extends Leaf { * @param color the fog color */ public Fog(Color3f color) { - ((FogRetained)this.retained).initColor(color); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((FogRetained)this.retained).initColor(color); } /** @@ -106,7 +118,10 @@ public abstract class Fog extends Leaf { * @param b the blue component of the fog color */ public Fog(float r, float g, float b) { - ((FogRetained)this.retained).initColor(r, g, b); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((FogRetained)this.retained).initColor(r, g, b); } /** diff --git a/src/classes/share/javax/media/j3d/FogRetained.java b/src/classes/share/javax/media/j3d/FogRetained.java index 9c84fd5..9ab5ec6 100644 --- a/src/classes/share/javax/media/j3d/FogRetained.java +++ b/src/classes/share/javax/media/j3d/FogRetained.java @@ -90,6 +90,9 @@ abstract class FogRetained extends LeafRetained{ // Is true, if the mirror fog is viewScoped boolean isViewScoped = false; + // Scale value extracted from localToVworld transform + private double localToVworldScale = 1.0; + FogRetained() { localBounds = new BoundingBox(); ((BoundingBox)localBounds).setLower( 1.0, 1.0, 1.0); @@ -750,6 +753,8 @@ abstract class FogRetained extends LeafRetained{ } void updateTransformChange() { + super.updateTransformChange(); + setLocalToVworldScale(sgFog.getLastLocalToVworld().getDistanceScale()); } // Called on mirror object @@ -785,5 +790,19 @@ abstract class FogRetained extends LeafRetained{ void getMirrorObjects(ArrayList leafList, HashKey key) { leafList.add(mirrorFog); } - + + /** + * Scale distances from local to eye coordinate + */ + protected void validateDistancesInEc(double vworldToCoexistenceScale) { + assert false : "subclasses should override this method"; + } + + double getLocalToVworldScale() { + return localToVworldScale; + } + + void setLocalToVworldScale(double localToVworldScale) { + this.localToVworldScale = localToVworldScale; + } } diff --git a/src/classes/share/javax/media/j3d/Font3D.java b/src/classes/share/javax/media/j3d/Font3D.java index 5e440f8..d706abe 100644 --- a/src/classes/share/javax/media/j3d/Font3D.java +++ b/src/classes/share/javax/media/j3d/Font3D.java @@ -178,6 +178,49 @@ public class Font3D extends NodeComponent { bounds.setUpper(upper); } + // BY MIK OF CLASSX + /** + * Returns a GeometryArray of a glyph in this Font3D. + * + * @param c character from which to generate a tessellated glyph. + * + * @return a GeometryArray + * + * @since Java 3D 1.4 + */ + public GeometryArray getGlyphGeometry(char c) { + char code[] = { c }; + GlyphVector gv = font.createGlyphVector(frc, code); + + // triangulate the glyph + GeometryArrayRetained glyph_gar = triangulateGlyphs(gv, code[0]); + + // Assume that triangulateGlyphs returns a triangle array with only coords & normals + // (and without by-ref, interleaved, etc.) + assert glyph_gar instanceof TriangleArrayRetained : + "Font3D: GeometryArray is not an instance of TrangleArray"; + assert glyph_gar.getVertexFormat() == (GeometryArray.COORDINATES | GeometryArray.NORMALS) : + "Font3D: Illegal GeometryArray format -- only coordinates and normals expected"; + + // create a correctly sized TriangleArray + TriangleArray ga = new TriangleArray(glyph_gar.getVertexCount(),glyph_gar.getVertexFormat()); + + // temp storage for coords, normals + float tmp[] = new float[3]; + + int vertexCount = ga.getVertexCount(); + for(int i=0; i<vertexCount; i++) { + // copy the glyph geometry to the TriangleArray + glyph_gar.getCoordinate(i,tmp); + ga.setCoordinate(i,tmp); + + glyph_gar.getNormal(i,tmp); + ga.setNormal(i,tmp); + } + + return ga; + } + // Triangulate glyph with 'unicode' if not already done. GeometryArrayRetained triangulateGlyphs(GlyphVector gv, char c) { @@ -415,7 +458,7 @@ public class Font3D extends NodeComponent { } } - // TODO: Should use IndexedTriangleArray to avoid + // XXXX: Should use IndexedTriangleArray to avoid // duplication of vertices. To create triangles for // side faces, every vertex is duplicated currently. TriangleArray triAry = new TriangleArray(vertCnt, diff --git a/src/classes/share/javax/media/j3d/FreeListManager.java b/src/classes/share/javax/media/j3d/FreeListManager.java index f5c10c5..0233669 100644 --- a/src/classes/share/javax/media/j3d/FreeListManager.java +++ b/src/classes/share/javax/media/j3d/FreeListManager.java @@ -25,10 +25,9 @@ class FreeListManager { static final int DISPLAYLIST = 4; static final int TEXTURE2D = 5; static final int TEXTURE3D = 6; - static final int CANVASBIT = 7; - static final int VECTOR3D = 8; - static final int POINT3D = 9; - static int MAXINT = 9; + static final int VECTOR3D = 7; + static final int POINT3D = 8; + static int MAXINT = 8; // what list we are going to shrink next private static int currlist = 0; @@ -44,7 +43,6 @@ class FreeListManager { freelist[DISPLAYLIST] = new IntegerFreeList(); freelist[TEXTURE2D] = new IntegerFreeList(); freelist[TEXTURE3D] = new IntegerFreeList(); - freelist[CANVASBIT] = new IntegerFreeList(); freelist[POINT3D] = new MemoryFreeList("javax.vecmath.Point3d"); freelist[VECTOR3D] = new MemoryFreeList("javax.vecmath.Vector3d"); } diff --git a/src/classes/share/javax/media/j3d/GLSLShaderProgram.java b/src/classes/share/javax/media/j3d/GLSLShaderProgram.java new file mode 100644 index 0000000..5608cb8 --- /dev/null +++ b/src/classes/share/javax/media/j3d/GLSLShaderProgram.java @@ -0,0 +1,158 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The GLSLShaderProgram object is a concrete implementation of a + * ShaderProgram node component for the OpenGL GLSL shading language. + * + * @see SourceCodeShader + * + * @since Java 3D 1.4 + */ + +public class GLSLShaderProgram extends ShaderProgram { + + /** + * Constructs a GLSL shader program node component. + * + * <br> + * TODO: ADD MORE DOCUMENTATION HERE. + */ + public GLSLShaderProgram() { + } + + // Implement abstract setVertexAttrNames method (inherit javadoc from parent class) + public void setVertexAttrNames(String[] vertexAttrNames) { + checkForLiveOrCompiled(); + + if (vertexAttrNames != null) { + for (int i = 0; i < vertexAttrNames.length; i++) { + if (vertexAttrNames[i] == null) { + throw new NullPointerException(); + } + } + } + + ((GLSLShaderProgramRetained)this.retained).setVertexAttrNames(vertexAttrNames); + } + + // Implement abstract getVertexAttrNames method (inherit javadoc from parent class) + public String[] getVertexAttrNames() { + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_NAMES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GLSLShaderProgram0")); + } + } + + return ((GLSLShaderProgramRetained)this.retained).getVertexAttrNames(); + + } + + // Implement abstract setShaderAttrNames method (inherit javadoc from parent class) + public void setShaderAttrNames(String[] shaderAttrNames) { + checkForLiveOrCompiled(); + + if (shaderAttrNames != null) { + for (int i = 0; i < shaderAttrNames.length; i++) { + if (shaderAttrNames[i] == null) { + throw new NullPointerException(); + } + } + } + + ((GLSLShaderProgramRetained)this.retained).setShaderAttrNames(shaderAttrNames); + } + + // Implement abstract getShaderAttrNames method (inherit javadoc from parent class) + public String[] getShaderAttrNames() { + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_NAMES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GLSLShaderProgram0")); + } + } + + return ((GLSLShaderProgramRetained)this.retained).getShaderAttrNames(); + + } + + /** + * Copies the specified array of shaders into this shader + * program. This method makes a shallow copy of the array. The + * array of shaders may be null or empty (0 length), but the + * elements of the array must be non-null. The shading language of + * each shader in the array must be + * <code>SHADING_LANGUAGE_GLSL</code>. Each shader in the array must + * be a SourceCodeShader. + * + * @param shaders array of Shader objects to be copied into this + * ShaderProgram + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalArgumentException if the shading language of + * any shader in the shaders array is <em>not</em> + * <code>SHADING_LANGUAGE_GLSL</code>. + * + * @exception ClassCastException if any shader in the shaders + * array is <em>not</em> a SourceCodeShader. + * + * @exception NullPointerException if any element in the + * shaders array is null. + */ + public void setShaders(Shader[] shaders) { + checkForLiveOrCompiled(); + + if(shaders != null) { + // Check shaders for valid shading language and class type + for (int i = 0; i < shaders.length; i++) { + if (shaders[i].getShadingLanguage() != Shader.SHADING_LANGUAGE_GLSL) { + throw new IllegalArgumentException(J3dI18N.getString("GLSLShaderProgram2")); + } + + // Try to cast shader to SourceCodeShader; it will throw + // ClassCastException if it isn't. + SourceCodeShader shad = (SourceCodeShader)shaders[i]; + } + + } + + ((GLSLShaderProgramRetained)this.retained).setShaders(shaders); + } + + // Implement abstract getShaders method (inherit javadoc from parent class) + public Shader[] getShaders() { + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_SHADERS_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GLSLShaderProgram1")); + } + } + + return ((GLSLShaderProgramRetained)this.retained).getShaders(); + } + + /** + * Creates a retained mode GLSLShaderProgramRetained object that this + * GLSLShaderProgram component object will point to. + */ + void createRetained() { + this.retained = new GLSLShaderProgramRetained(); + this.retained.setSource(this); + } + + +} diff --git a/src/classes/share/javax/media/j3d/GLSLShaderProgramRetained.java b/src/classes/share/javax/media/j3d/GLSLShaderProgramRetained.java new file mode 100644 index 0000000..7d4e10b --- /dev/null +++ b/src/classes/share/javax/media/j3d/GLSLShaderProgramRetained.java @@ -0,0 +1,281 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The GLSLShaderProgram object is a concrete implementation of a + * ShaderProgram node component for the OpenGL GLSL shading language. + * + * @see SourceCodeShader + * + * @since Java 3D 1.4 + */ + +class GLSLShaderProgramRetained extends ShaderProgramRetained { + + /** + * Constructs a GLSL shader program node component. + * + * <br> + * TODO: ADD MORE DOCUMENTATION HERE. + */ + GLSLShaderProgramRetained() { + } + + synchronized void createMirrorObject() { + // System.out.println("GLSLShaderProgramRetained : createMirrorObject"); + // This method should only call by setLive(). + if (mirror == null) { + GLSLShaderProgramRetained mirrorGLSLSP = new GLSLShaderProgramRetained(); + mirror = mirrorGLSLSP; + mirror.source = source; + } + initMirrorObject(); + } + + // ShaderAttributeValue methods + + native ShaderError setUniform1i(long ctx, + long shaderProgramId, + long uniformLocation, + int value); + + native ShaderError setUniform1f(long ctx, + long shaderProgramId, + long uniformLocation, + float value); + + native ShaderError setUniform2i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + native ShaderError setUniform2f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniform3i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + native ShaderError setUniform3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniform4i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + native ShaderError setUniform4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniformMatrix3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + native ShaderError setUniformMatrix4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + // ShaderAttributeArray methods + + native ShaderError setUniform1iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform1fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniform2iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform2fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniform3iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniform4iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + native ShaderError setUniform4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniformMatrix3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + native ShaderError setUniformMatrix4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + /* New native interfaces */ + private native ShaderError createNativeShader(long ctx, int shaderType, long[] shaderId); + private native ShaderError destroyNativeShader(long ctx, long shaderId); + private native ShaderError compileNativeShader(long ctx, long shaderId, String program); + + private native ShaderError createNativeShaderProgram(long ctx, long[] shaderProgramId); + private native ShaderError destroyNativeShaderProgram(long ctx, long shaderProgramId); + private native ShaderError linkNativeShaderProgram(long ctx, long shaderProgramId, + long[] shaderId); + private native ShaderError bindNativeVertexAttrName(long ctx, long shaderProgramId, + String attrName, int attrIndex); + private native void lookupNativeShaderAttrNames(long ctx, long shaderProgramId, + int numAttrNames, String[] attrNames, long[] locArr, + int[] typeArr, int[] sizeArr, boolean[] isArrayArr); + + private native ShaderError useShaderProgram(long ctx, long shaderProgramId); + + /** + * Method to return a flag indicating whether this + * ShaderProgram is supported on the specified Canvas. + */ + boolean isSupported(Canvas3D cv) { + return cv.shadingLanguageGLSL; + } + + /** + * Method to create the native shader. + */ + ShaderError createShader(long ctx, ShaderRetained shader, long[] shaderIdArr) { + return createNativeShader(ctx, shader.shaderType, shaderIdArr); + } + + /** + * Method to destroy the native shader. + */ + ShaderError destroyShader(long ctx, long shaderId) { + return destroyNativeShader(ctx, shaderId); + } + + /** + * Method to compile the native shader. + */ + ShaderError compileShader(long ctx, long shaderId, String source) { + return compileNativeShader(ctx, shaderId, source ); + } + + /** + * Method to create the native shader program. + */ + ShaderError createShaderProgram(long ctx, long[] shaderProgramIdArr) { + return createNativeShaderProgram(ctx, shaderProgramIdArr); + } + + /** + * Method to destroy the native shader program. + */ + ShaderError destroyShaderProgram(long ctx, long shaderProgramId) { + return destroyNativeShaderProgram(ctx, shaderProgramId); + } + + /** + * Method to link the native shader program. + */ + ShaderError linkShaderProgram(long ctx, long shaderProgramId, long[] shaderIds) { + return linkNativeShaderProgram(ctx, shaderProgramId, shaderIds); + } + + ShaderError bindVertexAttrName(long ctx, long shaderProgramId, String attrName, int attrIndex) { + return bindNativeVertexAttrName(ctx, shaderProgramId, attrName, attrIndex); + } + + void lookupVertexAttrNames(long ctx, long shaderProgramId, String[] attrNames, boolean[] errArr) { + // This method is a no-op for GLSL + } + + void lookupShaderAttrNames(long ctx, long shaderProgramId, + String[] attrNames, AttrNameInfo[] attrNameInfoArr) { + + int numAttrNames = attrNames.length; + + long[] locArr = new long[numAttrNames]; + int[] typeArr = new int[numAttrNames]; + int[] sizeArr = new int[numAttrNames]; // currently unused + boolean[] isArrayArr = new boolean[numAttrNames]; + + // Initialize loc array to -1 (indicating no location) + for (int i = 0; i < numAttrNames; i++) { + locArr[i] = -1; + } + + lookupNativeShaderAttrNames(ctx, shaderProgramId, + numAttrNames, attrNames, locArr, typeArr, sizeArr, isArrayArr); + + for (int i = 0; i < numAttrNames; i++) { + attrNameInfoArr[i] = new AttrNameInfo(); + attrNameInfoArr[i].setLocation(locArr[i]); + attrNameInfoArr[i].setArray(isArrayArr[i]); + attrNameInfoArr[i].setType(typeArr[i]); +// System.err.println(attrNames[i] + +// " : loc = " + locArr[i] + +// ", type = " + typeArr[i] + +// ", isArray = " + isArrayArr[i] + +// ", size = " + sizeArr[i]); + } + } + + /** + * Method to enable the native shader program. + */ + ShaderError enableShaderProgram(long ctx, long shaderProgramId) { + return useShaderProgram(ctx, shaderProgramId); + } + + /** + * Method to disable the native shader program. + */ + ShaderError disableShaderProgram(long ctx) { + return useShaderProgram(ctx, 0); + } + + +} diff --git a/src/classes/share/javax/media/j3d/Geometry.java b/src/classes/share/javax/media/j3d/Geometry.java index 042b366..89391b1 100644 --- a/src/classes/share/javax/media/j3d/Geometry.java +++ b/src/classes/share/javax/media/j3d/Geometry.java @@ -32,14 +32,22 @@ package javax.media.j3d; public abstract class Geometry extends NodeComponent { /** - * Specifies that this Geometry allows intersect operation. + * Specifies that this Geometry allows intersect operation. This + * capability bit is set (true) by default for all Geometry objects. */ public static final int ALLOW_INTERSECT = CapabilityBits.GEOMETRY_ALLOW_INTERSECT; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_INTERSECT + }; + /** * Constructs a new Geometry object. */ public Geometry() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } } diff --git a/src/classes/share/javax/media/j3d/GeometryArray.java b/src/classes/share/javax/media/j3d/GeometryArray.java index 8851569..b784a11 100644 --- a/src/classes/share/javax/media/j3d/GeometryArray.java +++ b/src/classes/share/javax/media/j3d/GeometryArray.java @@ -17,7 +17,8 @@ import javax.vecmath.*; /** * The GeometryArray object contains separate arrays of positional - * coordinates, colors, normals, and texture coordinates that + * coordinates, colors, normals, texture coordinates, and vertex + * attributes that * describe point, line, or polygon geometry. This class is extended * to create the various primitive types (such as lines, * triangle strips, etc.). @@ -29,7 +30,8 @@ import javax.vecmath.*; * <li> * <b>By Copying:</b> * The existing methods for setting positional coordinates, colors, - * normals, and texture coordinates (such as <code>setCoordinate</code>, + * normals, texture coordinates, and vertex attributes + * (such as <code>setCoordinate</code>, * <code>setColors</code>, etc.) copy the data into this * GeometryArray. This is appropriate for many applications and * offers an application much flexibility in organizing its data. @@ -41,9 +43,11 @@ import javax.vecmath.*; * this feature, set the <code>BY_REFERENCE</code> bit in the * <code>vertexFormat</code> field of the constructor for this * GeometryArray. In this mode, the various set methods for - * coordinates, normals, colors, and texture coordinates are not used. + * coordinates, normals, colors, texture coordinates, and vertex attributes + * are not used. * Instead, new methods are used to set a reference to user-supplied - * coordinate, color, normal, and texture coordinate arrays (such as + * coordinate, color, normal, texture coordinate, and vertex attribute + * arrays (such as * <code>setCoordRefFloat</code>, <code>setColorRefFloat</code>, * etc.). Data in any array that is referenced by a live or compiled * GeometryArray object may only be modified via the @@ -133,6 +137,24 @@ public abstract class GeometryArray extends Geometry { ALLOW_TEXCOORD_WRITE = CapabilityBits.GEOMETRY_ARRAY_ALLOW_TEXCOORD_WRITE; /** + * Specifies that this GeometryArray allows reading the array of + * vertex attributes. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_VERTEX_ATTR_READ = CapabilityBits.GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_READ; + + /** + * Specifies that this GeometryArray allows writing the array of + * vertex attributes. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_VERTEX_ATTR_WRITE = CapabilityBits.GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_WRITE; + + /** * Specifies that this GeometryArray allows reading the count or * initial index information for this object. */ @@ -268,15 +290,12 @@ public abstract class GeometryArray extends Geometry { * is only valid in conjunction with the <code>BY_REFERENCE</code> * flag. * - * <p> - * NOTE: Use of this class requires version 1.4 of the - * Java<sup><font size="-2">TM</font></sup> 2 Platform. - * * @see J3DBuffer * @see #setCoordRefBuffer(J3DBuffer) * @see #setColorRefBuffer(J3DBuffer) * @see #setNormalRefBuffer(J3DBuffer) * @see #setTexCoordRefBuffer(int,J3DBuffer) + * @see #setVertexAttrRefBuffer(int,J3DBuffer) * @see #setInterleavedVertexBuffer(J3DBuffer) * * @since Java 3D 1.3 @@ -287,17 +306,30 @@ public abstract class GeometryArray extends Geometry { * Specifies that only the coordinate indices are used for indexed * geometry arrays. In this mode, the values from the coordinate * index array are used as a single set of index values to access - * the vertex data for all four vertex components (coord, color, - * normal, and texCoord). The color, normal, and texCoord index arrays - * are ignored. This flag is only valid for indexed geometry arrays + * the vertex data for all five vertex components (coord, color, + * normal, texCoord, and vertexAttr). The color, normal, texCoord, + * and vertexAttr index arrays are neither allocated nor used. Any + * attempt to access the color, normal, texCoord, + * or vertexAttr index arrays will result in a NullPointerException. + * This flag is only valid for indexed geometry arrays * (subclasses of IndexedGeometryArray). * * @since Java 3D 1.3 */ public static final int USE_COORD_INDEX_ONLY = 0x200; + /** + * Specifies that this GeometryArray contains one or more arrays of + * vertex attributes. These attributes are used in programmable + * shading. + * + * @since Java 3D 1.4 + */ + public static final int VERTEX_ATTRIBUTES = 0x1000; + + // Used to keep track of the last bit (for adding new bits only) - private static final int LAST_FORMAT_BIT = 0x800; + private static final int LAST_FORMAT_BIT = 0x1000; // Scratch arrays for converting Point[234]f to TexCoord[234]f @@ -306,11 +338,26 @@ public abstract class GeometryArray extends Geometry { private TexCoord4f [] texCoord4fArray = null; private TexCoord2f texCoord2fScratch = null; private TexCoord3f texCoord3fScratch = null; - - + + private static final int[] defTexCoordMap = { 0 }; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_COLOR_READ, + ALLOW_COORDINATE_READ, + ALLOW_COUNT_READ, + ALLOW_FORMAT_READ, + ALLOW_NORMAL_READ, + ALLOW_REF_DATA_READ, + ALLOW_TEXCOORD_READ, + ALLOW_VERTEX_ATTR_READ + }; + // non-public, no parameter constructor GeometryArray() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } @@ -321,12 +368,15 @@ public abstract class GeometryArray extends Geometry { * <ul> * texCoordSetCount : 1<br> * texCoordSetMap : { 0 }<br> + * vertexAttrCount : 0<br> + * vertexAttrSizes : null<br> * validVertexCount : vertexCount<br> * initialVertexIndex : 0<br> * initialCoordIndex : 0<br> * initialColorIndex : 0<br> * initialNormalIndex : 0<br> * initialTexCoordIndex : 0<br> + * initialVertexAttrIndex : 0<br> * all data array values : 0.0<br> * all data array references : null<br> * </ul> @@ -355,46 +405,29 @@ public abstract class GeometryArray extends Geometry { * <code>USE_COORD_INDEX_ONLY</code>, * to indicate that only the coordinate indices are used for indexed * geometry arrays. - * @exception IllegalArgumentException if vertexCount < 0, if - * vertexFormat does NOT include <code>COORDINATES</code>, - * if the <code>USE_COORD_INDEX_ONLY</code> bit is set for non-indexed - * geometry arrays (that is, GeometryArray objects that are not a - * subclass of IndexedGeometryArray), - * if the <code>INTERLEAVED</code> bit is set without the - * <code>BY_REFERENCE</code> bit being set, - * or if the <code>USE_NIO_BUFFER</code> bit is set without the - * <code>BY_REFERENCE</code> bit being set. + * + * @exception IllegalArgumentException if vertexCount < 0 + * + * @exception IllegalArgumentException if vertexFormat does <b>not</b> + * include <code>COORDINATES</code> + * + * @exception IllegalArgumentException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set for non-indexed geometry arrays (that is, GeometryArray objects + * that are not a subclass of IndexedGeometryArray) + * + * @exception IllegalArgumentException if the <code>INTERLEAVED</code> + * bit is set without the <code>BY_REFERENCE</code> bit being set + * + * @exception IllegalArgumentException if the <code>USE_NIO_BUFFER</code> + * bit is set without the <code>BY_REFERENCE</code> bit being set + * + * @exception IllegalArgumentException if the <code>INTERLEAVED</code> + * bit and the <code>VERTEX_ATTRIBUTES</code> bit are both set */ public GeometryArray(int vertexCount, int vertexFormat) { - - if (vertexCount < 0) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray96")); - - if ((vertexFormat & COORDINATES) == 0) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray0")); - - if ((vertexFormat & INTERLEAVED) != 0 && - (vertexFormat & BY_REFERENCE) == 0) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray80")); - - if ((vertexFormat & USE_NIO_BUFFER) != 0 && - (vertexFormat & BY_REFERENCE) == 0) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray117")); - - if ((vertexFormat & TEXTURE_COORDINATE) != 0) { - if ((vertexFormat & TEXTURE_COORDINATE_2) != 0) { - texCoord2fArray = new TexCoord2f[1]; - texCoord2fScratch = new TexCoord2f(); - } - else if ((vertexFormat & TEXTURE_COORDINATE_3) != 0) { - texCoord3fArray = new TexCoord3f[1]; - texCoord3fScratch = new TexCoord3f(); - } else if ((vertexFormat & TEXTURE_COORDINATE_4) != 0) { - texCoord4fArray = new TexCoord4f[1]; - } - } - - ((GeometryArrayRetained)this.retained).createGeometryArrayData(vertexCount, vertexFormat); + this(vertexCount, vertexFormat, + ((vertexFormat & TEXTURE_COORDINATE) != 0 ? 1 : 0), + ((vertexFormat & TEXTURE_COORDINATE) != 0 ? defTexCoordMap : null)); } @@ -467,48 +500,59 @@ public abstract class GeometryArray extends Geometry { * * <p> * <ul> - * <table BORDER=1 CELLSPACING=1 CELLPADDING=1> + * <table BORDER=1 CELLSPACING=2 CELLPADDING=2> * <tr> * <td><center><b>Index</b></center></td> * <td><center><b>Element</b></center></td> - * <td><center><b>Description</b></center></td> + * <td><b>Description</b></td> * </tr> * <tr> * <td><center>0</center></td> * <td><center>1</center></td> - * <td><center>Use tex coord set 1 for tex unit 0</center></td> + * <td>Use tex coord set 1 for tex unit 0</td> * </tr> * <tr> * <td><center>1</center></td> * <td><center>-1</center></td> - * <td><center>Use no tex coord set for tex unit 1</center></td> + * <td>Use no tex coord set for tex unit 1</td> * </tr> * <tr> * <td><center>2</center></td> * <td><center>0</center></td> - * <td><center>Use tex coord set 0 for tex unit 2</center></td> + * <td>Use tex coord set 0 for tex unit 2</td> * </tr> * <tr> * <td><center>3</center></td> * <td><center>1</center></td> - * <td><center>Reuse tex coord set 1 for tex unit 3</center></td> + * <td>Reuse tex coord set 1 for tex unit 3</td> * </tr> * </table> * </ul> * <p> * + * @exception IllegalArgumentException if vertexCount < 0 + * + * @exception IllegalArgumentException if vertexFormat does <b>not</b> + * include <code>COORDINATES</code> + * + * @exception IllegalArgumentException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set for non-indexed geometry arrays (that is, GeometryArray objects + * that are not a subclass of IndexedGeometryArray) + * + * @exception IllegalArgumentException if the <code>INTERLEAVED</code> + * bit is set without the <code>BY_REFERENCE</code> bit being set + * + * @exception IllegalArgumentException if the <code>USE_NIO_BUFFER</code> + * bit is set without the <code>BY_REFERENCE</code> bit being set + * + * @exception IllegalArgumentException if the <code>INTERLEAVED</code> + * bit and the <code>VERTEX_ATTRIBUTES</code> bit are both set + * * @exception IllegalArgumentException if - * <code>vertexCount < 0</code>, if vertexFormat does - * NOT include <code>COORDINATES</code>, if the - * <code>INTERLEAVED</code> bit is set without the - * <code>BY_REFERENCE</code> bit being set, if the - * <code>USE_NIO_BUFFER</code> bit is set without the - * <code>BY_REFERENCE</code> bit being set, if - * the <code>USE_COORD_INDEX_ONLY</code> bit is set for non-indexed - * geometry arrays (that is, GeometryArray objects that are not a - * subclass of IndexedGeometryArray), if - * <code>texCoordSetCount < 0</code>, or if any element - * in <code>texCoordSetMap[] >= texCoordSetCount</code>. + * <code>texCoordSetCount < 0</code> + * + * @exception IllegalArgumentException if any element in + * <code>texCoordSetMap[] >= texCoordSetCount</code>. * * @since Java 3D 1.2 */ @@ -516,20 +560,196 @@ public abstract class GeometryArray extends Geometry { int vertexFormat, int texCoordSetCount, int[] texCoordSetMap) { + this(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap, 0, null); + } + + + /** + * Constructs an empty GeometryArray object with the specified + * number of vertices, vertex format, number of texture coordinate + * sets, texture coordinate mapping array, vertex attribute count, + * and vertex attribute sizes array. + * + * @param vertexCount the number of vertex elements in this + * GeometryArray<p> + * + * @param vertexFormat a mask indicating which components are + * present in each vertex. This is specified as one or more + * individual flags that are bitwise "OR"ed together to describe + * the per-vertex data. + * The flags include: <code>COORDINATES</code>, to signal the inclusion of + * vertex positions--always present; <code>NORMALS</code>, to signal + * the inclusion of per vertex normals; one of <code>COLOR_3</code> or + * <code>COLOR_4</code>, to signal the inclusion of per vertex + * colors (without or with alpha information); one of + * <code>TEXTURE_COORDINATE_2</code> or <code>TEXTURE_COORDINATE_3</code> + * or <code>TEXTURE_COORDINATE_4</code>, + * to signal the + * inclusion of per-vertex texture coordinates (2D , 3D or 4D); + * <code>VERTEX_ATTRIBUTES</code>, to signal + * the inclusion of one or more arrays of vertex attributes; + * <code>BY_REFERENCE</code>, to indicate that the data is passed + * by reference + * rather than by copying; <code>INTERLEAVED</code>, to indicate + * that the referenced + * data is interleaved in a single array; + * <code>USE_NIO_BUFFER</code>, to indicate that the referenced data + * is accessed via a J3DBuffer object that wraps an NIO buffer; + * <code>USE_COORD_INDEX_ONLY</code>, + * to indicate that only the coordinate indices are used for indexed + * geometry arrays.<p> + * + * @param texCoordSetCount the number of texture coordinate sets + * in this GeometryArray object. If <code>vertexFormat</code> + * does not include one of <code>TEXTURE_COORDINATE_2</code> or + * <code>TEXTURE_COORDINATE_3</code>, the + * <code>texCoordSetCount</code> parameter is not used.<p> + * + * <a name="texCoordSetMap"> + * @param texCoordSetMap an array that maps texture coordinate + * sets to texture units. The array is indexed by texture unit + * number for each texture unit in the associated Appearance + * object. The values in the array specify the texture coordinate + * set within this GeometryArray object that maps to the + * corresponding texture + * unit. All elements within the array must be less than + * <code>texCoordSetCount</code>. A negative value specifies that + * no texture coordinate set maps to the texture unit + * corresponding to the index. If there are more texture units in + * any associated Appearance object than elements in the mapping + * array, the extra elements are assumed to be -1. The same + * texture coordinate set may be used for more than one texture + * unit. Each texture unit in every associated Appearance must + * have a valid source of texture coordinates: either a + * non-negative texture coordinate set must be specified in the + * mapping array or texture coordinate generation must be enabled. + * Texture coordinate generation will take precedence for those + * texture units for which a texture coordinate set is specified + * and texture coordinate generation is enabled. If + * <code>vertexFormat</code> does not include one of + * <code>TEXTURE_COORDINATE_2</code> or + * <code>TEXTURE_COORDINATE_3</code> or + * <code>TEXTURE_COORDINATE_4</code>, the + * <code>texCoordSetMap</code> array is not used. The following example + * illustrates the use of the <code>texCoordSetMap</code> array. + * + * <p> + * <ul> + * <table BORDER=1 CELLSPACING=2 CELLPADDING=2> + * <tr> + * <td><center><b>Index</b></center></td> + * <td><center><b>Element</b></center></td> + * <td><b>Description</b></td> + * </tr> + * <tr> + * <td><center>0</center></td> + * <td><center>1</center></td> + * <td>Use tex coord set 1 for tex unit 0</td> + * </tr> + * <tr> + * <td><center>1</center></td> + * <td><center>-1</center></td> + * <td>Use no tex coord set for tex unit 1</td> + * </tr> + * <tr> + * <td><center>2</center></td> + * <td><center>0</center></td> + * <td>Use tex coord set 0 for tex unit 2</td> + * </tr> + * <tr> + * <td><center>3</center></td> + * <td><center>1</center></td> + * <td>Reuse tex coord set 1 for tex unit 3</td> + * </tr> + * </table> + * </ul> + * <p> + * + * @param vertexAttrCount the number of vertex attributes + * in this GeometryArray object. If <code>vertexFormat</code> + * does not include <code>VERTEX_ATTRIBUTES</code>, the + * <code>vertexAttrCount</code> parameter must be 0.<p> + * + * @param vertexAttrSizes is an array that specifes the size of + * each vertex attribute. Each element in the array specifies the + * number of components in the attribute, from 1 to 4. The length + * of the array must be equal to <code>vertexAttrCount</code>.<p> + * + * @exception IllegalArgumentException if vertexCount < 0 + * + * @exception IllegalArgumentException if vertexFormat does <b>not</b> + * include <code>COORDINATES</code> + * + * @exception IllegalArgumentException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set for non-indexed geometry arrays (that is, GeometryArray objects + * that are not a subclass of IndexedGeometryArray) + * + * @exception IllegalArgumentException if the <code>INTERLEAVED</code> + * bit is set without the <code>BY_REFERENCE</code> bit being set + * + * @exception IllegalArgumentException if the <code>USE_NIO_BUFFER</code> + * bit is set without the <code>BY_REFERENCE</code> bit being set + * + * @exception IllegalArgumentException if the <code>INTERLEAVED</code> + * bit and the <code>VERTEX_ATTRIBUTES</code> bit are both set + * + * @exception IllegalArgumentException if + * <code>texCoordSetCount < 0</code> + * + * @exception IllegalArgumentException if any element in + * <code>texCoordSetMap[] >= texCoordSetCount</code>. + * + * @exception IllegalArgumentException if + * <code>vertexAttrCount > 0</code> and the + * <code>VERTEX_ATTRIBUTES</code> bit is not set + * + * @exception IllegalArgumentException if + * <code>vertexAttrCount < 0</code> + * + * @exception IllegalArgumentException if + * <code>vertexAttrSizes.length != vertexAttrCount</code> + * + * @exception IllegalArgumentException if any element in + * <code>vertexAttrSizes[]</code> is <code>< 1</code> or + * <code>> 4</code>. + * + * @since Java 3D 1.4 + */ + public GeometryArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes) { if (vertexCount < 0) throw new IllegalArgumentException(J3dI18N.getString("GeometryArray96")); + if (texCoordSetCount < 0) + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray124")); + + if (vertexAttrCount < 0) + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray125")); + if ((vertexFormat & COORDINATES) == 0) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray0" -)); + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray0")); if ((vertexFormat & INTERLEAVED) != 0 && (vertexFormat & BY_REFERENCE) == 0) throw new IllegalArgumentException(J3dI18N.getString("GeometryArray80")); + if ((vertexFormat & INTERLEAVED) != 0 && + (vertexFormat & VERTEX_ATTRIBUTES) != 0) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray128")); + } + + if ((vertexFormat & USE_COORD_INDEX_ONLY) != 0 && + !(this instanceof IndexedGeometryArray)) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray135")); + } + if ((vertexFormat & USE_NIO_BUFFER) != 0 && - (vertexFormat & BY_REFERENCE) == 0) + (vertexFormat & BY_REFERENCE) == 0) throw new IllegalArgumentException(J3dI18N.getString("GeometryArray117")); if ((vertexFormat & TEXTURE_COORDINATE) != 0) { @@ -556,8 +776,36 @@ public abstract class GeometryArray extends Geometry { texCoord4fArray = new TexCoord4f[1]; } } - - ((GeometryArrayRetained)this.retained).createGeometryArrayData(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap); + + if ((vertexFormat & VERTEX_ATTRIBUTES) != 0) { + if (vertexAttrCount > 0) { + if (vertexAttrCount != vertexAttrSizes.length) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray132")); + } + + for (int i = 0; i < vertexAttrSizes.length; i++) { + if (vertexAttrSizes[i] < 1 || vertexAttrSizes[i] > 4) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray133")); + } + } + } else { + if (vertexAttrSizes != null && vertexAttrSizes.length != 0) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray132")); + } + } + } else { + if (vertexAttrCount > 0) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray131")); + } + } + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((GeometryArrayRetained)this.retained).createGeometryArrayData( + vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); } @@ -636,7 +884,35 @@ public abstract class GeometryArray extends Geometry { */ public void getTexCoordSetMap(int[] texCoordSetMap) { ((GeometryArrayRetained)this.retained).getTexCoordSetMap(texCoordSetMap); - return; + } + + + /** + * Retrieves the number of vertex attributes in this GeometryArray + * object. + * + * @return the number of vertex attributes in this GeometryArray + * object + * + * @since Java 3D 1.4 + */ + public int getVertexAttrCount() { + return ((GeometryArrayRetained)this.retained).getVertexAttrCount(); + } + + + /** + * Retrieves the vertex attribute sizes array from this + * GeometryArray object. + * + * @param vertexAttrSizes an array that will receive a copy of + * the vertex attribute sizes array. The array must hold at least + * <code>vertexAttrCount</code> elements. + * + * @since Java 3D 1.4 + */ + public void getVertexAttrSizes(int[] vertexAttrSizes) { + ((GeometryArrayRetained)this.retained).getVertexAttrSizes(vertexAttrSizes); } @@ -688,27 +964,30 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if any of the following are * true: * <ul> - * <code>validVertexCount < 0</code>,<br> - * <code>initialVertexIndex + validVertexCount > vertexCount</code>,<br> - * <code>initialCoordIndex + validVertexCount > vertexCount</code>,<br> - * <code>initialColorIndex + validVertexCount > vertexCount</code>,<br> - * <code>initialNormalIndex + validVertexCount > vertexCount</code>,<br> - * <code>initialTexCoordIndex + validVertexCount > vertexCount</code> + * <code>validVertexCount < 0</code>,<br> + * <code>initialVertexIndex + validVertexCount > vertexCount</code>,<br> + * <code>initialCoordIndex + validVertexCount > vertexCount</code>,<br> + * <code>initialColorIndex + validVertexCount > vertexCount</code>,<br> + * <code>initialNormalIndex + validVertexCount > vertexCount</code>,<br> + * <code>initialTexCoordIndex + validVertexCount > vertexCount</code>,<br> + * <code>initialVertexAttrIndex + validVertexCount > vertexCount</code> * </ul> * <p> * @exception ArrayIndexOutOfBoundsException if the geometry data format * is <code>BY_REFERENCE</code> and any the following * are true for non-null array references: * <ul> - * <code>CoordRef.length</code> < <i>num_words</i> * + * <code>CoordRef.length</code> < <i>num_words</i> * * (<code>initialCoordIndex + validVertexCount</code>),<br> - * <code>ColorRef.length</code> < <i>num_words</i> * + * <code>ColorRef.length</code> < <i>num_words</i> * * (<code>initialColorIndex + validVertexCount</code>),<br> - * <code>NormalRef.length</code> < <i>num_words</i> * + * <code>NormalRef.length</code> < <i>num_words</i> * * (<code>initialNormalIndex + validVertexCount</code>),<br> - * <code>TexCoordRef.length</code> < <i>num_words</i> * + * <code>TexCoordRef.length</code> < <i>num_words</i> * * (<code>initialTexCoordIndex + validVertexCount</code>),<br> - * <code>InterleavedVertices.length</code> < <i>words_per_vertex</i> * + * <code>VertexAttrRef.length</code> < <i>num_words</i> * + * (<code>initialVertexAttrIndex + validVertexCount</code>),<br> + * <code>InterleavedVertices.length</code> < <i>words_per_vertex</i> * * (<code>initialVertexIndex + validVertexCount</code>)<br> * </ul> * where <i>num_words</i> depends on which variant of @@ -727,7 +1006,7 @@ public abstract class GeometryArray extends Geometry { throw new IllegalArgumentException(J3dI18N.getString("GeometryArray96")); ((GeometryArrayRetained)this.retained).setValidVertexCount(validVertexCount); - // NOTE: the checks for initial*Index + validVertexCount > + // NOTE: the checks for initial*Index + validVertexCount > // vertexCount need to be done in the retained method } @@ -770,61 +1049,99 @@ public abstract class GeometryArray extends Geometry { * @see NodeComponent#setDuplicateOnCloneTree */ void duplicateAttributes(NodeComponent originalNodeComponent, - boolean forceDuplicate) { - - super.duplicateAttributes(originalNodeComponent, forceDuplicate); - // vertexFormat and vertexCount are copied in subclass when constructor - // public GeometryArray(int vertexCount, int vertexFormat) is used - // in cloneNodeComponent() - GeometryArrayRetained src = (GeometryArrayRetained) originalNodeComponent.retained; - GeometryArrayRetained dst = (GeometryArrayRetained) retained; - int format = src.getVertexFormat(); - if ((format & BY_REFERENCE) == 0) { - System.arraycopy(src.vertexData, 0, dst.vertexData, 0, - src.vertexData.length); - dst.setInitialVertexIndex(src.getInitialVertexIndex()); - - } else { - dst.setInitialCoordIndex(src.getInitialCoordIndex()); - dst.setInitialColorIndex(src.getInitialColorIndex()); - dst.setInitialNormalIndex(src.getInitialNormalIndex()); - int setCount = src.getTexCoordSetCount(); - for (int i=0; i < setCount; i++) { - dst.setInitialTexCoordIndex(i, src.getInitialTexCoordIndex(i)); - } - if ((format & INTERLEAVED) == 0) { - dst.setCoordRefFloat(src.getCoordRefFloat()); - dst.setCoordRefDouble(src.getCoordRefDouble()); - dst.setCoordRef3f(src.getCoordRef3f()); - dst.setCoordRef3d(src.getCoordRef3d()); - dst.setColorRefFloat(src.getColorRefFloat()); - dst.setColorRefByte(src.getColorRefByte()); - if ((format & WITH_ALPHA) == 0) { - dst.setColorRef3f(src.getColorRef3f()); - dst.setColorRef3b(src.getColorRef3b()); - } else { - dst.setColorRef4f(src.getColorRef4f()); - dst.setColorRef4b(src.getColorRef4b()); - } - dst.setNormalRefFloat(src.getNormalRefFloat()); - dst.setNormalRef3f(src.getNormalRef3f()); - for (int i=0; i < setCount; i++) { - dst.setTexCoordRefFloat(i, src.getTexCoordRefFloat(i)); - } - if ((format & TEXTURE_COORDINATE_2) != 0) { - for (int i=0; i < setCount; i++) { - dst.setTexCoordRef2f(i, src.getTexCoordRef2f(i)); - } - } - if ((format & TEXTURE_COORDINATE_3) != 0) { - for (int i=0; i < setCount; i++) { - dst.setTexCoordRef3f(i, src.getTexCoordRef3f(i)); - } - } - } else { - dst.setInterleavedVertices(src.getInterleavedVertices()); - } - } + boolean forceDuplicate) { + + super.duplicateAttributes(originalNodeComponent, forceDuplicate); + // vertexFormat and vertexCount are copied in subclass when constructor + // public GeometryArray(int vertexCount, int vertexFormat) is used + // in cloneNodeComponent() + GeometryArrayRetained src = (GeometryArrayRetained) originalNodeComponent.retained; + GeometryArrayRetained dst = (GeometryArrayRetained) retained; + int format = src.getVertexFormat(); + if ((format & BY_REFERENCE) == 0) { + System.arraycopy(src.vertexData, 0, dst.vertexData, 0, + src.vertexData.length); + dst.setInitialVertexIndex(src.getInitialVertexIndex()); + + } else { + dst.setInitialCoordIndex(src.getInitialCoordIndex()); + dst.setInitialColorIndex(src.getInitialColorIndex()); + dst.setInitialNormalIndex(src.getInitialNormalIndex()); + int setCount = src.getTexCoordSetCount(); + int vAttrCount = src.getVertexAttrCount(); + for (int i=0; i < setCount; i++) { + dst.setInitialTexCoordIndex(i, src.getInitialTexCoordIndex(i)); + } + if ((format & INTERLEAVED) == 0) { + if ((format & USE_NIO_BUFFER) == 0) { + // Java arrays + dst.setCoordRefFloat(src.getCoordRefFloat()); + dst.setCoordRefDouble(src.getCoordRefDouble()); + dst.setCoordRef3f(src.getCoordRef3f()); + dst.setCoordRef3d(src.getCoordRef3d()); + dst.setColorRefFloat(src.getColorRefFloat()); + dst.setColorRefByte(src.getColorRefByte()); + if ((format & WITH_ALPHA) == 0) { + dst.setColorRef3f(src.getColorRef3f()); + dst.setColorRef3b(src.getColorRef3b()); + } else { + dst.setColorRef4f(src.getColorRef4f()); + dst.setColorRef4b(src.getColorRef4b()); + } + dst.setNormalRefFloat(src.getNormalRefFloat()); + dst.setNormalRef3f(src.getNormalRef3f()); + + switch (src.getVertexAttrType()) { + case GeometryArrayRetained.AF: + for (int i=0; i < vAttrCount; i++) { + dst.setVertexAttrRefFloat(i, src.getVertexAttrRefFloat(i)); + } + break; + } + + switch (src.getTexCoordType()) { + case GeometryArrayRetained.TF: + for (int i=0; i < setCount; i++) { + dst.setTexCoordRefFloat(i, src.getTexCoordRefFloat(i)); + } + break; + case GeometryArrayRetained.T2F: + for (int i=0; i < setCount; i++) { + dst.setTexCoordRef2f(i, src.getTexCoordRef2f(i)); + } + break; + case GeometryArrayRetained.T3F: + for (int i=0; i < setCount; i++) { + dst.setTexCoordRef3f(i, src.getTexCoordRef3f(i)); + } + break; + } + } else { + // NIO buffer + dst.setCoordRefBuffer(src.getCoordRefBuffer()); + dst.setColorRefBuffer(src.getColorRefBuffer()); + dst.setNormalRefBuffer(src.getNormalRefBuffer()); + + switch (src.getVertexAttrType()) { + case GeometryArrayRetained.AF: + for (int i=0; i < vAttrCount; i++) { + dst.setVertexAttrRefBuffer(i, src.getVertexAttrRefBuffer(i)); + } + break; + } + + switch (src.getTexCoordType()) { + case GeometryArrayRetained.TF: + for (int i=0; i < setCount; i++) { + dst.setTexCoordRefBuffer(i, src.getTexCoordRefBuffer(i)); + } + break; + } + } + } else { + dst.setInterleavedVertices(src.getInterleavedVertices()); + } + } } @@ -848,15 +1165,15 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if either of the following are * true: * <ul> - * <code>initialVertexIndex < 0</code> or<br> - * <code>initialVertexIndex + validVertexCount > vertexCount</code><br> + * <code>initialVertexIndex < 0</code> or<br> + * <code>initialVertexIndex + validVertexCount > vertexCount</code><br> * </ul> * * @exception ArrayIndexOutOfBoundsException if the geometry data format * is <code>INTERLEAVED</code>, the InterleavedVertices array is * non-null, and: * <ul> - * <code>InterleavedVertices.length</code> < <i>num_words</i> * + * <code>InterleavedVertices.length</code> < <i>num_words</i> * * (<code>initialVertexIndex + validVertexCount</code>)<br> * </ul> * where <i>num_words</i> depends on which vertex formats are enabled. @@ -2271,7 +2588,7 @@ public abstract class GeometryArray extends Geometry { if (((((GeometryArrayRetained)this.retained).vertexFormat) & - (TEXTURE_COORDINATE_2 | TEXTURE_COORDINATE_3)) != 0) + (TEXTURE_COORDINATE_2 | TEXTURE_COORDINATE_4)) != 0) throw new IllegalStateException(J3dI18N.getString("GeometryArray95")); ((GeometryArrayRetained)this.retained).setTextureCoordinates( @@ -2338,7 +2655,7 @@ public abstract class GeometryArray extends Geometry { * * @param index starting destination vertex index in this geometry array * @param texCoords source array of 2*n , 3*n or 4*n values containing - * n new * texture coordinates + * n new texture coordinates * @param start starting source vertex index in <code>texCoords</code> * array. * @param length number of texture Coordinates to be copied. @@ -2531,6 +2848,581 @@ public abstract class GeometryArray extends Geometry { texCoordSet, index, texCoords, start, length); } + + /** + * Sets the vertex attribute associated with the vertex at the + * specified index in the specified vertex attribute number for + * this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index destination vertex index in this geometry array + * @param vertexAttr source array of 1, 2, 3 or 4 values containing + * the new vertex attribute + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range, or if the vertexAttr array is + * too small. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @since Java 3D 1.4 + */ + public void setVertexAttr(int vertexAttrNum, int index, + float[] vertexAttr) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttr, 0, 1); + } + + /** + * Sets the vertex attribute associated with the vertex at the + * specified index in the specified vertex attribute number for + * this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index destination vertex index in this geometry array + * @param vertexAttr the Point2f containing the new vertex attribute + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 2. + * + * @since Java 3D 1.4 + */ + public void setVertexAttr(int vertexAttrNum, int index, + Point2f vertexAttr) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 2) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttr( + vertexAttrNum, index, vertexAttr); + } + + /** + * Sets the vertex attribute associated with the vertex at the + * specified index in the specified vertex attribute number for + * this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index destination vertex index in this geometry array + * @param vertexAttr the Point3f containing the new vertex attribute + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 3. + * + * @since Java 3D 1.4 + */ + public void setVertexAttr(int vertexAttrNum, int index, + Point3f vertexAttr) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 3) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttr( + vertexAttrNum, index, vertexAttr); + } + + /** + * Sets the vertex attribute associated with the vertex at the + * specified index in the specified vertex attribute number for + * this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index destination vertex index in this geometry array + * @param vertexAttr the Point4f containing the new vertex attribute + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 4. + * + * @since Java 3D 1.4 + */ + public void setVertexAttr(int vertexAttrNum, int index, + Point4f vertexAttr) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 4) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttr( + vertexAttrNum, index, vertexAttr); + } + + /** + * Sets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The entire source array is copied to this + * geometry array. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of 1*n, 2*n, 3*n, or 4*n values + * containing n new vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range, or if the vertexAttr array is + * too large. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + float[] vertexAttrs) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, 0, vertexAttrs.length / size); + } + + /** + * Sets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The entire source array is copied to this + * geometry array. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point2f objects containing new + * vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range, or if the vertexAttr array is + * too large. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 2. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + Point2f[] vertexAttrs) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 2) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, 0, vertexAttrs.length); + } + + /** + * Sets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The entire source array is copied to this + * geometry array. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point3f objects containing new + * vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range, or if the vertexAttr array is + * too large. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 3. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + Point3f[] vertexAttrs) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 3) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, 0, vertexAttrs.length); + } + + /** + * Sets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The entire source array is copied to this + * geometry array. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point4f objects containing new + * vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range, or if the vertexAttr array is + * too large. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 4. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + Point4f[] vertexAttrs) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 4) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, 0, vertexAttrs.length); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of 1*n, 2*n, 3*n, or 4*n values + * containing n new vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if any of index, + * (index+length), or vertexAttrNum are out of range, or if + * vertexAttrs is too small. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + float[] vertexAttrs, + int start, int length) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, start, length); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point2f objects containing new + * vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if any of index, + * (index+length), or vertexAttrNum are out of range, or if + * vertexAttrs is too small. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 2. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + Point2f[] vertexAttrs, + int start, int length) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 2) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, start, length); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point3f objects containing new + * vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if any of index, + * (index+length), or vertexAttrNum are out of range, or if + * vertexAttrs is too small. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 3. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + Point3f[] vertexAttrs, + int start, int length) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 3) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, start, length); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point4f objects containing new + * vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if any of index, + * (index+length), or vertexAttrNum are out of range, or if + * vertexAttrs is too small. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 4. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrs(int vertexAttrNum, int index, + Point4f[] vertexAttrs, + int start, int length) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray126")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 4) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrs( + vertexAttrNum, index, vertexAttrs, start, length); + } + + /** * Gets the coordinate associated with the vertex at * the specified index for this object using data in <code>texCoords</code> @@ -3714,6 +4606,384 @@ public abstract class GeometryArray extends Geometry { texCoordSet, index, texCoords); } + /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index source vertex index in this geometry array + * @param vertexAttr array of 1, 2, 3 or 4 values that will receive the + * vertex attribute + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range, or if the vertexAttr array is + * too small. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @since Java 3D 1.4 + */ + public void getVertexAttr(int vertexAttrNum, int index, + float[] vertexAttr) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttr( + vertexAttrNum, index, vertexAttr); + } + + /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index source vertex index in this geometry array + * @param vertexAttr the vector that will receive the vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 2. + * + * @since Java 3D 1.4 + */ + public void getVertexAttr(int vertexAttrNum, int index, + Point2f vertexAttr) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 2) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttr( + vertexAttrNum, index, vertexAttr); + } + + /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index source vertex index in this geometry array + * @param vertexAttr the vector that will receive the vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 3. + * + * @since Java 3D 1.4 + */ + public void getVertexAttr(int vertexAttrNum, int index, + Point3f vertexAttr) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 3) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttr( + vertexAttrNum, index, vertexAttr); + } + + /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index source vertex index in this geometry array + * @param vertexAttr the vector that will receive the vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 4. + * + * @since Java 3D 1.4 + */ + public void getVertexAttr(int vertexAttrNum, int index, + Point4f vertexAttr) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 4) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttr( + vertexAttrNum, index, vertexAttr); + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The length of the destination + * array determines the number of vertex attributes copied. + * A maximum of <code>vertexCount-index</code> vertex attributes + * are copied. If the destination array is larger than is needed + * to hold the vertex attributes, the excess locations in the + * array are not modified. If the destination array is smaller + * than is needed to hold the vertex attributes, only as + * many vertex attributes as the array will hold are copied. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting source vertex index in this geometry array + * @param vertexAttrs destination array of 1*n, 2*n, 3*n, or 4*n values + * that will receive n new vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @since Java 3D 1.4 + */ + public void getVertexAttrs(int vertexAttrNum, int index, + float[] vertexAttrs) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttrs( + vertexAttrNum, index, vertexAttrs); + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The length of the destination + * array determines the number of vertex attributes copied. + * A maximum of <code>vertexCount-index</code> vertex attributes + * are copied. If the destination array is larger than is needed + * to hold the vertex attributes, the excess locations in the + * array are not modified. If the destination array is smaller + * than is needed to hold the vertex attributes, only as + * many vertex attributes as the array will hold are copied. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting source vertex index in this geometry array + * @param vertexAttrs destination array of Point2f objects that will + * receive the vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 2. + * + * @since Java 3D 1.4 + */ + public void getVertexAttrs(int vertexAttrNum, int index, + Point2f[] vertexAttrs) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 2) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttrs( + vertexAttrNum, index, vertexAttrs); + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The length of the destination + * array determines the number of vertex attributes copied. + * A maximum of <code>vertexCount-index</code> vertex attributes + * are copied. If the destination array is larger than is needed + * to hold the vertex attributes, the excess locations in the + * array are not modified. If the destination array is smaller + * than is needed to hold the vertex attributes, only as + * many vertex attributes as the array will hold are copied. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting source vertex index in this geometry array + * @param vertexAttrs destination array of Point3f objects that will + * receive the vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 3. + * + * @since Java 3D 1.4 + */ + public void getVertexAttrs(int vertexAttrNum, int index, + Point3f[] vertexAttrs) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 3) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttrs( + vertexAttrNum, index, vertexAttrs); + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. The length of the destination + * array determines the number of vertex attributes copied. + * A maximum of <code>vertexCount-index</code> vertex attributes + * are copied. If the destination array is larger than is needed + * to hold the vertex attributes, the excess locations in the + * array are not modified. If the destination array is smaller + * than is needed to hold the vertex attributes, only as + * many vertex attributes as the array will hold are copied. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting source vertex index in this geometry array + * @param vertexAttrs destination array of Point4f objects that will + * receive the vertex attributes + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception IllegalStateException if the data mode for this geometry + * array object is <code>BY_REFERENCE</code>. + * + * @exception IllegalStateException if the size of the specified + * vertex attribute number is not 4. + * + * @since Java 3D 1.4 + */ + public void getVertexAttrs(int vertexAttrNum, int index, + Point4f[] vertexAttrs) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_VERTEX_ATTR_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray127")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray82")); + } + + int size = ((GeometryArrayRetained)this.retained).vertexAttrSizes[vertexAttrNum]; + if (size != 4) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray134")); + } + + ((GeometryArrayRetained)this.retained).getVertexAttrs( + vertexAttrNum, index, vertexAttrs); + } + //------------------------------------------------------------------ // By-reference methods @@ -3742,14 +5012,14 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if either of the following are * true: * <ul> - * <code>initialCoordIndex < 0</code> or<br> - * <code>initialCoordIndex + validVertexCount > vertexCount</code><br> + * <code>initialCoordIndex < 0</code> or<br> + * <code>initialCoordIndex + validVertexCount > vertexCount</code><br> * </ul> * <p> * @exception ArrayIndexOutOfBoundsException if * the CoordRef array is non-null and: * <ul> - * <code>CoordRef.length</code> < <i>num_words</i> * + * <code>CoordRef.length</code> < <i>num_words</i> * * (<code>initialCoordIndex + validVertexCount</code>)<br> * </ul> * where <i>num_words</i> depends on which variant of @@ -3820,14 +5090,14 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if either of the following are * true: * <ul> - * <code>initialColorIndex < 0</code> or<br> - * <code>initialColorIndex + validVertexCount > vertexCount</code><br> + * <code>initialColorIndex < 0</code> or<br> + * <code>initialColorIndex + validVertexCount > vertexCount</code><br> * </ul> * <p> * @exception ArrayIndexOutOfBoundsException if * the ColorRef array is non-null and: * <ul> - * <code>ColorRef.length</code> < <i>num_words</i> * + * <code>ColorRef.length</code> < <i>num_words</i> * * (<code>initialColorIndex + validVertexCount</code>)<br> * </ul> * where <i>num_words</i> depends on which variant of @@ -3898,14 +5168,14 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if either of the following are * true: * <ul> - * <code>initialNormalIndex < 0</code> or<br> - * <code>initialNormalIndex + validVertexCount > vertexCount</code><br> + * <code>initialNormalIndex < 0</code> or<br> + * <code>initialNormalIndex + validVertexCount > vertexCount</code><br> * </ul> * <p> * @exception ArrayIndexOutOfBoundsException if normals * the NormalRef array is non-null and: * <ul> - * <code>NormalRef.length</code> < <i>num_words</i> * + * <code>NormalRef.length</code> < <i>num_words</i> * * (<code>initialNormalIndex + validVertexCount</code>)<br> * </ul> * where <i>num_words</i> depends on which variant of @@ -3979,14 +5249,14 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if either of the following are * true: * <ul> - * <code>initialTexCoordIndex < 0</code> or<br> - * <code>initialTexCoordIndex + validVertexCount > vertexCount</code><br> + * <code>initialTexCoordIndex < 0</code> or<br> + * <code>initialTexCoordIndex + validVertexCount > vertexCount</code><br> * </ul> * <p> * @exception ArrayIndexOutOfBoundsException if * the TexCoordRef array is non-null and: * <ul> - * <code>TexCoordRef.length</code> < <i>num_words</i> * + * <code>TexCoordRef.length</code> < <i>num_words</i> * * (<code>initialTexCoordIndex + validVertexCount</code>)<br> * </ul> * where <i>num_words</i> depends on which variant of @@ -4054,6 +5324,109 @@ public abstract class GeometryArray extends Geometry { /** + * Sets the initial vertex attribute index for the specified + * vertex attribute number for this GeometryArray object. This + * index specifies the first vertex attribute within the array + * of vertex attributes referenced by this geometry array that + * is actually used in rendering or other operations such as + * picking and collision. This attribute is initialized to 0. + * This attribute is only used when the data mode for this + * geometry array object is <code>BY_REFERENCE</code> + * and is <i>not</i> </code>INTERLEAVED</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param initialVertexAttrIndex the new initial vertex attribute index. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * <p> + * @exception IllegalStateException if the data mode for this geometry + * array object is not <code>BY_REFERENCE</code> or if the data mode + * is <code>INTERLEAVED</code>. + * <p> + * @exception IllegalArgumentException if either of the following are + * true: + * <ul> + * <code>initialVertexAttrIndex < 0</code> or<br> + * <code>initialVertexAttrIndex + validVertexCount > vertexCount</code><br> + * </ul> + * <p> + * @exception ArrayIndexOutOfBoundsException if + * the VertexAttrRef array is non-null and: + * <ul> + * <code>VertexAttrRef.length</code> < <i>num_words</i> * + * (<code>initialVertexAttrIndex + validVertexCount</code>)<br> + * </ul> + * where <i>num_words</i> is the size of the specified + * vertexAttrNum (1, 2, 3, or 4). + * <p> + * @exception ArrayIndexOutOfBoundsException if vertexAttrNum is + * out of range. + * + * @since Java 3D 1.4 + */ + public void setInitialVertexAttrIndex(int vertexAttrNum, + int initialVertexAttrIndex) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_COUNT_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray90")); + } + } + + if (initialVertexAttrIndex < 0) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray97")); + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) == 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray83")); + } + + if ((format & INTERLEAVED) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray84")); + } + + ((GeometryArrayRetained)this.retained).setInitialVertexAttrIndex( + vertexAttrNum, initialVertexAttrIndex); + + // NOTE: the check for initialVertexAttrIndex + validVertexCount > + // vertexCount needs to be done in the retained method + } + + + /** + * Gets the initial vertex attribute index for the specified + * vertex attribute number for this GeometryArray object. + * This attribute is only used when the data mode for this + * geometry array object is <code>BY_REFERENCE</code> + * and is <i>not</i> </code>INTERLEAVED</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * + * @return the current initial vertex attribute index for the specified + * vertex attribute number + * + * @exception ArrayIndexOutOfBoundsException if vertexAttrNum is + * out of range. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public int getInitialVertexAttrIndex(int vertexAttrNum) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_COUNT_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray91")); + } + } + + return ((GeometryArrayRetained)this.retained).getInitialVertexAttrIndex( + vertexAttrNum); + } + + + /** * Sets the coordinate buffer reference to the specified * buffer object. The buffer contains either a java.nio.FloatBuffer * or java.nio.DoubleBuffer object containing single or double @@ -4081,7 +5454,7 @@ public abstract class GeometryArray extends Geometry { * java.nio.FloatBuffer or a java.nio.DoubleBuffer object. * * @exception ArrayIndexOutOfBoundsException if - * <code>coords.getBuffer().limit() < + * <code>coords.getBuffer().limit() < * 3 * (initialCoordIndex + validVertexCount)</code>. * * @exception ArrayIndexOutOfBoundsException if this GeometryArray @@ -4164,7 +5537,7 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if the specified array is * non-null and any other coordinate reference is also non-null. * @exception ArrayIndexOutOfBoundsException if - * <code>coords.length < 3 * (initialCoordIndex + validVertexCount)</code>. + * <code>coords.length < 3 * (initialCoordIndex + validVertexCount)</code>. * * @exception ArrayIndexOutOfBoundsException if this GeometryArray * object is a subclass of IndexedGeometryArray, and any element @@ -4253,7 +5626,7 @@ public abstract class GeometryArray extends Geometry { * @exception IllegalArgumentException if the specified array is * non-null and any other coordinate reference is also non-null. * @exception ArrayIndexOutOfBoundsException if - * <code>coords.length < 3 * (initialCoordIndex + validVertexCount)</code>. + * <code>coords.length < 3 * (initialCoordIndex + validVertexCount)</code>. * * @exception ArrayIndexOutOfBoundsException if this GeometryArray * object is a subclass of IndexedGeometryArray, and any element @@ -4456,7 +5829,7 @@ public abstract class GeometryArray extends Geometry { * @exception ArrayIndexOutOfBoundsException if none of the * <code>COLOR</code> bits are set in the * <code>vertexFormat</code>, or if - * <code>colors.getBuffer().limit() < </code> <i>num_words</i> <code> * + * <code>colors.getBuffer().limit() < </code> <i>num_words</i> <code> * * (initialColorIndex + validVertexCount)</code>, * where <i>num_words</i> is 3 or 4 depending on the vertex color format. * @@ -4549,7 +5922,7 @@ public abstract class GeometryArray extends Geometry { * @exception ArrayIndexOutOfBoundsException if none of the * <code>COLOR</code> bits are set in the * <code>vertexFormat</code>, or if - * <code>colors.length < </code> <i>num_words</i> <code> * + * <code>colors.length < </code> <i>num_words</i> <code> * * (initialColorIndex + validVertexCount)</code>, * where <i>num_words</i> is 3 or 4 depending on the vertex color format. * @@ -4646,7 +6019,7 @@ public abstract class GeometryArray extends Geometry { * @exception ArrayIndexOutOfBoundsException if none of the * <code>COLOR</code> bits are set in the * <code>vertexFormat</code>, or if - * <code>colors.length < </code> <i>num_words</i> <code> * + * <code>colors.length < </code> <i>num_words</i> <code> * * (initialColorIndex + validVertexCount)</code>, * where <i>num_words</i> is 3 or 4 depending on the vertex color format. * @@ -4978,7 +6351,7 @@ public abstract class GeometryArray extends Geometry { * @exception ArrayIndexOutOfBoundsException if * <code>NORMALS</code> bit is not set in the * <code>vertexFormat</code>, or if - * <code>normals.getBuffer().limit() < + * <code>normals.getBuffer().limit() < * 3 * (initialNormalIndex + validVertexCount)</code>. * * @exception ArrayIndexOutOfBoundsException if this GeometryArray @@ -5064,7 +6437,7 @@ public abstract class GeometryArray extends Geometry { * @exception ArrayIndexOutOfBoundsException if * <code>NORMALS</code> bit is not set in the * <code>vertexFormat</code>, or if - * <code>normals.length < 3 * (initialNormalIndex + validVertexCount)</code>. + * <code>normals.length < 3 * (initialNormalIndex + validVertexCount)</code>. * * @exception ArrayIndexOutOfBoundsException if this GeometryArray * object is a subclass of IndexedGeometryArray, and any element @@ -5186,7 +6559,7 @@ public abstract class GeometryArray extends Geometry { /** - * Sets the texture coordinate array reference for the specified + * Sets the texture coordinate buffer reference for the specified * texture coordinate set to the * specified buffer object. The buffer contains a java.nio.FloatBuffer * object containing <i>s</i>, @@ -5223,7 +6596,7 @@ public abstract class GeometryArray extends Geometry { * <code>TEXTURE_COORDINATE</code> bits are set in the * <code>vertexFormat</code>, or if texCoordSet is out of range, * or if - * <code>texCoords.getBuffer().limit() < </code> <i>num_words</i> + * <code>texCoords.getBuffer().limit() < </code> <i>num_words</i> * <code> * (initialTexCoordIndex + validVertexCount)</code>, * where <i>num_words</i> is 2, 3, or 4 depending on the vertex * texture coordinate format. @@ -5336,7 +6709,7 @@ public abstract class GeometryArray extends Geometry { * <code>TEXTURE_COORDINATE</code> bits are set in the * <code>vertexFormat</code>, or if texCoordSet is out of range, * or if - * <code>texCoords.length < </code> <i>num_words</i> <code> * + * <code>texCoords.length < </code> <i>num_words</i> <code> * * (initialTexCoordIndex + validVertexCount)</code>, * where <i>num_words</i> is 2, 3, or 4 depending on the vertex * texture coordinate format. @@ -5543,11 +6916,265 @@ public abstract class GeometryArray extends Geometry { texCoordSet); } + + /** + * Sets the vertex attribute buffer reference for the specified + * vertex attribute number to the specified buffer object. The + * buffer contains a java.nio.FloatBuffer object containing 1, 2, + * 3, or 4 values for each vertex (for a total of 1*<i>n</i>, + * 2*<i>n</i>, 3*<i>n</i>, or 4*<i>n</i> values, where <i>n</i> is + * the number of vertices). + * If the vertexAttr buffer reference is null and vertex + * attributes are enabled (that is, the vertexFormat includes + * <code>VERTEX_ATTRIBUTES</code>), the entire geometry array + * object is treated as if it were null--any Shape3D node that + * uses this geometry array will not be drawn. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * + * @param vertexAttrs a J3DBuffer object to which a reference will + * be set. The buffer contains an NIO buffer of 1*<i>n</i>, + * 2*<i>n</i>, 3*<i>n</i>, or 4*<i>n</i> float values. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception IllegalStateException if the data mode for this geometry + * array object is not <code>BY_REFERENCE</code>, + * is not <code>USE_NIO_BUFFER</code>, or is <code>INTERLEAVED</code>. + * + * @exception IllegalArgumentException if the java.nio.Buffer + * contained in the specified J3DBuffer is not a + * java.nio.FloatBuffer object. + * + * @exception ArrayIndexOutOfBoundsException if vertexAttrNum is out of + * range, or if + * <code>vertexAttrs.getBuffer().limit() < </code> <i>num_words</i> + * <code> * (initialVertexAttrIndex + validVertexCount)</code>, + * where <i>num_words</i> is the size of the specified + * vertexAttrNum (1, 2, 3, or 4). + * + * @exception ArrayIndexOutOfBoundsException if this GeometryArray + * object is a subclass of IndexedGeometryArray, and any element + * in the range + * <code>[initialIndexIndex, initialIndexIndex+validIndexCount-1]</code> + * in the vertex attribute index array is greater than or equal to the + * number of vertices defined by the vertexAttrs object, + * <code>vertexAttrs.getBuffer().limit() / </code> <i>num_words</i>. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrRefBuffer(int vertexAttrNum, J3DBuffer vertexAttrs) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_REF_DATA_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray86")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + + if ((format & USE_NIO_BUFFER) == 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray118")); + } + + if ((format & INTERLEAVED) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray84")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrRefBuffer( + vertexAttrNum, vertexAttrs); + } + + + /** + * Gets the vertex attribute array buffer reference for the specified + * vertex attribute number. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * + * @return the current vertex attribute array buffer reference + * for the specified vertex attribute number + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception IllegalStateException if the data mode for this geometry + * array object is not <code>BY_REFERENCE</code>, + * is not <code>USE_NIO_BUFFER</code>, or is <code>INTERLEAVED</code>. + * + * @exception ArrayIndexOutOfBoundsException if vertexAttrNum is out + * of range. + * + * @since Java 3D 1.4 + */ + public J3DBuffer getVertexAttrRefBuffer(int vertexAttrNum) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_REF_DATA_READ) && + !this.getCapability(J3D_1_2_ALLOW_REF_DATA_READ)) { + + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray87")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + + if ((format & USE_NIO_BUFFER) == 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray118")); + } + + if ((format & INTERLEAVED) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray84")); + } + + return ((GeometryArrayRetained)this.retained).getVertexAttrRefBuffer(vertexAttrNum); + } + + + /* + * XXXX: add the following to the javadoc if we ever add double-precision + * methods for vertex attribtues. + * + *----------------------------------------------------------------- + * Only one of <code>vertexAttrRefFloat</code>, or + * <code>vertexAttrRefDouble</code> may be non-null (or they may + * all be null). An attempt to set more than one of these + * attributes to a non-null reference will result in an exception + * being thrown. + * + * If all vertexAttr array references are null and vertex + * ... + * @exception IllegalArgumentException if the specified array is + * non-null and any other vertexAttr reference is also non-null. + * ... + *----------------------------------------------------------------- + */ + + /** + * Sets the float vertex attribute array reference for the + * specified vertex attribute number to the specified array. The + * array contains 1, 2, 3, or 4 floating-point values for each + * vertex (for a total of 1*<i>n</i>, 2*<i>n</i>, 3*<i>n</i>, or + * 4*<i>n</i> values, where <i>n</i> is the number of vertices). + * + * If the vertexAttr array reference is null and vertex + * attributes are enabled (that is, the vertexFormat includes + * <code>VERTEX_ATTRIBUTES</code>), the entire geometry array + * object is treated as if it were null--any Shape3D node that + * uses this geometry array will not be drawn. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * + * @param vertexAttrs an array of 1*<i>n</i>, 2*<i>n</i>, + * 3*<i>n</i>, or 4*<i>n</i> values to which a reference will be + * set. + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * @exception IllegalStateException if the data mode for this geometry + * array object is not <code>BY_REFERENCE</code>, + * is <code>USE_NIO_BUFFER</code>, or is <code>INTERLEAVED</code>. + * + * @exception ArrayIndexOutOfBoundsException if vertexAttrNum is + * out of range, or if + * <code>vertexAttrs.length < </code> <i>num_words</i> <code> * + * (initialVertexAttrIndex + validVertexCount)</code>, + * where <i>num_words</i> is the size of the specified + * vertexAttrNum (1, 2, 3, or 4). + * + * @exception ArrayIndexOutOfBoundsException if this GeometryArray + * object is a subclass of IndexedGeometryArray, and any element + * in the range + * <code>[initialIndexIndex, initialIndexIndex+validIndexCount-1]</code> + * in the vertex attribute index array is greater than or equal to the + * number of vertices defined by the vertexAttrs array, + * <code>vertexAttrs.length / </code> <i>num_words</i>. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrRefFloat(int vertexAttrNum, float[] vertexAttrs) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_REF_DATA_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray86")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) == 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray83")); + } + + if ((format & USE_NIO_BUFFER) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray119")); + } + + if ((format & INTERLEAVED) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray84")); + } + + ((GeometryArrayRetained)this.retained).setVertexAttrRefFloat( + vertexAttrNum, vertexAttrs); + + // NOTE: the checks for multiple non-null references, and the + // array length check need to be done in the retained method + } + + + /** + * Gets the float vertex attribute array reference for the specified + * vertex attribute number. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * + * @return the current float vertex attribute array reference + * for the specified vertex attribute number + * + * @exception CapabilityNotSetException if the appropriate capability is + * not set and this object is part of a live or compiled scene graph + * + * @exception IllegalStateException if the data mode for this geometry + * array object is not <code>BY_REFERENCE</code>, + * is <code>USE_NIO_BUFFER</code>, or is <code>INTERLEAVED</code>. + * + * @exception ArrayIndexOutOfBoundsException if vertexAttrNum is + * out of range. + * + * @since Java 3D 1.4 + */ + public float[] getVertexAttrRefFloat(int vertexAttrNum) { + + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_REF_DATA_READ) && + !this.getCapability(J3D_1_2_ALLOW_REF_DATA_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("GeometryArray87")); + } + } + + int format = ((GeometryArrayRetained)this.retained).vertexFormat; + if ((format & BY_REFERENCE) == 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray83")); + } + + if ((format & USE_NIO_BUFFER) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray119")); + } + + if ((format & INTERLEAVED) != 0) { + throw new IllegalStateException(J3dI18N.getString("GeometryArray84")); + } + + return ((GeometryArrayRetained)this.retained).getVertexAttrRefFloat( + vertexAttrNum); + } + + /** * Sets the interleaved vertex array reference to the specified * array. The vertex components must be stored in a predetermined * order in the array. The order is: texture coordinates, colors, - * normals, and positional coordinates. In the case of texture + * normals, and positional coordinates. + * Vertex attributes are not supported in interleaved mode. + * In the case of texture * coordinates, the values for each texture coordinate set * are stored in order from 0 through texCoordSetCount-1. Only those * components that are enabled appear in the vertex. The number @@ -5584,7 +7211,7 @@ public abstract class GeometryArray extends Geometry { * or is <code>USE_NIO_BUFFER</code>. * * @exception ArrayIndexOutOfBoundsException if - * <code>vertexData.length</code> < <i>words_per_vertex</i> * + * <code>vertexData.length</code> < <i>words_per_vertex</i> * * (<code>initialVertexIndex + validVertexCount</code>), * where <i>words_per_vertex</i> depends on which formats are enabled. * @@ -5652,7 +7279,9 @@ public abstract class GeometryArray extends Geometry { * buffer object. The buffer must contain a java.nio.FloatBuffer object. * The vertex components must be stored in a predetermined * order in the buffer. The order is: texture coordinates, colors, - * normals, and positional coordinates. In the case of texture + * normals, and positional coordinates. + * Vertex attributes are not supported in interleaved mode. + * In the case of texture * coordinates, the values for each texture coordinate set * are stored in order from 0 through texCoordSetCount-1. Only those * components that are enabled appear in the vertex. The number @@ -5696,7 +7325,7 @@ public abstract class GeometryArray extends Geometry { * java.nio.FloatBuffer object. * * @exception ArrayIndexOutOfBoundsException if - * <code>vertexData.getBuffer().limit()</code> < <i>words_per_vertex</i> * + * <code>vertexData.getBuffer().limit()</code> < <i>words_per_vertex</i> * * (<code>initialVertexIndex + validVertexCount</code>), * where <i>words_per_vertex</i> depends on which formats are enabled. * diff --git a/src/classes/share/javax/media/j3d/GeometryArrayRetained.java b/src/classes/share/javax/media/j3d/GeometryArrayRetained.java index fce41cd..dcc380c 100644 --- a/src/classes/share/javax/media/j3d/GeometryArrayRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryArrayRetained.java @@ -36,9 +36,7 @@ import com.sun.j3d.internal.DoubleBufferWrapper; abstract class GeometryArrayRetained extends GeometryRetained{ - - - // TODO: Memory footprint reduction. Should have separate object to + // XXXX: Memory footprint reduction. Should have separate object to // to contain specific data such as a ByRef object for // all ByRef related data. So that incases where no // ByRef is needed, the ByRef object reference is @@ -89,6 +87,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // Offset (in words) within each vertex of the texture coordinate int textureOffset; + // Offset (in words) within each vertex of each vertex attribute + int[] vertexAttrOffsets; + + // Stride (size) of all vertex attributes + int vertexAttrStride; + // alpha value for transparency and texture blending float[] lastAlpha = new float[1]; float lastScreenAlpha = -1; @@ -132,7 +136,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ int initialCoordIndex = 0; int initialColorIndex = 0; int initialNormalIndex = 0; - int initialTexCoordIndex[] = null; + int[] initialTexCoordIndex = null; + int[] initialVertexAttrIndex = null; int initialVertexIndex = 0; @@ -174,6 +179,19 @@ abstract class GeometryArrayRetained extends GeometryRetained{ static final int T2F = 0x2000; static final int T3F = 0x4000; static final int TEXCOORD_DEFINED = TF | T2F | T3F; + + static final int AF = 0x8000; + static final int VATTR_DEFINED = AF; + + // Flag word indicating the type of by-ref texCoord. We will copy this to + // the vertexType field only when the references for all texture coordinate + // sets are set to non-null values. + private int texCoordType = 0; + + // Flag word indicating the type of by-ref vertex attr. We will copy this to + // the vertexType field only when the references for all vertex attrs + // are set to non-null values. + private int vertexAttrType = 0; // flag for execute geometry array when by reference static final int COORD_FLOAT = 0x01; @@ -181,9 +199,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ static final int COLOR_FLOAT = 0x04; static final int COLOR_BYTE = 0x08; static final int NORMAL_FLOAT = 0x10; - static final int TEXCOORD_FLOAT = 0x20; - - + static final int TEXCOORD_FLOAT = 0x20; + static final int VATTR_FLOAT = 0x40; + + // used by "by reference" normals float[] floatRefNormals = null; Vector3f[] v3fRefNormals = null; @@ -192,6 +211,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ J3DBuffer normalRefBuffer = null; FloatBufferWrapper floatBufferRefNormals = null; + // used for "by reference" vertex attrs + float[][] floatRefVertexAttrs = null; + + // Used for NIO buffer vertex attrs + J3DBuffer[] vertexAttrsRefBuffer = null; + FloatBufferWrapper[] floatBufferRefVertexAttrs = null; + Object[] nioFloatBufferRefVertexAttrs = null; // used by "by reference" tex coords Object[] refTexCoords = null; @@ -212,10 +238,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // pointers used, when transparency is turned on // or when its an object such as C3F, P3F etc .. - // TODO: Update this for J3DBuffer float[] mirrorFloatRefCoords = null; double[] mirrorDoubleRefCoords = null; float[] mirrorFloatRefNormals = null; + float[][] mirrorFloatRefVertexAttrs = null; float[] mirrorFloatRefTexCoords = null; Object[] mirrorRefTexCoords = null; @@ -223,14 +249,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ byte[][] mirrorUnsignedByteRefColors= new byte[1][]; float[][] mirrorInterleavedColorPointer = null; - // This native method builds a native representation of this object, then - // returns the nativeId. - native int build(int geoType); - // boolean to determine if a mirror was allocated int mirrorVertexAllocated = 0; int mirrorColorAllocated = 0; - boolean mirrorTexCoordAllocated = false; boolean mirrorNormalAllocated = false; // Some dirty bits for GeometryArrays @@ -240,12 +261,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ static final int TEXTURE_CHANGED = 0x08; static final int BOUNDS_CHANGED = 0x10; static final int INDEX_CHANGED = 0x20; - static final int STRIPCOUNT_CHANGED = 0x40; + static final int STRIPCOUNT_CHANGED = 0x40; + static final int VATTR_CHANGED = 0x80; static final int VERTEX_CHANGED = COORDINATE_CHANGED | NORMAL_CHANGED | COLOR_CHANGED | - TEXTURE_CHANGED; - + TEXTURE_CHANGED | + VATTR_CHANGED; static final int defaultTexCoordSetMap[] = {0}; int texCoordSetCount = 0; @@ -255,6 +277,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // texture unit. -1 means no corresponding texCoord data offset int [] texCoordSetMapOffset = null; + // Vertex attribute information + int vertexAttrCount = 0; + int[] vertexAttrSizes = null; + + // This point to a list of VertexBuffers in a Vector structure // Each element correspond to a D3D context that create this VB. // Note that this GeometryArray can be used by multiple ctx. @@ -936,26 +963,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } - // TODO: may not need this function in NIO buffer version - // setup mirror vertex pointers for J3DBuffer version - void setupMirrorVertexPointerNIOBuffer(int vType) { - int i, index = 0; - switch(vType) { - case PF: - - break; - case PD: - - break; - - // do not need to handle P3F and P3D case in NIO buffer version - default: - break; - - } - - } - // If turned transparent the first time, then force it to allocate void setupMirrorInterleavedColorPointer(boolean force) { int index, length, offset; @@ -1266,7 +1273,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ vertexType |= CF; vertexType &= ~CUB; if (c4fAllocated == 0 && !force) { - // TODO: make suren mirrorFloatRefColors[0] is set right + // NOTE: make suren mirrorFloatRefColors[0] is set right mirrorFloatRefColors[0] = null; mirrorColorAllocated &= ~CF; } @@ -1302,7 +1309,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ vertexType |= CUB; vertexType &= ~CF; if (c4fAllocated == 0 && !force) { - // TODO: make suren mirrorUnsignedByteRefColors[0] is set right + // NOTE: make sure mirrorUnsignedByteRefColors[0] is set right mirrorUnsignedByteRefColors[0] = null; mirrorColorAllocated &= ~CUB;; } @@ -1387,42 +1394,58 @@ abstract class GeometryArrayRetained extends GeometryRetained{ void setupMirrorTexCoordPointer(int type) { for (int i = 0; i < texCoordSetCount; i++) { - setupMirrorTexCoordPointer(i, type); + doSetupMirrorTexCoordPointer(i, type); } - } + validateTexCoordPointerType(); + } + void setupMirrorTexCoordPointer(int texCoordSet, int type) { - int i, index; + doSetupMirrorTexCoordPointer(texCoordSet, type); + validateTexCoordPointerType(); + } + + // If all texCoord pointers are set to a non-null value, then set the + // texcoord type in the vertexType flag word, else clear the texcoord type + private void validateTexCoordPointerType() { + boolean allNonNull = true; + boolean allNull = true; + for (int i = 0; i < texCoordSetCount; i++) { + if (refTexCoords[i] == null) { + allNonNull = false; + } else { + allNull = false; + } + } - if (mirrorRefTexCoords == null) - mirrorRefTexCoords = new Object[texCoordSetCount]; + // Reset texCoordType if all references are null + if (allNull) { + texCoordType = 0; + } - switch (type) { - case TF: - if (refTexCoords[texCoordSet] == null) { - if ((vertexType & TEXCOORD_DEFINED) == TF) { - vertexType &= ~TF; - mirrorRefTexCoords[texCoordSet] = null; - mirrorTexCoordAllocated = false; - } - } - else { - vertexType |= TF; - mirrorRefTexCoords[texCoordSet] = refTexCoords[texCoordSet]; - mirrorTexCoordAllocated = false; - } + // Copy texCoordType to vertexType if all references are non-null + vertexType &= ~TEXCOORD_DEFINED; + if (allNonNull) { + vertexType |= texCoordType; + } + } + + private void doSetupMirrorTexCoordPointer(int texCoordSet, int type) { + int i, index; + + switch (type) { + case TF: + texCoordType = TF; + mirrorRefTexCoords[texCoordSet] = refTexCoords[texCoordSet]; break; - case T2F: + + case T2F: + texCoordType = T2F; t2fRefTexCoords = (TexCoord2f[])refTexCoords[texCoordSet]; if (t2fRefTexCoords == null) { - if ((vertexType & TEXCOORD_DEFINED) == T2F) { - vertexType &= ~T2F; - } - return; - } - else { - vertexType |= T2F; + mirrorRefTexCoords[texCoordSet] = null; + break; } mirrorFloatRefTexCoords = (float[])mirrorRefTexCoords[texCoordSet]; @@ -1441,19 +1464,15 @@ abstract class GeometryArrayRetained extends GeometryRetained{ mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].x; mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].y; } - mirrorTexCoordAllocated = true; break; - case T3F: + case T3F: + texCoordType = T3F; t3fRefTexCoords = (TexCoord3f[])refTexCoords[texCoordSet]; - if (t3fRefTexCoords == null) { - if ((vertexType & TEXCOORD_DEFINED) == T3F) { - vertexType &= ~T3F; - } - return; - } - else { - vertexType |= T3F; + + if (t3fRefTexCoords == null) { + mirrorRefTexCoords[texCoordSet] = null; + break; } mirrorFloatRefTexCoords = (float[])mirrorRefTexCoords[texCoordSet]; @@ -1473,142 +1492,240 @@ abstract class GeometryArrayRetained extends GeometryRetained{ mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].y; mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].z; } - mirrorTexCoordAllocated = true; break; default: break; } } - - void createGeometryArrayData(int vertexCount, int vertexFormat) - { + void setupMirrorVertexAttrPointer(int type) { + for (int i = 0; i < vertexAttrCount; i++) { + doSetupMirrorVertexAttrPointer(i, type); + } + + validateVertexAttrPointerType(); + } + + void setupMirrorVertexAttrPointer(int vertexAttrNum, int type) { + doSetupMirrorVertexAttrPointer(vertexAttrNum, type); + validateVertexAttrPointerType(); + } + + // If all vertex attr pointers are set to a non-null value, then set the + // vertex attr type in the vertexType flag word, else clear the + // vertex attr type + private void validateVertexAttrPointerType() { + boolean allNonNull = true; + boolean allNull = true; + + if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) { + for (int i = 0; i < vertexAttrCount; i++) { + if (floatRefVertexAttrs[i] == null) { + allNonNull = false; + } else { + allNull = false; + } + } + } else { + for (int i = 0; i < vertexAttrCount; i++) { + if (nioFloatBufferRefVertexAttrs[i] == null) { + allNonNull = false; + } else { + allNull = false; + } + } + } + + // Reset vertexAttrType if all references are null + if (allNull) { + vertexAttrType = 0; + } + + // Copy vertexAttrType to vertexType if all references are non-null + vertexType &= ~VATTR_DEFINED; + if (allNonNull) { + vertexType |= vertexAttrType; + } + } + + private void doSetupMirrorVertexAttrPointer(int vertexAttrNum, int type) { + switch (type) { + case AF: + vertexAttrType = AF; + mirrorFloatRefVertexAttrs[vertexAttrNum] = + floatRefVertexAttrs[vertexAttrNum]; + break; + default: + break; + } + } + + + void createGeometryArrayData(int vertexCount, int vertexFormat) { if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { createGeometryArrayData(vertexCount, vertexFormat, 1, - defaultTexCoordSetMap); + defaultTexCoordSetMap); } else { createGeometryArrayData(vertexCount, vertexFormat, 0, null); } } void createGeometryArrayData(int vertexCount, int vertexFormat, - int texCoordSetCount, int[] texCoordSetMap) - { + int texCoordSetCount, int[] texCoordSetMap) { + + createGeometryArrayData(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + 0, null); + } + + void createGeometryArrayData(int vertexCount, int vertexFormat, + int texCoordSetCount, int[] texCoordSetMap, + int vertexAttrCount, int[] vertexAttrSizes) { this.vertexFormat = vertexFormat; this.vertexCount = vertexCount; this.validVertexCount = vertexCount; + this.texCoordSetCount = texCoordSetCount; - this.texCoordSetMap = texCoordSetMap; + if (texCoordSetMap == null) { + this.texCoordSetMap = null; + } + else { + this.texCoordSetMap = (int[])texCoordSetMap.clone(); + } + + this.vertexAttrCount = vertexAttrCount; + if (vertexAttrSizes == null) { + this.vertexAttrSizes = null; + } + else { + this.vertexAttrSizes = (int[])vertexAttrSizes.clone(); + } + + this.vertexAttrStride = this.vertexAttrStride(); this.stride = this.stride(); + + this.vertexAttrOffsets = this.vertexAttrOffsets(); this.texCoordSetMapOffset = this.texCoordSetMapOffset(); - this.textureOffset = 0; + this.textureOffset = this.textureOffset(); this.colorOffset = this.colorOffset(); this.normalOffset = this.normalOffset(); this.coordinateOffset = this.coordinateOffset(); + if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { this.vertexData = new float[this.vertexCount * this.stride]; } else { // By reference geometry this.vertexData = null; if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + this.mirrorRefTexCoords = new Object[texCoordSetCount]; this.refTexCoords = new Object[texCoordSetCount]; // keep J3DBufferImp object in nio buffer case if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0 ) this.refTexCoordsBuffer = new Object[texCoordSetCount]; // keep J3DBuffer object } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + this.floatRefVertexAttrs = new float[vertexAttrCount][]; + this.mirrorFloatRefVertexAttrs = new float[vertexAttrCount][]; + if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { + this.vertexAttrsRefBuffer = new J3DBuffer[vertexAttrCount]; + this.floatBufferRefVertexAttrs = new FloatBufferWrapper[vertexAttrCount]; + this.nioFloatBufferRefVertexAttrs = new Object[vertexAttrCount]; + } + } } if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { this.initialTexCoordIndex = new int[texCoordSetCount]; } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + this.initialVertexAttrIndex = new int[vertexAttrCount]; + } noAlpha = ((vertexFormat & GeometryArray.WITH_ALPHA) == 0); lastAlpha[0] = 1.0f; } // used for GeometryArrays by Copy or interleaved - native void execute(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int startVIndex, int vcount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - float[] varray, float[] cdata, int texUnitIndex, int cdirty); - - - + private native void execute(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean multiScreen, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int texCoordSetMap[], + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int[] texUnitStateMap, + int vertexAttrCount, int[] vertexAttrSizes, + float[] varray, float[] cdata, int texUnitIndex, int cdirty); // used by GeometryArray by Reference with java arrays - native void executeVA(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, float[] vfcoords, double[] vdcoords, - int colorIndex, float[] cfdata, byte[] cbdata, - int normalIndex, float[] ndata, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int[] texIndex, int texstride, Object[] texCoords, - int cdirty); - - + private native void executeVA(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean multiScreen, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int pass, int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, int[] texunitstatemap, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty); // used by GeometryArray by Reference with NIO buffer - native void executeVABuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, - Object vcoords, - int colorIndex, - Object cdataBuffer, - float[] cfdata, byte[] cbdata, - int normalIndex, Object ndata, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int[] texIndex, int texstride, Object[] texCoords, - int cdirty); + private native void executeVABuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean multiScreen, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, + Object vcoords, + int colorIndex, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + int normalIndex, Object ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, Object[] vertexAttrData, + int pass, int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, int[] texunitstatemap, + int[] texIndex, int texstride, Object[] texCoords, + int cdirty); // used by GeometryArray by Reference in interleaved format with NIO buffer - native void executeInterleavedBuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int startVIndex, int vcount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - Object varray, float[] cdata, int texUnitIndex, int cdirty); - - - - native void setVertexFormat(int vformat, boolean useAlpha, - boolean ignoreVertexColors, long ctx); - native void disableGlobalAlpha(long ctx, int vformat, - boolean useAlpha, - boolean ignoreVertexColors); + private native void executeInterleavedBuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean multiScreen, + boolean ignoreVertexColors, + int startVIndex, int vcount, int vformat, + int texCoordSetCount, int texCoordSetMap[], + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int[] texUnitStateMap, + Object varray, float[] cdata, int texUnitIndex, int cdirty); + + private native void setVertexFormat(long ctx, + int vformat, boolean useAlpha, boolean ignoreVertexColors); + + private native void disableGlobalAlpha(long ctx, int vformat, + boolean useAlpha, boolean ignoreVertexColors); void setVertexFormat(boolean useAlpha, boolean ignoreVC, long ctx) { - setVertexFormat(vertexFormat, useAlpha, ignoreVC, ctx); + setVertexFormat(ctx, vertexFormat, useAlpha, ignoreVC); } void disableGlobalAlpha(long ctx, boolean useAlpha, boolean ignoreVC) { @@ -1628,6 +1745,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return mirrorFloatRefColors[0]; } + // Issue 113 + // TODO: Fix this for screen > 0, for now just ignore transparency + if (screen > 0) { + return mirrorFloatRefColors[0]; + } + // update alpha only if vertex format includes alpha if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) return mirrorFloatRefColors[0]; @@ -1796,6 +1919,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return mirrorUnsignedByteRefColors[0]; } + // Issue 113 + // TODO: Fix this for screen > 0, for now just ignore transparency + if (screen > 0) { + return mirrorUnsignedByteRefColors[0]; + } + // update alpha only if vertex format includes alpha if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) return mirrorUnsignedByteRefColors[0]; @@ -1951,6 +2080,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return retVal; } + // Issue 113 + // TODO: Fix this for screen > 0, for now just ignore transparency + if (screen > 0) { + retVal[1] = vertexData; + return retVal; + } + // update alpha only if vertex format includes alpha if ((vertexFormat & GeometryArray.COLOR) == 0) { retVal[1] = vertexData; @@ -1980,7 +2116,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // allocate a copy of the vertex data for the screen if needed. // this piece of code is mainly for multi-screens case - // TODO: this might not too much data for just to update alpha + // NOTE: this might not too much data for just to update alpha if (mvertexData == null || mvertexData.length <= screen) { float[][] cfData = new float[screen + 1][]; @@ -2101,6 +2237,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return retVal; } + // Issue 113 + // TODO: Fix this for screen > 0, for now just ignore transparency + if (screen > 0) { + retVal[1] = null; + return retVal; + } + // update alpha only if vertex format includes alpha if (((vertexFormat | c4fAllocated) & GeometryArray.COLOR) == 0) { retVal[1] = mirrorInterleavedColorPointer[0]; @@ -2131,7 +2274,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // allocate a copy of the vertex data for the screen if needed. // this piece of code is mainly for multi-screens case - // TODO: this might not too much data for just to update alpha + // NOTE: this might not too much data for just to update alpha if (mirrorInterleavedColorPointer.length <= screen) { float[][] cfData = new float[screen + 1][]; @@ -2252,8 +2395,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ boolean useAlpha = false; Object[] retVal; + // Check for by-copy case if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { - float[] vdata; + float[] vdata; synchronized (this) { cdirty = dirtyFlag; @@ -2294,8 +2438,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ (texCoordSetMap == null) ? 0 : texCoordSetMap.length, texCoordSetMapOffset, cv.numActiveTexUnit, cv.texUnitStateMap, - vdata, null, - pass, cdirty); + vertexAttrCount, vertexAttrSizes, + vdata, null, + pass, cdirty); } //By reference with java array @@ -2338,8 +2483,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ texCoordSetCount, texCoordSetMap, (texCoordSetMap == null) ? 0 : texCoordSetMap.length, texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, - interLeavedVertexData, cdata, + cv.numActiveTexUnit, cv.texUnitStateMap, + vertexAttrCount, vertexAttrSizes, + interLeavedVertexData, cdata, pass, cdirty); } // end of interleaved case @@ -2354,7 +2500,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0) || (((vertexFormat & GeometryArray.NORMALS) != 0) && - (vertexType & NORMAL_DEFINED) == 0) || + (vertexType & NORMAL_DEFINED) == 0) || + (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && + (vertexType & VATTR_DEFINED) == 0) || (((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) { return; @@ -2419,6 +2567,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ vdefined |= COLOR_BYTE; if((vertexType & NORMAL_DEFINED) != 0) vdefined |= NORMAL_FLOAT; + if((vertexType & VATTR_DEFINED) != 0) + vdefined |= VATTR_FLOAT; if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; @@ -2432,6 +2582,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ mirrorFloatRefCoords, mirrorDoubleRefCoords, initialColorIndex, cfdata, cbdata, initialNormalIndex, mirrorFloatRefNormals, + vertexAttrCount, vertexAttrSizes, + initialVertexAttrIndex, mirrorFloatRefVertexAttrs, pass, ((texCoordSetMap == null) ? 0:texCoordSetMap.length), texCoordSetMap, @@ -2456,7 +2608,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ cdirty = dirtyFlag; if (updateAlpha && !ignoreVertexColors) { // update the alpha values - // TODO: to handle alpha case + // XXXX: to handle alpha case retVal = updateAlphaInInterLeavedData(cv, screen, alpha); useAlpha = (retVal[0] == Boolean.TRUE); cdata = (float[])retVal[1]; @@ -2466,7 +2618,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ cdirty |= COLOR_CHANGED; } } else { - // TODO: to handle alpha case + // XXXX: to handle alpha case cdata = null; // if transparency switch between on/off if (lastScreenAlpha != -1) { @@ -2477,7 +2629,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ dirtyFlag = 0; } - executeInterleavedBuffer(cv.ctx, this, geoType, isNonUniformScale, useAlpha, multiScreen, @@ -2493,9 +2644,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ pass, cdirty); } // end of interleaved case - + // non interleaved data else { + // Check if a vertexformat is set, but the array is null // if yes, don't draw anything if ((vertexType == 0) || @@ -2503,15 +2655,16 @@ abstract class GeometryArrayRetained extends GeometryRetained{ (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0) || (((vertexFormat & GeometryArray.NORMALS) != 0) && - (vertexType & NORMAL_DEFINED) == 0) || + (vertexType & NORMAL_DEFINED) == 0) || + (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && + (vertexType & VATTR_DEFINED) == 0) || (((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) { return; } else { byte[] cbdata = null; float[] cfdata = null; - - + if ((vertexType & CF ) != 0) { synchronized (this) { cdirty = dirtyFlag; @@ -2523,7 +2676,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ cdirty |= COLOR_CHANGED; } } else { - // TODO: handle transparency case + // XXXX: handle transparency case //cfdata = null; cfdata = mirrorFloatRefColors[0]; // if transparency switch between on/off @@ -2547,7 +2700,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ cdirty |= COLOR_CHANGED; } } else { - // TODO: handle transparency case + // XXXX: handle transparency case //cbdata = null; cbdata = mirrorUnsignedByteRefColors[0]; // if transparency switch between on/off @@ -2585,9 +2738,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if((vertexType & NORMAL_DEFINED) != 0) { vdefined |= NORMAL_FLOAT; normal = floatBufferRefNormals.getBufferAsObject(); - } + } - if((vertexType & TEXCOORD_DEFINED) != 0) + if ((vertexType & VATTR_DEFINED) != 0) { + vdefined |= VATTR_FLOAT; + } + + if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; executeVABuffer(cv.ctx, this, geoType, isNonUniformScale, @@ -2603,6 +2760,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ cfdata, cbdata, initialNormalIndex, normal, + vertexAttrCount, vertexAttrSizes, + initialVertexAttrIndex, + nioFloatBufferRefVertexAttrs, pass, ((texCoordSetMap == null) ? 0:texCoordSetMap.length), texCoordSetMap, @@ -2616,60 +2776,68 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } // used for GeometryArrays - native void buildGA(long ctx, GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int startVIndex, - int vcount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetMapOffset, - double[] xform, double[] nxform, - float[] varray); - - // used to Build Dlist GeometryArray by Reference with java arrays - native void buildGAForByRef(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, float[] vfcoords, double[] vdcoords, - int colorIndex, float[] cfdata, byte[] cbdata, - int normalIndex, float[] ndata, - int texcoordmaplength, - int[] texcoordoffset, - int[] texIndex, int texstride, Object[] texCoords, - double[] xform, double[] nxform); - - - // used to Build Dlist GeometryArray by Reference with java arrays - native void buildGAForBuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int vcount, - int vformat, - int vdefined, - int coordIndex, Object vcoords, - int colorIndex, Object cdata, - int normalIndex, Object ndata, - int texcoordmaplength, - int[] texcoordoffset, - int[] texIndex, int texstride, Object[] texCoords, - double[] xform, double[] nxform); - - + private native void buildGA(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int startVIndex, + int vcount, int vformat, + int texCoordSetCount, int texCoordSetMap[], + int texCoordSetMapLen, int[] texCoordSetMapOffset, + int vertexAttrCount, int[] vertexAttrSizes, + double[] xform, double[] nxform, + float[] varray); + + // used to Build Dlist GeometryArray by Reference with java arrays + private native void buildGAForByRef(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, float[] vfcoords, double[] vdcoords, + int colorIndex, float[] cfdata, byte[] cbdata, + int normalIndex, float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + int[] vertexAttrIndex, float[][] vertexAttrData, + int texcoordmaplength, + int[] texcoordoffset, + int[] texIndex, int texstride, Object[] texCoords, + double[] xform, double[] nxform); + + + // used to Build Dlist GeometryArray by Reference with NIO buffer + // NOTE: NIO buffers are no longer supported in display lists. + /* + private native void buildGAForBuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int vcount, + int vformat, + int vdefined, + int coordIndex, Object vcoords, + int colorIndex, Object cdata, + int normalIndex, Object ndata, + int texcoordmaplength, + int[] texcoordoffset, + int[] texIndex, int texstride, Object[] texCoords, + double[] xform, double[] nxform); + */ void buildGA(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, boolean ignoreVertexColors, Transform3D xform, Transform3D nxform) { - float[] vdata = null; + + float[] vdata = null; + + // NIO buffers are no longer supported in display lists + assert (vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0; if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { vdata = vertexData; @@ -2690,13 +2858,31 @@ abstract class GeometryArrayRetained extends GeometryRetained{ texCoordSetCount, texCoordSetMap, (texCoordSetMap == null) ? 0 : texCoordSetMap.length, texCoordSetMapOffset, - (xform == null) ? null : xform.mat, + vertexAttrCount, vertexAttrSizes, + (xform == null) ? null : xform.mat, (nxform == null) ? null : nxform.mat, vdata); } else { - // Either non-interleaved, by-ref or nio buffer + // Check if a vertexformat is set, but the array is null + // if yes, don't draw anything + if ((vertexType == 0) || + ((vertexType & VERTEX_DEFINED) == 0) || + (((vertexFormat & GeometryArray.COLOR) != 0) && + (vertexType & COLOR_DEFINED) == 0) || + (((vertexFormat & GeometryArray.NORMALS) != 0) && + (vertexType & NORMAL_DEFINED) == 0) || + (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && + (vertexType & VATTR_DEFINED) == 0) || + (((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) && + (vertexType & TEXCOORD_DEFINED) == 0)) { + + return; + } + + // Either non-interleaved, by-ref or nio buffer if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) { + // Java array case // setup vdefined to passed to native code int vdefined = 0; if((vertexType & (PF | P3F)) != 0) @@ -2709,8 +2895,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ vdefined |= COLOR_BYTE; if((vertexType & NORMAL_DEFINED) != 0) vdefined |= NORMAL_FLOAT; + if((vertexType & VATTR_DEFINED) != 0) + vdefined |= VATTR_FLOAT; if((vertexType & TEXCOORD_DEFINED) != 0) vdefined |= TEXCOORD_FLOAT; + buildGAForByRef(cv.ctx, this, geoType, isNonUniformScale, updateAlpha, alpha, ignoreVertexColors, @@ -2721,6 +2910,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ mirrorFloatRefCoords, mirrorDoubleRefCoords, initialColorIndex, mirrorFloatRefColors[0], mirrorUnsignedByteRefColors[0], initialNormalIndex, mirrorFloatRefNormals, + vertexAttrCount, vertexAttrSizes, + initialVertexAttrIndex, mirrorFloatRefVertexAttrs, ((texCoordSetMap == null) ? 0:texCoordSetMap.length), texCoordSetMap, initialTexCoordIndex,texCoordStride, @@ -2728,50 +2919,60 @@ abstract class GeometryArrayRetained extends GeometryRetained{ (xform == null) ? null : xform.mat, (nxform == null) ? null : nxform.mat); } + /* + // NOTE: NIO buffers are no longer supported in display lists. + // This was never enabled by default anyway (only when the + // optimizeForSpace property was set to false), so it wasn't + // well-tested. If future support is desired, we will need to + // add vertex attributes to buildGAForBuffer. There are no plans + // to ever do this. else { - Object vcoord = null, cdataBuffer=null, normal=null; - - int vdefined = 0; - if((vertexType & PF) != 0) { - vdefined |= COORD_FLOAT; - vcoord = floatBufferRefCoords.getBufferAsObject(); - } else if((vertexType & PD ) != 0) { - vdefined |= COORD_DOUBLE; - vcoord = doubleBufferRefCoords.getBufferAsObject(); - } - - if((vertexType & CF ) != 0) { - vdefined |= COLOR_FLOAT; - cdataBuffer = floatBufferRefColors.getBufferAsObject(); - } else if((vertexType & CUB) != 0) { - vdefined |= COLOR_BYTE; - cdataBuffer = byteBufferRefColors.getBufferAsObject(); - } - - if((vertexType & NORMAL_DEFINED) != 0) { - vdefined |= NORMAL_FLOAT; - normal = floatBufferRefNormals.getBufferAsObject(); - } + // NIO Buffer case + Object vcoord = null, cdataBuffer=null, normal=null; + + int vdefined = 0; + if((vertexType & PF) != 0) { + vdefined |= COORD_FLOAT; + vcoord = floatBufferRefCoords.getBufferAsObject(); + } else if((vertexType & PD ) != 0) { + vdefined |= COORD_DOUBLE; + vcoord = doubleBufferRefCoords.getBufferAsObject(); + } - if((vertexType & TEXCOORD_DEFINED) != 0) - vdefined |= TEXCOORD_FLOAT; - buildGAForBuffer(cv.ctx, this, geoType, isNonUniformScale, - updateAlpha, alpha, - ignoreVertexColors, - validVertexCount, - vertexFormat, - vdefined, - initialCoordIndex, - vcoord, - initialColorIndex,cdataBuffer, - initialNormalIndex, normal, - ((texCoordSetMap == null) ? 0:texCoordSetMap.length), - texCoordSetMap, - initialTexCoordIndex,texCoordStride, - refTexCoords, - (xform == null) ? null : xform.mat, - (nxform == null) ? null : nxform.mat); - } + if((vertexType & CF ) != 0) { + vdefined |= COLOR_FLOAT; + cdataBuffer = floatBufferRefColors.getBufferAsObject(); + } else if((vertexType & CUB) != 0) { + vdefined |= COLOR_BYTE; + cdataBuffer = byteBufferRefColors.getBufferAsObject(); + } + + if((vertexType & NORMAL_DEFINED) != 0) { + vdefined |= NORMAL_FLOAT; + normal = floatBufferRefNormals.getBufferAsObject(); + } + + if((vertexType & TEXCOORD_DEFINED) != 0) + vdefined |= TEXCOORD_FLOAT; + // NOTE : need to add vertex attrs + buildGAForBuffer(cv.ctx, this, geoType, isNonUniformScale, + updateAlpha, alpha, + ignoreVertexColors, + validVertexCount, + vertexFormat, + vdefined, + initialCoordIndex, + vcoord, + initialColorIndex,cdataBuffer, + initialNormalIndex, normal, + ((texCoordSetMap == null) ? 0:texCoordSetMap.length), + texCoordSetMap, + initialTexCoordIndex,texCoordStride, + refTexCoords, + (xform == null) ? null : xform.mat, + (nxform == null) ? null : nxform.mat); + } + */ } @@ -2786,8 +2987,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } - void unIndexifyJavaArray(IndexedGeometryArrayRetained src) { - int vOffset = 0, srcOffset, tOffset = 0; + private void unIndexifyJavaArray(IndexedGeometryArrayRetained src) { +// System.err.println("unIndexifyJavaArray"); + + int vOffset = 0, srcOffset, tOffset = 0; int index, colorStride = 0; float[] vdata = null; int i; @@ -2843,10 +3046,24 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } System.arraycopy(vdata, - (((int[])src.indexTexCoord[i])[index])*src.stride + src.textureOffset + interleavedOffset, + (src.indexTexCoord[i][index])*src.stride + src.textureOffset + interleavedOffset, vertexData, tcOffset, texCoordStride); } } + + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + // vertex attributes can't be interleaved + assert (src.vertexFormat & GeometryArray.INTERLEAVED) == 0; + + for (i = 0; i < vertexAttrCount; i++) { + int vaOffset = vOffset + vertexAttrOffsets[i]; + + System.arraycopy(vdata, + (src.indexVertexAttr[i][index])*src.stride + src.vertexAttrOffsets[i], + vertexData, vaOffset, vertexAttrSizes[i]); + } + } + if ((vertexFormat & GeometryArray.COORDINATES) != 0){ // System.out.println("===> copying coords"); System.arraycopy(vdata, @@ -2859,7 +3076,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } else { - if ((vertexFormat & GeometryArray.NORMALS) != 0){ + if ((vertexFormat & GeometryArray.NORMALS) != 0) { vOffset = normalOffset; switch ((src.vertexType & NORMAL_DEFINED)) { case NF: @@ -2884,7 +3101,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ break; } } - if ((vertexFormat & GeometryArray.COLOR) != 0){ + + if ((vertexFormat & GeometryArray.COLOR) != 0) { vOffset = colorOffset; int multiplier = 3; if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) @@ -2968,6 +3186,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ break; } } + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { vOffset = textureOffset; switch ((src.vertexType & TEXCOORD_DEFINED)) { @@ -2976,7 +3195,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) { System.arraycopy(src.refTexCoords[i], - ((int[])src.indexTexCoord[i])[index]*texCoordStride, + src.indexTexCoord[i][index]*texCoordStride, vertexData, tOffset, texCoordStride); tOffset += texCoordStride; } @@ -2987,7 +3206,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ for (index=start; index < end; index++) { for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) { - srcOffset = ((int[])src.indexTexCoord[i])[index]; + srcOffset = src.indexTexCoord[i][index]; vertexData[tOffset] = ((TexCoord2f[])src.refTexCoords[i])[srcOffset].x; vertexData[tOffset+1] = @@ -3001,7 +3220,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ for (index=start; index < end; index++) { for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) { - srcOffset = ((int[])src.indexTexCoord[i])[index]; + srcOffset = src.indexTexCoord[i][index]; vertexData[tOffset] = ((TexCoord3f[])src.refTexCoords[i])[srcOffset].x; vertexData[tOffset+1] = @@ -3016,8 +3235,26 @@ abstract class GeometryArrayRetained extends GeometryRetained{ default: break; } - } - if ((vertexFormat & GeometryArray.COORDINATES) != 0){ + } + + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + vOffset = 0; + switch (src.vertexType & VATTR_DEFINED) { + case AF: + for (index=start; index < end; index++) { + for (i = 0; i < vertexAttrCount; i++) { + int vaOffset = vOffset + vertexAttrOffsets[i]; + System.arraycopy(src.floatRefVertexAttrs[i], + src.indexVertexAttr[i][index]*vertexAttrSizes[i], + vertexData, vaOffset, vertexAttrSizes[i]); + } + vOffset += stride; + } + break; + } + } + + if ((vertexFormat & GeometryArray.COORDINATES) != 0) { vOffset = coordinateOffset; switch ((src.vertexType & VERTEX_DEFINED)) { case PF: @@ -3062,11 +3299,13 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } - } + } + + private void unIndexifyNIOBuffer(IndexedGeometryArrayRetained src) { +// System.err.println("unIndexifyNIOBuffer"); - void unIndexifyNIOBuffer(IndexedGeometryArrayRetained src) { - int vOffset = 0, srcOffset, tOffset = 0; + int vOffset = 0, srcOffset, tOffset = 0; int index, colorStride = 0; float[] vdata = null; int i; @@ -3101,7 +3340,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ for (i = 0; i < texCoordSetCount; i++, tcOffset += texCoordStride) { - src.interleavedFloatBufferImpl.position((((int[])src.indexTexCoord[i])[index])*src.stride + + src.interleavedFloatBufferImpl.position((src.indexTexCoord[i][index])*src.stride + src.textureOffset); src.interleavedFloatBufferImpl.get(vertexData, tcOffset, texCoordStride); } @@ -3124,7 +3363,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } } - if ((vertexFormat & GeometryArray.COLOR) != 0){ + + if ((vertexFormat & GeometryArray.COLOR) != 0){ vOffset = colorOffset; int multiplier = 3; if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) @@ -3165,7 +3405,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ break; } } - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { vOffset = textureOffset; FloatBufferWrapper texBuffer; if ((src.vertexType & TEXCOORD_DEFINED) != 0) { @@ -3173,15 +3414,31 @@ abstract class GeometryArrayRetained extends GeometryRetained{ for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) { texBuffer = (FloatBufferWrapper)(((J3DBuffer) (src.refTexCoordsBuffer[i])).getBufferImpl()); - texBuffer.position(((int[])src.indexTexCoord[i])[index]*texCoordStride); + texBuffer.position(src.indexTexCoord[i][index]*texCoordStride); texBuffer.get(vertexData, tOffset, texCoordStride); tOffset += texCoordStride; } vOffset += stride; } } - } - if ((vertexFormat & GeometryArray.COORDINATES) != 0){ + } + + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + vOffset = 0; + if ((src.vertexType & VATTR_DEFINED) == AF) { + for (index=start; index < end; index++) { + for (i = 0; i < vertexAttrCount; i++) { + int vaOffset = vOffset + vertexAttrOffsets[i]; + FloatBufferWrapper vaBuffer = src.floatBufferRefVertexAttrs[i]; + vaBuffer.position(src.indexVertexAttr[i][index]*vertexAttrSizes[i]); + vaBuffer.get(vertexData, vaOffset, vertexAttrSizes[i]); + } + vOffset += stride; + } + } + } + + if ((vertexFormat & GeometryArray.COORDINATES) != 0){ vOffset = coordinateOffset; switch ((src.vertexType & VERTEX_DEFINED)) { case PF: @@ -3206,7 +3463,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } - } + } + /** * Returns the vertex stride in numbers of floats as a function @@ -3250,6 +3508,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ stride += texCoordStride * texCoordSetCount; } + if ((this.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + stride += vertexAttrStride; + } + + //System.err.println("stride() = " + stride); return stride; } @@ -3270,6 +3533,61 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } /** + * Returns the stride of the set of vertex attributes. This is the + * sum of the sizes of each vertex attribute. + * @return the stride of the vertex attribute data + */ + int vertexAttrStride() { + int sum = 0; + for (int i = 0; i < vertexAttrCount; i++) { + sum += vertexAttrSizes[i]; + } + return sum; + } + + /** + * Returns the offset in number of floats from the start of a vertex to + * each per-vertex vertex attribute. + * @return array of offsets in floats vertex start to the vertex attribute data + */ + int[] vertexAttrOffsets() { + int[] offsets; + + // Create array of offsets to the start of each vertex attribute. + // The offset of the first attribute is always 0. If no vertex attributes exist, + // then we will allocate an array of length 1 to avoid some checking elsewhere. + if (vertexAttrCount > 0) { + offsets = new int[vertexAttrCount]; + } + else { + offsets = new int[1]; + } + offsets[0] = 0; + for (int i = 1; i < vertexAttrCount; i++) { + offsets[i] = offsets[i-1] + vertexAttrSizes[i-1]; + } + + return offsets; + } + + /** + * Returns the offset in number of floats from the start of a vertex to + * the per-vertex texture coordinate data. + * texture coordinate data always follows vertex attribute data + * @return the offset in floats vertex start to the tetxure data + */ + int textureOffset() + { + int offset = vertexAttrOffsets[0]; + + if ((this.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + offset += vertexAttrStride; + } + + return offset; + } + + /** * Returns the offset in number of floats from the start of a vertex to * the per-vertex color data. * color data always follows texture data @@ -3344,6 +3662,32 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return vertexFormat; } + /** + * Retrieves the number of vertex attributes in this GeometryArray + * object. + * + * @return the number of vertex attributes in this GeometryArray + * object + */ + int getVertexAttrCount() { + return vertexAttrCount; + } + + + /** + * Retrieves the vertex attribute sizes array from this + * GeometryArray object. + * + * @param vertexAttrSizes an array that will receive a copy of + * the vertex attribute sizes array. The array must hold at least + * <code>vertexAttrCount</code> elements. + */ + void getVertexAttrSizes(int[] vertexAttrSizes) { + for (int i = 0; i < vertexAttrCount; i++) { + vertexAttrSizes[i] = this.vertexAttrSizes[i]; + } + } + void sendDataChangedMessage(boolean coordinatesChanged) { @@ -3360,7 +3704,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // Send a message to renderBin to rebuild the display list or // process the vertex array accordingly - // TODO: Should I send one per universe, isn't display list + // XXXX: Should I send one per universe, isn't display list // shared by all context/universes? int threads = J3dThread.UPDATE_RENDER; // If the geometry type is Indexed then we need to clone the geometry @@ -4890,7 +5234,259 @@ abstract class GeometryArrayRetained extends GeometryRetained{ geomLock.unLock(); sendDataChangedMessage(false); - } + } + + + /** + * Sets the vertex attribute associated with the vertex at the + * specified index in the specified vertex attribute number for + * this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index destination vertex index in this geometry array + * @param vertexAttr the Point2f containing the new vertex attribute + */ + void setVertexAttr(int vertexAttrNum, int index, + Point2f vertexAttr) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + + this.vertexData[offset] = vertexAttr.x; + this.vertexData[offset+1] = vertexAttr.y; + + if (source == null || !source.isLive()) { + geomLock.unLock(); + return; + } + + geomLock.unLock(); + sendDataChangedMessage(false); + } + + /** + * Sets the vertex attribute associated with the vertex at the + * specified index in the specified vertex attribute number for + * this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index destination vertex index in this geometry array + * @param vertexAttr the Point3f containing the new vertex attribute + */ + void setVertexAttr(int vertexAttrNum, int index, + Point3f vertexAttr) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + + this.vertexData[offset] = vertexAttr.x; + this.vertexData[offset+1] = vertexAttr.y; + this.vertexData[offset+2] = vertexAttr.z; + + if (source == null || !source.isLive()) { + geomLock.unLock(); + return; + } + + geomLock.unLock(); + sendDataChangedMessage(false); + } + + /** + * Sets the vertex attribute associated with the vertex at the + * specified index in the specified vertex attribute number for + * this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index destination vertex index in this geometry array + * @param vertexAttr the Point4f containing the new vertex attribute + */ + void setVertexAttr(int vertexAttrNum, int index, + Point4f vertexAttr) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + + this.vertexData[offset] = vertexAttr.x; + this.vertexData[offset+1] = vertexAttr.y; + this.vertexData[offset+2] = vertexAttr.z; + this.vertexData[offset+3] = vertexAttr.w; + + if (source == null || !source.isLive()) { + geomLock.unLock(); + return; + } + + geomLock.unLock(); + sendDataChangedMessage(false); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of 1*n, 2*n, 3*n, or 4*n values + * containing n new vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + */ + void setVertexAttrs(int vertexAttrNum, int index, + float[] vertexAttrs, + int start, int length) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int size = vertexAttrSizes[vertexAttrNum]; + int i, j, k; + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + + for (i = start * size, j = offset, k = 0; k < length; i += size, j += this.stride, k++) { + for (int ii = 0; ii < size; ii++) { + this.vertexData[j+ii] = vertexAttrs[i+ii]; + } + } + + if (source == null || !source.isLive()) { + geomLock.unLock(); + return; + } + + geomLock.unLock(); + sendDataChangedMessage(false); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point2f objects containing new + * vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + */ + void setVertexAttrs(int vertexAttrNum, int index, + Point2f[] vertexAttrs, + int start, int length) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int i, j, k; + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + + for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) { + this.vertexData[j] = vertexAttrs[i].x; + this.vertexData[j+1] = vertexAttrs[i].y; + } + + if (source == null || !source.isLive()) { + geomLock.unLock(); + return; + } + + geomLock.unLock(); + sendDataChangedMessage(false); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point3f objects containing new + * vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + */ + void setVertexAttrs(int vertexAttrNum, int index, + Point3f[] vertexAttrs, + int start, int length) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int i, j, k; + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + + for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) { + this.vertexData[j] = vertexAttrs[i].x; + this.vertexData[j+1] = vertexAttrs[i].y; + this.vertexData[j+2] = vertexAttrs[i].z; + } + + if (source == null || !source.isLive()) { + geomLock.unLock(); + return; + } + + geomLock.unLock(); + sendDataChangedMessage(false); + } + + /** + * Sets the vertex attributes associated with the vertices + * starting at the specified index in the specified vertex + * attribute number for this object using data in + * <code>vertexAttrs</code> starting at index <code>start</code> and + * ending at index <code>start+length</code>. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index starting destination vertex index in this geometry array + * @param vertexAttrs source array of Point4f objects containing new + * vertex attributes + * @param start starting source vertex index in <code>vertexAttrs</code> + * array. + * @param length number of vertex attributes to be copied. + */ + void setVertexAttrs(int vertexAttrNum, int index, + Point4f[] vertexAttrs, + int start, int length) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int i, j, k; + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + + for (i = start, j = offset, k = 0; k < length; i++, j += this.stride, k++) { + this.vertexData[j] = vertexAttrs[i].x; + this.vertexData[j+1] = vertexAttrs[i].y; + this.vertexData[j+2] = vertexAttrs[i].z; + this.vertexData[j+3] = vertexAttrs[i].w; + } + + if (source == null || !source.isLive()) { + geomLock.unLock(); + return; + } + + geomLock.unLock(); + sendDataChangedMessage(false); + } + /** * Gets the coordinate associated with the vertex at @@ -5505,6 +6101,158 @@ abstract class GeometryArrayRetained extends GeometryRetained{ /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttr(int vertexAttrNum, int index, + float[] vertexAttr) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int size = vertexAttrSizes[vertexAttrNum]; + + for (int i = 0; i < size; i++) { + vertexAttr[i] = this.vertexData[offset+i]; + + } + + } + + /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttr(int vertexAttrNum, int index, + Point2f vertexAttr) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + + vertexAttr.x = this.vertexData[offset]; + vertexAttr.y = this.vertexData[offset+1]; + + } + + /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttr(int vertexAttrNum, int index, + Point3f vertexAttr) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + + vertexAttr.x = this.vertexData[offset]; + vertexAttr.y = this.vertexData[offset+1]; + vertexAttr.z = this.vertexData[offset+2]; + + } + + /** + * Gets the vertex attribute associated with the vertex at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttr(int vertexAttrNum, int index, + Point4f vertexAttr) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + + vertexAttr.x = this.vertexData[offset]; + vertexAttr.y = this.vertexData[offset+1]; + vertexAttr.z = this.vertexData[offset+2]; + vertexAttr.w = this.vertexData[offset+3]; + + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttrs(int vertexAttrNum, int index, + float[] vertexAttrs) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int size = vertexAttrSizes[vertexAttrNum]; + int i, j, k; + + for (i = 0, j = offset; + ((i < vertexAttrs.length) && (j < this.vertexData.length)) ; + i += size, j += this.stride) { + for (k = 0; k < size; k++) { + vertexAttrs[i+k] = this.vertexData[j+k]; + } + } + + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttrs(int vertexAttrNum, int index, + Point2f[] vertexAttrs) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int i, j; + + for (i = 0, j = offset; + ((i < vertexAttrs.length) && (j < this.vertexData.length)) ; + i++, j += this.stride) { + vertexAttrs[i].x = this.vertexData[j]; + vertexAttrs[i].y = this.vertexData[j+1]; + } + + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttrs(int vertexAttrNum, int index, + Point3f[] vertexAttrs) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int i, j; + + for (i = 0, j = offset; + ((i < vertexAttrs.length) && (j < this.vertexData.length)) ; + i++, j += this.stride) { + vertexAttrs[i].x = this.vertexData[j]; + vertexAttrs[i].y = this.vertexData[j+1]; + vertexAttrs[i].z = this.vertexData[j+2]; + } + + } + + /** + * Gets the vertex attributes associated with the vertices starting at + * the specified index in the specified vertex attribute number + * for this object. + */ + public void getVertexAttrs(int vertexAttrNum, int index, + Point4f[] vertexAttrs) { + + int offset = this.stride*index + vertexAttrOffsets[vertexAttrNum]; + int i, j; + + for (i = 0, j = offset; + ((i < vertexAttrs.length) && (j < this.vertexData.length)) ; + i++, j += this.stride) { + vertexAttrs[i].x = this.vertexData[j]; + vertexAttrs[i].y = this.vertexData[j+1]; + vertexAttrs[i].z = this.vertexData[j+2]; + vertexAttrs[i].w = this.vertexData[j+3]; + } + + } + + + /** * Updates geometry array data. */ void updateData(GeometryUpdater updater) { @@ -5519,7 +6267,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ inUpdater = false; if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) { if((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { - // TODO: handle the nio buffer + // XXXX: handle the nio buffer if (!(this instanceof IndexedGeometryArrayRetained) || (vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) { if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) { @@ -5540,10 +6288,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ nullGeo = (interLeavedVertexData == null); } else { - setupMirrorVertexPointer((vertexType & VERTEX_DEFINED)); + setupMirrorVertexPointer(vertexType & VERTEX_DEFINED); setupMirrorColorPointer((vertexType & COLOR_DEFINED), false); - setupMirrorNormalPointer((vertexType & NORMAL_DEFINED)); - setupMirrorTexCoordPointer((vertexType & TEXCOORD_DEFINED)); + setupMirrorNormalPointer(vertexType & NORMAL_DEFINED); + setupMirrorTexCoordPointer(texCoordType); + setupMirrorVertexAttrPointer(vertexAttrType); nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0); } } @@ -7254,7 +8003,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ direction.z = end.z - start.z; result = intersectRayOrSegment(coordinates, direction, start, dist, iPnt, true); freeVector3d(direction); - return result; + if((result == true) && (dist[0] <= 1.0)) { + return true; + } + + return false; + } @@ -7435,7 +8189,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // Note that by next round sign*lastSign = 0 so it will // not pass the interest test. This should only happen once in the // loop because we already check for degenerate geometry before. - lastSign = 0; } } } @@ -7467,7 +8220,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ isIntersect = ((t > -EPS) && (t < 1+EPS)); break; } else { - lastSign = 0; //degenerate line=>point + //degenerate line=>point } } } @@ -7499,7 +8252,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ isIntersect = ((t > -EPS) && (t < 1+EPS)); break; } else { - lastSign = 0; //degenerate line=>point + //degenerate line=>point } } } @@ -7529,7 +8282,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ isIntersect = ((t > -EPS) && (t < 1+EPS)); break; } else { - lastSign = 0; //degenerate line=>point + //degenerate line=>point } } } @@ -8036,18 +8789,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (coords != null) { switch (coords.getBufferType()) { case J3DBuffer.TYPE_FLOAT: - if ( !((FloatBufferWrapper)coords.getBufferImpl()).isDirect()) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray120")); - - // TODO: may need to check whether it is direct and if so, - // whether it is consistent with native byte order + assert ((FloatBufferWrapper)coords.getBufferImpl()).isDirect(); break; case J3DBuffer.TYPE_DOUBLE: - if ( !((DoubleBufferWrapper)coords.getBufferImpl()).isDirect()) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray120")); - - // TODO: may need to check whether it is direct and if so, - // whether it is consistent with native byte order + assert ((DoubleBufferWrapper)coords.getBufferImpl()).isDirect(); break; case J3DBuffer.TYPE_NULL: throw new IllegalArgumentException(J3dI18N.getString("GeometryArray115")); @@ -8066,7 +8811,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } - //throw new RuntimeException("method not implemeted"); // lock the geometry and start to do real work geomLock.getLock(); dirtyFlag |= COORDINATE_CHANGED; @@ -8074,7 +8818,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if(coords == null) { floatBufferRefCoords = null; doubleBufferRefCoords = null; - // TODO: if not mix java array with nio buffer + // XXXX: if not mix java array with nio buffer // vertexType can be used as vertexTypeBuffer vertexType &= ~PD; vertexType &= ~PF; @@ -8101,7 +8845,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // need not call setupMirrorVertexPointer() since // we are not going to set mirror in NIO buffer case - // TODO: if we need to mix java array with buffer, + // XXXX: if we need to mix java array with buffer, // we may need to consider setupMirrorVertexPointer() geomLock.unLock(); @@ -8375,12 +9119,10 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if (colors != null) { switch(colors.getBufferType()) { case J3DBuffer.TYPE_FLOAT: - if ( !((FloatBufferWrapper)colors.getBufferImpl()).isDirect()) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray120")); + assert ((FloatBufferWrapper)colors.getBufferImpl()).isDirect(); break; case J3DBuffer.TYPE_BYTE: - if ( !((ByteBufferWrapper)colors.getBufferImpl()).isDirect()) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray120")); + assert ((ByteBufferWrapper)colors.getBufferImpl()).isDirect(); break; case J3DBuffer.TYPE_NULL: throw new IllegalArgumentException(J3dI18N.getString("GeometryArray115")); @@ -8759,8 +9501,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ bufferImpl = (FloatBufferWrapper)normals.getBufferImpl(); - if ( ! bufferImpl.isDirect()) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray120")); + assert bufferImpl.isDirect(); if ((vertexFormat & GeometryArray.NORMALS) == 0) { throw new IllegalStateException(J3dI18N.getString("GeometryArray122")); @@ -8863,15 +9604,17 @@ abstract class GeometryArrayRetained extends GeometryRetained{ void setTexCoordRefFloat(int texCoordSet, float[] texCoords) { - if (texCoords != null) { + if (texCoordType != 0 && texCoordType != TF) { + if (texCoords != null) { + throw new IllegalArgumentException( + J3dI18N.getString("GeometryArray98")); + } + return; + } - if ((vertexType & TEXCOORD_DEFINED) != 0 && - (vertexType & TEXCOORD_DEFINED) != TF) { - throw new IllegalArgumentException( - J3dI18N.getString("GeometryArray98")); - } + if (texCoords != null) { - int ts = getTexStride(); + int ts = getTexStride(); if (this instanceof IndexedGeometryArrayRetained) { IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this; @@ -8889,10 +9632,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ refTexCoords[texCoordSet] = texCoords; if (inUpdater || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) { - if (texCoords == null) - vertexType &= ~TF; - else - vertexType |= TF; + texCoordType = TF; + validateTexCoordPointerType(); } else { setupMirrorTexCoordPointer(texCoordSet, TF); @@ -8903,8 +9644,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } - - + float[] getTexCoordRefFloat(int texCoordSet) { return ((float[])refTexCoords[texCoordSet]); } @@ -8921,8 +9661,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ bufferImpl = (FloatBufferWrapper)texCoords.getBufferImpl(); int bufferSize = bufferImpl.limit(); - if ( ! bufferImpl.isDirect()) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray120")); + assert bufferImpl.isDirect(); int ts = getTexStride(); @@ -8941,14 +9680,14 @@ abstract class GeometryArrayRetained extends GeometryRetained{ // refTexCoordsBuffer contains J3DBuffer object for tex coord refTexCoordsBuffer[texCoordSet] = texCoords; if (texCoords == null) { - vertexType &= ~TF; refTexCoords[texCoordSet] = null; } else { - vertexType |= TF; // refTexCoords contains NIOBuffer object for tex coord refTexCoords[texCoordSet] = bufferImpl.getBufferAsObject(); } + texCoordType = TF; + validateTexCoordPointerType(); geomLock.unLock(); if (!inUpdater && source != null && source.isLive()) { sendDataChangedMessage(false); @@ -8961,13 +9700,15 @@ abstract class GeometryArrayRetained extends GeometryRetained{ void setTexCoordRef2f(int texCoordSet, TexCoord2f[] texCoords) { - if (texCoords != null) { - if ((vertexType & TEXCOORD_DEFINED) != 0 && - (vertexType & TEXCOORD_DEFINED) != T2F) { - throw new IllegalArgumentException( - J3dI18N.getString("GeometryArray98")); - } - + if (texCoordType != 0 && texCoordType != T2F) { + if (texCoords != null) { + throw new IllegalArgumentException( + J3dI18N.getString("GeometryArray98")); + } + return; + } + + if (texCoords != null) { if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) == 0) { throw new IllegalStateException( J3dI18N.getString("GeometryArray94")); @@ -8990,13 +9731,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ refTexCoords[texCoordSet] = texCoords; if (inUpdater || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) { - if (texCoords == null) - vertexType &= ~T2F; - else - vertexType |= T2F; + texCoordType = T2F; + validateTexCoordPointerType(); } else { - setupMirrorTexCoordPointer(T2F); + setupMirrorTexCoordPointer(texCoordSet, T2F); } geomLock.unLock(); if (!inUpdater && source != null && source.isLive()) { @@ -9017,14 +9756,16 @@ abstract class GeometryArrayRetained extends GeometryRetained{ void setTexCoordRef3f(int texCoordSet, TexCoord3f[] texCoords) { + if (texCoordType != 0 && texCoordType != T3F) { + if (texCoords != null) { + throw new IllegalArgumentException( + J3dI18N.getString("GeometryArray98")); + } + return; + } + if (texCoords != null) { - if ((vertexType & TEXCOORD_DEFINED) != 0 && - (vertexType & TEXCOORD_DEFINED) != T3F) { - throw new IllegalArgumentException( - J3dI18N.getString("GeometryArray98")); - } - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) == 0) { throw new IllegalStateException( J3dI18N.getString("GeometryArray95")); @@ -9048,13 +9789,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ refTexCoords[texCoordSet] = texCoords; if (inUpdater || (this instanceof IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) { - if (texCoords == null) - vertexType &= ~T3F; - else - vertexType |= T3F; + texCoordType = T3F; + validateTexCoordPointerType(); } else { - setupMirrorTexCoordPointer(T3F); + setupMirrorTexCoordPointer(texCoordSet, T3F); } geomLock.unLock(); if (!inUpdater && source != null && source.isLive()) { @@ -9073,6 +9812,125 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } + /** + * Sets the float vertex attribute array reference for the + * specified vertex attribute number to the specified array. + */ + void setVertexAttrRefFloat(int vertexAttrNum, float[] vertexAttrs) { + + // XXXX: Add the following test if we ever add double-precision types + /* + if (vertexAttrType != 0 && vertexAttrType != AF) { + if (vertexAttrs != null) { + // XXXX: new exception string + throw new IllegalArgumentException( + J3dI18N.getString("GeometryArray98-XXX")); + } + return; + } + */ + + if (vertexAttrs != null) { + int sz = vertexAttrSizes[vertexAttrNum]; + + if (this instanceof IndexedGeometryArrayRetained) { + IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this; + + if (sz*idx.maxVertexAttrIndices[vertexAttrNum] >= vertexAttrs.length) { + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30")); + } + + } else if (vertexAttrs.length < sz*(initialVertexAttrIndex[vertexAttrNum] + validVertexCount) ) { + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray129")); + } + } + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + floatRefVertexAttrs[vertexAttrNum] = vertexAttrs; + if (inUpdater || (this instanceof IndexedGeometryArrayRetained && + ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) { + vertexAttrType = AF; + validateVertexAttrPointerType(); + } + else { + setupMirrorVertexAttrPointer(vertexAttrNum, AF); + } + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } + } + + /** + * Gets the float vertex attribute array reference for the specified + * vertex attribute number. + */ + float[] getVertexAttrRefFloat(int vertexAttrNum) { + return floatRefVertexAttrs[vertexAttrNum]; + } + + + /** + * Sets the vertex attribute buffer reference for the specified + * vertex attribute number to the specified buffer object. + */ + void setVertexAttrRefBuffer(int vertexAttrNum, J3DBuffer vertexAttrs) { + + FloatBufferWrapper bufferImpl = null; + + if (vertexAttrs != null) { + if(vertexAttrs.getBufferType() != J3DBuffer.TYPE_FLOAT) + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116")); + + bufferImpl = (FloatBufferWrapper)vertexAttrs.getBufferImpl(); + int bufferSize = bufferImpl.limit(); + + assert bufferImpl.isDirect(); + + int sz = vertexAttrSizes[vertexAttrNum]; + + if (this instanceof IndexedGeometryArrayRetained) { + IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained)this; + + if (idx.maxVertexAttrIndices[vertexAttrNum] * sz >= bufferSize) { + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30")); + } + } else if (bufferSize < sz*(initialVertexAttrIndex[vertexAttrNum] + validVertexCount)) { + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray129")); + } + } + + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + vertexAttrsRefBuffer[vertexAttrNum] = vertexAttrs; + if (vertexAttrs == null) { + floatBufferRefVertexAttrs[vertexAttrNum] = null; + nioFloatBufferRefVertexAttrs[vertexAttrNum] = null; + } + else { + floatBufferRefVertexAttrs[vertexAttrNum] = bufferImpl; + nioFloatBufferRefVertexAttrs[vertexAttrNum] = + bufferImpl.getBufferAsObject(); + } + vertexAttrType = AF; + validateVertexAttrPointerType(); + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } + + } + + /** + * Gets the vertex attribute array buffer reference for the specified + * vertex attribute number. + */ + J3DBuffer getVertexAttrRefBuffer(int vertexAttrNum) { + return vertexAttrsRefBuffer[vertexAttrNum]; + } + + void setInterleavedVertices(float[] vertexData) { if (vertexData != null) { @@ -9135,10 +9993,9 @@ abstract class GeometryArrayRetained extends GeometryRetained{ throw new IllegalArgumentException(J3dI18N.getString("GeometryArray116")); bufferImpl = (FloatBufferWrapper)vertexData.getBufferImpl(); - - if (!bufferImpl.isDirect()) - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray120")); - + + assert bufferImpl.isDirect(); + int bufferSize = bufferImpl.limit(); if (this instanceof IndexedGeometryArrayRetained) { @@ -9203,37 +10060,20 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } void setValidVertexCount(int validVertexCount) { + boolean nullGeo = false; if (validVertexCount < 0) { throw new IllegalArgumentException(J3dI18N.getString("GeometryArray110")); } - if ((initialVertexIndex + validVertexCount) > vertexCount) { - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray100")); - } - else if ((initialCoordIndex + validVertexCount) > vertexCount) { - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray104")); - } - else if ((initialColorIndex + validVertexCount) > vertexCount) { - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray101")); - } - else if ((initialNormalIndex + validVertexCount) > vertexCount) { - throw new IllegalArgumentException(J3dI18N.getString("GeometryArray102")); - } - else { - if ((vertexFormat & (GeometryArray.BY_REFERENCE|vertexFormat &GeometryArray.INTERLEAVED)) == GeometryArray.BY_REFERENCE) { - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { - for (int i = 0; i < texCoordSetCount; i++) { - if ((initialTexCoordIndex[i] + validVertexCount) - > vertexCount) { - throw new IllegalArgumentException(J3dI18N.getString( - "GeometryArray103")); - } - } - } - } - } - if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) { - // use nio buffer for interleaved data + + if ((initialVertexIndex + validVertexCount) > vertexCount) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray100")); + } + + if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) { + // Interleaved, by-ref + + // use nio buffer for interleaved data if(( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0 && interleavedFloatBufferImpl != null){ if(interleavedFloatBufferImpl.limit() < stride * (initialVertexIndex + validVertexCount)) { throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray114")); @@ -9249,10 +10089,41 @@ abstract class GeometryArrayRetained extends GeometryRetained{ nullGeo = true; } } else if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) { - if ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0) + // Non-interleaved, by-ref + + if ((initialCoordIndex + validVertexCount) > vertexCount) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray104")); + } + if ((initialColorIndex + validVertexCount) > vertexCount) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray101")); + } + if ((initialNormalIndex + validVertexCount) > vertexCount) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray102")); + } + + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + for (int i = 0; i < texCoordSetCount; i++) { + if ((initialTexCoordIndex[i] + validVertexCount) > vertexCount) { + throw new IllegalArgumentException(J3dI18N.getString( + "GeometryArray103")); + } + } + } + + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + if ((initialVertexAttrIndex[i] + validVertexCount) > vertexCount) { + throw new IllegalArgumentException(J3dI18N.getString( + "GeometryArray130")); + } + } + } + + if ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0) { nullGeo = true; - - if(( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { + } + + if (( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { // by reference with nio buffer switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) { case PF: @@ -9324,6 +10195,18 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } break; } + switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) { + case AF: + for (int i = 0; i < vertexAttrCount; i++) { + int sz = vertexAttrSizes[i]; + if (floatBufferRefVertexAttrs[i].limit() < + (sz * (initialVertexAttrIndex[i] + validVertexCount)) ) { + throw new ArrayIndexOutOfBoundsException( + J3dI18N.getString("GeometryArray129")); + } + } + break; + } } // By reference with java array else { @@ -9444,6 +10327,18 @@ abstract class GeometryArrayRetained extends GeometryRetained{ throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("GeometryArray111")); } } + switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) { + case AF: + for (int i = 0; i < vertexAttrCount; i++) { + int sz = vertexAttrSizes[i]; + if (floatRefVertexAttrs[i].length < + (sz * (initialVertexAttrIndex[i] + validVertexCount)) ) { + throw new ArrayIndexOutOfBoundsException( + J3dI18N.getString("GeometryArray129")); + } + } + break; + } } } @@ -9455,7 +10350,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ processCoordsChanged(nullGeo); sendDataChangedMessage(true); } - } @@ -9689,6 +10583,49 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return initialNormalIndex; } + /** + * Sets the initial vertex attribute index for the specified + * vertex attribute number for this GeometryArray object. + */ + void setInitialVertexAttrIndex(int vertexAttrNum, + int initialVertexAttrIndex) { + + if ((initialVertexAttrIndex + validVertexCount) > vertexCount) { + throw new IllegalArgumentException(J3dI18N.getString("GeometryArray130")); + } + + int sz = vertexAttrSizes[vertexAttrNum]; + int minLength = sz * (initialVertexAttrIndex + validVertexCount); + if ((vertexType & VATTR_DEFINED) == AF) { + if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { + if (floatBufferRefVertexAttrs[vertexAttrNum].limit() < minLength) { + throw new ArrayIndexOutOfBoundsException( + J3dI18N.getString("GeometryArray129")); + } + } else { + if (floatRefVertexAttrs[vertexAttrNum].length < minLength ) { + throw new ArrayIndexOutOfBoundsException( + J3dI18N.getString("GeometryArray129")); + } + } + } + geomLock.getLock(); + dirtyFlag |= VATTR_CHANGED; + this.initialVertexAttrIndex[vertexAttrNum] = initialVertexAttrIndex; + geomLock.unLock(); + // There is no need to send message for by reference, since we + // use VA + } + + + /** + * Gets the initial vertex attribute index for the specified + * vertex attribute number for this GeometryArray object. + */ + int getInitialVertexAttrIndex(int vertexAttrNum) { + return initialVertexAttrIndex[vertexAttrNum]; + } + void setInitialTexCoordIndex(int texCoordSet, int initialTexCoordIndex) { if ((initialTexCoordIndex + validVertexCount) > vertexCount) { throw new IllegalArgumentException(J3dI18N.getString("GeometryArray103")); @@ -9900,6 +10837,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ source.getCapability(GeometryArray.ALLOW_COLOR_WRITE) || source.getCapability(GeometryArray.ALLOW_NORMAL_WRITE) || source.getCapability(GeometryArray.ALLOW_TEXCOORD_WRITE) || + source.getCapability(GeometryArray.ALLOW_VERTEX_ATTR_WRITE) || source.getCapability(GeometryArray.ALLOW_COUNT_WRITE) || source.getCapability(GeometryArray.ALLOW_REF_DATA_WRITE)) return false; @@ -9963,7 +10901,8 @@ abstract class GeometryArrayRetained extends GeometryRetained{ float[] curVertexData; int length, srcOffset; int curOffset = 0; - // We only merge if the texCoordSetCount is 1; + // We only merge if the texCoordSetCount is 1 and there are no + // vertex attrs if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { texCoordSetCount = 1; texCoordSetMap = new int[1]; @@ -10002,7 +10941,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ texCoordSetMap != null && texCoordSetMap.length > 1)) { return false; } - + + // We will avoid merging geometry if there are any vertex attributes. + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + return false; + } // If intersect is allowed turn off merging if (source.getCapability(Geometry.ALLOW_INTERSECT)) @@ -10011,32 +10954,6 @@ abstract class GeometryArrayRetained extends GeometryRetained{ return true; } - boolean isTextureGeometryMergeable(GeometryArrayRetained srcGeo) { - - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { - if (texCoordSetCount != srcGeo.texCoordSetCount ) - return false; - - // If they are both non-null, then check if they are equivalent - if (texCoordSetMap != null && srcGeo.texCoordSetMap != null) { - if (texCoordSetMap.length != srcGeo.texCoordSetMap.length) - return false; - - // Check the texCoordSetMap is same - for (int j = 0; j < texCoordSetMap.length; j++) { - if (texCoordSetMap[j] != srcGeo.texCoordSetMap[j]) - return false; - } - } - // Check if they are both null; - // if one is null and other is non-null return false - else if (texCoordSetMap != srcGeo.texCoordSetMap) - return false; - } - - return true; - } - void compile(CompileState compState) { super.compile(compState); @@ -10097,7 +11014,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ geomLock.getLock(); if (this instanceof IndexedGeometryArrayRetained) { if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { - mirrorGeometry = (GeometryRetained) + mirrorGeometry = ((IndexedGeometryArrayRetained)this).cloneNonIndexedGeometry(); } else { @@ -10113,7 +11030,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ geomLock.getLock(); if (this instanceof IndexedGeometryArrayRetained) { if (mirrorGeometry != null) { - mirrorGeometry = (GeometryRetained) + mirrorGeometry = ((IndexedGeometryArrayRetained)this).cloneNonIndexedGeometry(); } } @@ -10261,7 +11178,7 @@ abstract class GeometryArrayRetained extends GeometryRetained{ if ((vertexFormat & GeometryArray.INTERLEAVED) == 0){ switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) { case PF: - count = floatBufferRefCoords.limit()/3; // TODO: limit or capacity + count = floatBufferRefCoords.limit()/3; // XXXX: limit or capacity? break; case PD: count = doubleBufferRefCoords.limit()/3; @@ -10437,8 +11354,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } return count; - } - + } + + // NOTE: we don't need a getNumVertexAttrCount method, since getNum*Count + // is only called by Morph, which doesn't support vertex attrs + + // Found the min distance from center to the point/line/tri/quad // form by dist[] void computeMinDistance(Point3d coordinates[], Point3d center, @@ -10633,9 +11554,11 @@ abstract class GeometryArrayRetained extends GeometryRetained{ (((vertexFormat & GeometryArray.COLOR) != 0) && bit == GeometryArray.ALLOW_COLOR_WRITE)|| (((vertexFormat & GeometryArray.NORMALS) != 0) && - bit ==GeometryArray.ALLOW_NORMAL_WRITE) || - (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0)&& + bit == GeometryArray.ALLOW_NORMAL_WRITE) || + (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && bit == GeometryArray.ALLOW_TEXCOORD_WRITE) || + (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && + bit == GeometryArray.ALLOW_VERTEX_ATTR_WRITE) || (bit == GeometryArray.ALLOW_COUNT_WRITE)) { mask = 1; } @@ -10649,5 +11572,12 @@ abstract class GeometryArrayRetained extends GeometryRetained{ } } + int getTexCoordType() { + return texCoordType; + } + + int getVertexAttrType() { + return vertexAttrType; + } } diff --git a/src/classes/share/javax/media/j3d/GeometryDecompressorRetained.java b/src/classes/share/javax/media/j3d/GeometryDecompressorRetained.java index 6511553..e9cbdc8 100644 --- a/src/classes/share/javax/media/j3d/GeometryDecompressorRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryDecompressorRetained.java @@ -57,7 +57,7 @@ class GeometryDecompressorRetained extends GeometryDecompressor { // normal-per-vertex data collected from the HelloUniverse.cg file // (seagull, '57 Chevy, dinosaur). // - // TODO: get fudge values for other vertex combinations + // XXXX: get fudge values for other vertex combinations private static final float bytesPerVertexFudge = 5.3f ; // Used for benchmarking if so configured. diff --git a/src/classes/share/javax/media/j3d/GeometryRetained.java b/src/classes/share/javax/media/j3d/GeometryRetained.java index 2b0a39d..3def9c3 100644 --- a/src/classes/share/javax/media/j3d/GeometryRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryRetained.java @@ -229,12 +229,11 @@ abstract class GeometryRetained extends NodeComponentRetained { return 0 ; } - abstract boolean intersect(PickShape pickShape, double dist[], Point3d iPnt); + abstract boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt); abstract boolean intersect(Bounds targetBound); abstract boolean intersect(Point3d[] pnts); abstract boolean intersect(Transform3D thisToOtherVworld, GeometryRetained geom); - boolean intersect(Transform3D thisLocalToVworld, Transform3D otherLocalToVworld, GeometryRetained geom) { Transform3D tg = VirtualUniverse.mc.getTransform3D(null); @@ -256,15 +255,69 @@ abstract class GeometryRetained extends NodeComponentRetained { } + // Return a flag indicating whether or not this Geometry object can be in + // a display list. + // + // XXXX: Note that for IndexedGeometryArray objects, the original + // vertex format is used in making this determination, even when it has + // been unindexified. This should be fixed by using the vertex format of + // the mirror geometry if there is one. boolean canBeInDisplayList(boolean alphaEditable) { - - return (VirtualUniverse.mc.isDisplayList) && - !(this.isEditable || - (!(this instanceof GeometryArrayRetained) && alphaEditable)|| - (alphaEditable && ((((GeometryArrayRetained)this).vertexFormat& - GeometryArray.COLOR) != 0)) || - (((((GeometryArrayRetained)this).vertexFormat & - GeometryArray.BY_REFERENCE) != 0) && !VirtualUniverse.mc.buildDisplayListIfPossible)); + // Check global flag to see whether we can build display lists + if (!VirtualUniverse.mc.isDisplayList) { + return false; + } + + // Can't build display lists if geometry is editable + // XXXX: should look at isFrequent bit and allow DL if + // infrequently writable + if (this.isEditable) { + return false; + } + + if (this instanceof GeometryArrayRetained) { + int vFormat = ((GeometryArrayRetained)this).vertexFormat; + + // If geometry has vertex attributes, check whether + // vertex attributes are allowed in display lists + if (((vFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && + !VirtualUniverse.mc.vertexAttrsInDisplayList) { + return false; + } + + // Can't build display lists if alpha is editable and + // geometry array has colors + if (alphaEditable && ((vFormat & GeometryArray.COLOR) != 0)) { + return false; + } + + // Only build DL for by-ref geometry when system property is set. + // Exclude NIO buffers and use-coord-index-only + if ((vFormat & GeometryArray.BY_REFERENCE) != 0) { + if (!VirtualUniverse.mc.buildDisplayListIfPossible) { + return false; + } + + // XXXX: we could change this to allow display lists for + // non-interleaved NIO buffers, but we would first need to + // update the now-obsolete buildGAForBuffer method to handle + // vertex attrs + if ((vFormat & GeometryArray.USE_NIO_BUFFER) != 0) { + return false; + } + + if ((vFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) { + return false; + } + } + + return true; + } else { + // Can't build display lists for other kind of geometry + // NOTE: This method is not called for any type of Geometry + // other than GeometryArray, so we shouldn't even get here. + return false; + } } void computeCentroid() { diff --git a/src/classes/share/javax/media/j3d/GeometryStripArray.java b/src/classes/share/javax/media/j3d/GeometryStripArray.java index 39c4dde..88d927f 100644 --- a/src/classes/share/javax/media/j3d/GeometryStripArray.java +++ b/src/classes/share/javax/media/j3d/GeometryStripArray.java @@ -31,18 +31,15 @@ public abstract class GeometryStripArray extends GeometryArray { * Constructs an empty GeometryStripArray object with the specified * number of vertices, vertex format, and * array of per-strip vertex counts. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2 or TEXTURE_COORDINATE_3, to signal the - * inclusion of per-vertex texture coordinates 2D or 3D. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * * @param stripVertexCounts array that specifies * the count of the number of vertices for each separate strip. * The length of this array is the number of separate strips. @@ -50,7 +47,10 @@ public abstract class GeometryStripArray extends GeometryArray { * of valid vertices that are rendered (validVertexCount). * * @exception IllegalArgumentException if - * <code>validVertexCount > vertexCount</code> + * <code>validVertexCount > vertexCount</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public GeometryStripArray(int vertexCount, int vertexFormat, @@ -66,50 +66,21 @@ public abstract class GeometryStripArray extends GeometryArray { * sets, texture coordinate mapping array, and * array of per-strip vertex counts. * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2 or TEXTURE_COORDINATE_3, to signal the - * inclusion of per-vertex texture coordinates 2D or 3D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code> or - * <code>TEXTURE_COORDINATE_3</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code> or - * <code>TEXTURE_COORDINATE_3</code>, the - * <code>texCoordSetMap</code> array is not used.<p> + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. * * @param stripVertexCounts array that specifies * the count of the number of vertices for each separate strip. @@ -118,7 +89,10 @@ public abstract class GeometryStripArray extends GeometryArray { * of valid vertices that are rendered (validVertexCount). * * @exception IllegalArgumentException if - * <code>validVertexCount > vertexCount</code> + * <code>validVertexCount > vertexCount</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -134,6 +108,62 @@ public abstract class GeometryStripArray extends GeometryArray { } /** + * Constructs an empty GeometryStripArray object with the + * specified number of vertices, vertex format, number of texture + * coordinate sets, texture coordinate mapping array, vertex + * attribute count, vertex attribute sizes array, and array of + * per-strip vertex counts. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param stripVertexCounts array that specifies + * the count of the number of vertices for each separate strip. + * The length of this array is the number of separate strips. + * The sum of the elements in this array defines the total number + * of valid vertices that are rendered (validVertexCount). + * + * @exception IllegalArgumentException if + * <code>validVertexCount > vertexCount</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public GeometryStripArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int[] stripVertexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); + + ((GeometryStripArrayRetained)this.retained).setStripVertexCounts(stripVertexCounts); + } + + /** * Get number of strips in the GeometryStripArray. * @return numStrips number of strips */ diff --git a/src/classes/share/javax/media/j3d/GeometryStripArrayRetained.java b/src/classes/share/javax/media/j3d/GeometryStripArrayRetained.java index 1340be7..e6f83c0 100644 --- a/src/classes/share/javax/media/j3d/GeometryStripArrayRetained.java +++ b/src/classes/share/javax/media/j3d/GeometryStripArrayRetained.java @@ -46,9 +46,9 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { /** * Set stripVertexCount data into local array */ - void setStripVertexCounts(int stripVertexCounts[]){ - boolean nullGeo = false; - + void setStripVertexCounts(int stripVertexCounts[]) { + boolean nullGeo = false; + int i, num = stripVertexCounts.length, total = 0; for (i=0; i < num; i++) { total += stripVertexCounts[i]; @@ -72,28 +72,37 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { if ((initialVertexIndex + total) > vertexCount) { throw new IllegalArgumentException(J3dI18N.getString("GeometryStripArray3")); } - else if ((initialCoordIndex + total) > vertexCount) { + if ((initialCoordIndex + total) > vertexCount) { throw new IllegalArgumentException(J3dI18N.getString("GeometryStripArray7")); } - else if ((initialColorIndex + total) > vertexCount) { + if ((initialColorIndex + total) > vertexCount) { throw new IllegalArgumentException(J3dI18N.getString("GeometryStripArray4")); } - else if ((initialNormalIndex + total) > vertexCount) { + if ((initialNormalIndex + total) > vertexCount) { throw new IllegalArgumentException(J3dI18N.getString("GeometryStripArray5")); } - else { - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { - if ((vertexFormat & (GeometryArray.BY_REFERENCE|vertexFormat &GeometryArray.INTERLEAVED)) == GeometryArray.BY_REFERENCE) { - for (i = 0; i < texCoordSetCount; i++) { - if ((initialTexCoordIndex[i] + total) > vertexCount) { - throw new IllegalArgumentException(J3dI18N.getString( - "GeometryStripArray6")); - } - } - } - } - } - geomLock.getLock(); + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + if ((vertexFormat & (GeometryArray.BY_REFERENCE|vertexFormat &GeometryArray.INTERLEAVED)) == GeometryArray.BY_REFERENCE) { + for (i = 0; i < texCoordSetCount; i++) { + if ((initialTexCoordIndex[i] + total) > vertexCount) { + throw new IllegalArgumentException( + J3dI18N.getString("GeometryStripArray6")); + } + } + } + } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + if ((vertexFormat & (GeometryArray.BY_REFERENCE|vertexFormat &GeometryArray.INTERLEAVED)) == GeometryArray.BY_REFERENCE) { + for (i = 0; i < vertexAttrCount; i++) { + if ((initialVertexAttrIndex[i] + total) > vertexCount) { + throw new IllegalArgumentException( + J3dI18N.getString("GeometryStripArray8")); + } + } + } + } + + geomLock.getLock(); dirtyFlag |= STRIPCOUNT_CHANGED; validVertexCount = total; this.stripVertexCounts = new int[num]; @@ -139,7 +148,8 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { unIndexifyNIOBuffer(src); } } - void unIndexifyJavaArray(IndexedGeometryStripArrayRetained src) { + + private void unIndexifyJavaArray(IndexedGeometryStripArrayRetained src) { int vOffset = 0, srcOffset, tOffset = 0; int base = src.initialIndexIndex; int i,j, k, index, colorStride = 0; @@ -169,7 +179,8 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { src.indexNormal[index]*src.stride + src.normalOffset, vertexData, vOffset + normalOffset, 3); } - if (colorStride == 4) { + + if (colorStride == 4) { /* System.out.println("vdata.length = "+vdata.length); System.out.println("vertexData.length = "+vertexData.length); @@ -188,11 +199,12 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { vertexData, vOffset + colorOffset, colorStride); vertexData[vOffset + colorOffset + 3] = 1.0f; } - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { for (k = 0; k < texCoordSetCount; k++) { System.arraycopy(vdata, - (((int[])src.indexTexCoord[k])[index]) - *src.stride + src.textureOffset + + (src.indexTexCoord[k][index]) + * src.stride + src.textureOffset + src.texCoordSetMapOffset[k], vertexData, vOffset + textureOffset + @@ -201,7 +213,17 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { } } - if ((vertexFormat & GeometryArray.COORDINATES) != 0){ + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (k = 0; k < vertexAttrCount; k++) { + System.arraycopy(vdata, + src.indexVertexAttr[k][index] * src.stride + src.vertexAttrOffsets[k], + vertexData, + vOffset + vertexAttrOffsets[k], + vertexAttrSizes[k]); + } + } + + if ((vertexFormat & GeometryArray.COORDINATES) != 0) { System.arraycopy(vdata, src.indexCoord[index]*src.stride + src.coordinateOffset, vertexData, vOffset + coordinateOffset, 3); @@ -245,7 +267,8 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { break; } } - if ((vertexFormat & GeometryArray.COLOR) != 0){ + + if ((vertexFormat & GeometryArray.COLOR) != 0){ base = src.initialIndexIndex; vOffset = colorOffset; int multiplier = 3; @@ -351,7 +374,8 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { break; } } - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { base = src.initialIndexIndex; vOffset = textureOffset; switch ((src.vertexType & TEXCOORD_DEFINED)) { @@ -363,7 +387,7 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { for (k = 0, tOffset = vOffset; k < texCoordSetCount; k++) { System.arraycopy(src.refTexCoords[k], - ((int[])src.indexTexCoord[k])[index] + src.indexTexCoord[k][index] *texCoordStride, vertexData, tOffset, texCoordStride); tOffset += texCoordStride; @@ -380,7 +404,7 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { for (k = 0, tOffset = vOffset; k < texCoordSetCount; k++) { srcOffset = - ((int[])src.indexTexCoord[k])[index]; + src.indexTexCoord[k][index]; vertexData[tOffset] = ((TexCoord2f[]) src.refTexCoords[k])[srcOffset].x; vertexData[tOffset+1] = ((TexCoord2f[]) @@ -399,7 +423,7 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { for (k = 0, tOffset = vOffset; k < texCoordSetCount; k++) { srcOffset = - ((int[])src.indexTexCoord[k])[index]; + src.indexTexCoord[k][index]; vertexData[tOffset] = ((TexCoord3f[]) src.refTexCoords[k])[srcOffset].x; vertexData[tOffset+1] = ((TexCoord3f[]) @@ -417,7 +441,32 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { default: break; } - } + } + + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + base = src.initialIndexIndex; + vOffset = 0; + switch (src.vertexType & VATTR_DEFINED) { + case AF: + for (i=0; i < src.stripIndexCounts.length; i++) { + for (j=0; j < src.stripIndexCounts[i]; j++) { + index = j+base; + + for (k = 0; k < vertexAttrCount; k++) { + System.arraycopy(src.floatRefVertexAttrs[k], + src.indexVertexAttr[k][index]*vertexAttrSizes[k], + vertexData, + vOffset + vertexAttrOffsets[k], + vertexAttrSizes[k]); + } + vOffset += stride; + } + base += src.stripIndexCounts[i]; + } + break; + } + } + if ((vertexFormat & GeometryArray.COORDINATES) != 0){ vOffset = coordinateOffset; base = src.initialIndexIndex; @@ -477,9 +526,9 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { } } } - - void unIndexifyNIOBuffer(IndexedGeometryStripArrayRetained src) { - int vOffset = 0, srcOffset, tOffset = 0; + + private void unIndexifyNIOBuffer(IndexedGeometryStripArrayRetained src) { + int vOffset = 0, srcOffset, tOffset = 0; int base = src.initialIndexIndex; int i,j, k, index, colorStride = 0; @@ -506,9 +555,10 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { src.interleavedFloatBufferImpl.get(vertexData, vOffset + colorOffset, colorStride); vertexData[vOffset + colorOffset + 3] = 1.0f; } - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { for (k = 0; k < texCoordSetCount; k++) { - src.interleavedFloatBufferImpl.position((((int[])src.indexTexCoord[k])[index]) + src.interleavedFloatBufferImpl.position((src.indexTexCoord[k][index]) *src.stride + src.textureOffset + src.texCoordSetMapOffset[k]); @@ -527,7 +577,7 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { } } else { - if ((vertexFormat & GeometryArray.NORMALS) != 0){ + if ((vertexFormat & GeometryArray.NORMALS) != 0) { base = src.initialIndexIndex; vOffset = normalOffset; if((src.vertexType & NORMAL_DEFINED) != 0) { @@ -542,7 +592,8 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { } } } - if ((vertexFormat & GeometryArray.COLOR) != 0){ + + if ((vertexFormat & GeometryArray.COLOR) != 0) { base = src.initialIndexIndex; vOffset = colorOffset; int multiplier = 3; @@ -593,7 +644,8 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { break; } } - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + + if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { base = src.initialIndexIndex; vOffset = textureOffset; FloatBufferWrapper texBuffer; @@ -605,7 +657,7 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { for (k = 0, tOffset = vOffset; k < texCoordSetCount; k++) { texBuffer = (FloatBufferWrapper)(((J3DBuffer) (src.refTexCoordsBuffer[k])).getBufferImpl()); - texBuffer.position(((int[])src.indexTexCoord[k])[index]*texCoordStride); + texBuffer.position(src.indexTexCoord[k][index]*texCoordStride); texBuffer.get(vertexData, tOffset, texCoordStride); tOffset += texCoordStride; } @@ -614,8 +666,30 @@ abstract class GeometryStripArrayRetained extends GeometryArrayRetained { base += src.stripIndexCounts[i]; } } - } - if ((vertexFormat & GeometryArray.COORDINATES) != 0){ + } + + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + base = src.initialIndexIndex; + vOffset = 0; + if((src.vertexType & VATTR_DEFINED) == AF) { + for (i=0; i < src.stripIndexCounts.length; i++) { + for (j=0; j < src.stripIndexCounts[i]; j++) { + index = j+base; + + for (k = 0; k < vertexAttrCount; k++) { + int vaOffset = vOffset + vertexAttrOffsets[k]; + FloatBufferWrapper vaBuffer = src.floatBufferRefVertexAttrs[k]; + vaBuffer.position(src.indexVertexAttr[k][index]*vertexAttrSizes[k]); + vaBuffer.get(vertexData, vaOffset, vertexAttrSizes[k]); + } + vOffset += stride; + } + base += src.stripIndexCounts[i]; + } + } + } + + if ((vertexFormat & GeometryArray.COORDINATES) != 0) { vOffset = coordinateOffset; base = src.initialIndexIndex; switch ((src.vertexType & VERTEX_DEFINED)) { diff --git a/src/classes/share/javax/media/j3d/GeometryStructure.java b/src/classes/share/javax/media/j3d/GeometryStructure.java index 7bb9552..b8d7e0d 100644 --- a/src/classes/share/javax/media/j3d/GeometryStructure.java +++ b/src/classes/share/javax/media/j3d/GeometryStructure.java @@ -168,7 +168,6 @@ class GeometryStructure extends J3dStructure { case J3dMessage.MORPH_CHANGED: { int comp = ((Integer)m.args[1]).intValue(); if (comp == MorphRetained.GEOMETRY_CHANGED) { - // TODO: Optimize this case. processBoundsChanged((Object []) m.args[3], false); } else if (comp == MorphRetained.APPEARANCE_CHANGED) { diff --git a/src/classes/share/javax/media/j3d/GraphStructureChangeListener.java b/src/classes/share/javax/media/j3d/GraphStructureChangeListener.java new file mode 100755 index 0000000..c0a50a0 --- /dev/null +++ b/src/classes/share/javax/media/j3d/GraphStructureChangeListener.java @@ -0,0 +1,54 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Listener interface for monitoring structural changes to live scene + * graphs. BranchGroup additions, removals and moves are reported. + * + * @see VirtualUniverse#addGraphStructureChangeListener + * + * @since Java 3D 1.4 + */ +public interface GraphStructureChangeListener { + /** + * Invoked when a branch group is added. + * Called just before the child is added to the parent. + * Parent can be either a BranchGroup or a Locale. + * + * @param parent the parent of the child being added + * @param child the child being added + */ + public void branchGroupAdded(Object parent, BranchGroup child); + + /** + * Invoked when a branch group is removed. + * Called just after the child has been removed from the parent. + * Parent can be either a BranchGroup or a Locale. + * + * @param parent the parent of the child being added + * @param child the child being added + */ + public void branchGroupRemoved(Object parent, BranchGroup child); + + /** + * Invoked when a branch group is moved. + * Called after a child has been moved to it's new parent. This call differs + * from the other methods in that the child is live when this method is called. + * + * @param oldParent the original parent of the child being moved + * @param newParent the new parent of the child being moved + * @param child the child being moved + */ + public void branchGroupMoved(Object oldParent, Object newParent, BranchGroup child); +} diff --git a/src/classes/share/javax/media/j3d/GraphicsConfigInfo.java b/src/classes/share/javax/media/j3d/GraphicsConfigInfo.java new file mode 100644 index 0000000..7d9e04f --- /dev/null +++ b/src/classes/share/javax/media/j3d/GraphicsConfigInfo.java @@ -0,0 +1,35 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +class GraphicsConfigInfo { + private int reqStencilSize = 0; + private long fbConfig = 0L; + + int getRequestedStencilSize() { + return reqStencilSize; + } + + void setRequestedStencilSize(int reqSS) { + reqStencilSize = reqSS; + } + + long getFBConfig() { + return fbConfig; + } + + void setFBConfig(long fbC) { + fbConfig = fbC; + } + +} diff --git a/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java b/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java index 8b59219..38e8156 100644 --- a/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java +++ b/src/classes/share/javax/media/j3d/GraphicsConfigTemplate3D.java @@ -39,6 +39,7 @@ public class GraphicsConfigTemplate3D extends GraphicsConfigTemplate { int redSize; int sceneAntialiasing; int stereo; + int stencilSize; // Temporary variables use for passing argument to/from Request Renderer Object testCfg; @@ -66,12 +67,14 @@ public class GraphicsConfigTemplate3D extends GraphicsConfigTemplate { * redSize : 2<br> * greenSize : 2<br> * blueSize : 2<br> + * stencilSize : 0<br> * </ul> */ public GraphicsConfigTemplate3D() { doubleBuffer = REQUIRED; stereo = UNNECESSARY; depthSize = 16; + stencilSize = 0; redSize = greenSize = blueSize = 2; sceneAntialiasing = UNNECESSARY; } @@ -172,6 +175,35 @@ public class GraphicsConfigTemplate3D extends GraphicsConfigTemplate { } /** + * Sets the stencil buffer size requirement. + * This is the minimum requirement. + * If no GraphicsConfiguration is found that meets or + * exceeds this minimum requirement, null will be returned in + * getBestConfiguration(). + * + * @param value the value to set this field to + * + * @since Java 3D 1.4 + */ + public void setStencilSize(int value) { + if (value < 0) + return; + + stencilSize = value; + } + + /** + * Retrieves the size of the stencil buffer. + * + * @return the current value of the stencilSize attribute + * + * @since Java 3D 1.4 + */ + public int getStencilSize() { + return stencilSize; + } + + /** * Sets the number of red bits required. This is the minimum requirement. * If no GraphicsConfiguration is found that meets or * exceeds this minimum requirement, null will be returned in @@ -298,7 +330,8 @@ public class GraphicsConfigTemplate3D extends GraphicsConfigTemplate { if (gc == null) { return false; } - synchronized (globalLock) { + + synchronized (globalLock) { testCfg = gc; threadWaiting = true; if (Thread.currentThread() instanceof BehaviorScheduler) { diff --git a/src/classes/share/javax/media/j3d/GraphicsContext3D.java b/src/classes/share/javax/media/j3d/GraphicsContext3D.java index b5c7516..003134f 100644 --- a/src/classes/share/javax/media/j3d/GraphicsContext3D.java +++ b/src/classes/share/javax/media/j3d/GraphicsContext3D.java @@ -183,7 +183,7 @@ public class GraphicsContext3D extends Object { boolean lightsChanged = false; // A boolean that indicates the sounds have changed - // TODO: the soundsChanged flag are set like lights methods set + // XXXX: the soundsChanged flag are set like lights methods set // lightsChanged? but where is this supposed to be check??? // lightsChanged tested in 'draw'; but Sound are not processed // in draw. @@ -285,27 +285,29 @@ public class GraphicsContext3D extends Object { // when a new command is to be // added to the list - static Integer commands[] = new Integer[NCOMMANDS]; - static Integer stereoModes[] = {new Integer(STEREO_LEFT), - new Integer(STEREO_RIGHT), - new Integer(STEREO_BOTH)}; + private static Integer[] commands = new Integer[NCOMMANDS]; + private static Integer[] stereoModes = { + new Integer(STEREO_LEFT), + new Integer(STEREO_RIGHT), + new Integer(STEREO_BOTH) + }; // dirty bits - static final int BUFFER_MODE = 0x1; + private static final int BUFFER_MODE = 0x1; private int dirtyMask = 0; // multi-texture - int numActiveTexUnit = 0; - int lastActiveTexUnitIndex = 0; - boolean toSimulateMultiTex = true; + private int numActiveTexUnit = 0; + private int lastActiveTexUnitIndex = 0; + private boolean toSimulateMultiTex = false; // for read raster - volatile boolean readRasterReady = false; + private volatile boolean readRasterReady = false; // for runMonitor - boolean gcReady = false; - int waiting = 0; + private boolean gcReady = false; + private int waiting = 0; /** @@ -381,7 +383,12 @@ public class GraphicsContext3D extends Object { enableLighting = false; } - if (((AppearanceRetained)appearance.retained).texUnitState != null) { + if (appearance instanceof ShaderAppearance) { + // TODO : handle ShaderProgram and ShaderAttributeSet + System.err.println("ShaderProgram not implemented for immediate mode rendering"); + } + + if (((AppearanceRetained)appearance.retained).texUnitState != null) { TextureUnitStateRetained[] texUnitState = ((AppearanceRetained)appearance.retained).texUnitState; @@ -626,9 +633,8 @@ public class GraphicsContext3D extends Object { if (fog != null) { ((FogRetained)fog.retained).setInImmCtx(true); - - if (fog.retained instanceof LinearFogRetained) - updateFogState((LinearFogRetained)fog.retained); + // Issue 144: updateFogState now called unconditionally + updateFogState((FogRetained)fog.retained); } } @@ -912,8 +918,9 @@ public class GraphicsContext3D extends Object { } - void updateFogState(LinearFogRetained lfog) { - lfog.localToVworldScale = modelTransform.getDistanceScale(); + void updateFogState(FogRetained fogRet) { + // Issue 144: update localToVWorldScale for all types of Fog + fogRet.setLocalToVworldScale(modelTransform.getDistanceScale()); } @@ -1280,7 +1287,7 @@ public class GraphicsContext3D extends Object { if (view != null) { SoundScheduler soundScheduler = getSoundScheduler(); if (soundScheduler == null) { - // TODO: Re-implement + // XXXX: Re-implement // start up SoundScheduler since it hasn't already been started } } @@ -1291,13 +1298,13 @@ public class GraphicsContext3D extends Object { this.modelTransform.transform(cs.direction, cs.xformDirection); cs.xformDirection.normalize(); this.modelTransform.transform(cs.position, cs.xformPosition); - // TODO (Question) Is drawTranform equivalent to Vworld-to-Local? + // XXXX (Question) Is drawTranform equivalent to Vworld-to-Local? cs.trans.setWithLock(drawTransform); } else if (sound instanceof PointSoundRetained) { PointSoundRetained ps = (PointSoundRetained) sound; this.modelTransform.transform(ps.position, ps.xformPosition); - // TODO (Question) Is drawTranform equivalent to Vworld-to-Local? + // XXXX (Question) Is drawTranform equivalent to Vworld-to-Local? ps.trans.setWithLock(drawTransform); } } @@ -1559,7 +1566,7 @@ public class GraphicsContext3D extends Object { else back = this.black; - // TODO: This should ideally be done by the renderer (or by the + // XXXX: This should ideally be done by the renderer (or by the // canvas itself) when the canvas is first added to a view. /* if ((canvas3d.screen.renderer != null) && @@ -1575,7 +1582,7 @@ public class GraphicsContext3D extends Object { try { if (canvas3d.drawingSurfaceObject.renderLock()) { - // TODO : Fix texture + // XXXX : Fix texture /* if (canvas3d.useSharedCtx) { if (canvas3d.screen.renderer.sharedCtx == 0) { @@ -1594,13 +1601,7 @@ public class GraphicsContext3D extends Object { if (canvas3d.ctx == 0) { synchronized (VirtualUniverse.mc.contextCreationLock) { - canvas3d.ctx = - canvas3d.createNewContext(canvas3d.screen.display, - canvas3d.window, - canvas3d.vid, - canvas3d.fbConfig, - 0, false, - canvas3d.offScreen); + canvas3d.ctx = canvas3d.createNewContext(0, false); if (canvas3d.ctx == 0) { canvas3d.drawingSurfaceObject.unLock(); return; @@ -1608,8 +1609,8 @@ public class GraphicsContext3D extends Object { canvas3d.ctxTimeStamp = VirtualUniverse.mc.getContextTimeStamp(); - canvas3d.screen.renderer.listOfCtxs.add( - new Long(canvas3d.ctx)); + canvas3d.screen.renderer.listOfCtxs.add( + new Long(canvas3d.ctx)); canvas3d.screen.renderer.listOfCanvases.add(canvas3d); canvas3d.beginScene(); @@ -1618,43 +1619,21 @@ public class GraphicsContext3D extends Object { canvas3d.graphics2D.init(); } - // query for the number of texture units - // supported - if (canvas3d.multiTexAccelerated) { - canvas3d.numTexUnitSupported = - canvas3d.getTextureUnitCount(canvas3d.ctx); - } - - // enable separate specular color + // enable separate specular color canvas3d.enableSeparateSpecularColor(); } // create the cache texture state in canvas // for state download checking purpose - if (canvas3d.texUnitState == null) { - canvas3d.texUnitState = - new TextureUnitStateRetained[ - canvas3d.numTexUnitSupported]; - for (int t = 0; t < canvas3d.numTexUnitSupported; t++) { - canvas3d.texUnitState[t] = - new TextureUnitStateRetained(); - canvas3d.texUnitState[t].texture = null; - canvas3d.texUnitState[t].mirror = null; - } + canvas3d.createTexUnitState(); } - - // also create the texture unit state map - // which is a mapping from texture unit state to - // the actual underlying texture unit - + // Create the texture unit state map if (canvas3d.texUnitStateMap == null) { - canvas3d.texUnitStateMap = - new int[canvas3d.numTexUnitSupported]; + canvas3d.createTexUnitStateMap(); } - canvas3d.drawingSurfaceObject.contextValidated(); canvas3d.screen.renderer.currentCtx = canvas3d.ctx; initializeState(); @@ -1830,7 +1809,7 @@ public class GraphicsContext3D extends Object { // rb.setVworldToVpc(vp.getVworldToVpc()); // rb.setVpcToVworld(vp.getVpcToVworld()); - // TODO: Fix this + // XXXX: Fix this rb.vpcToVworld = vpR.getVpcToVworld(); rb.vworldToVpc = vpR.getVworldToVpc(); @@ -1890,7 +1869,7 @@ public class GraphicsContext3D extends Object { switch(stereoMode) { case STEREO_RIGHT: vpcToEc = cvCache.getRightVpcToEc(); - // TODO: move this under check for + // XXXX: move this under check for // (dirtyMask & BUFFER_MODE) above after testing // PureImmediate mode canvas3d.setProjectionMatrix(canvas3d.ctx, @@ -1901,7 +1880,7 @@ public class GraphicsContext3D extends Object { case STEREO_BOTH: default: vpcToEc = cvCache.getLeftVpcToEc(); - // TODO: move this under check for + // XXXX: move this under check for // (dirtyMask & BUFFER_MODE) above after testing // PureImmediate mode canvas3d.setProjectionMatrix(canvas3d.ctx, @@ -2000,7 +1979,7 @@ public class GraphicsContext3D extends Object { if ((geometry.retained instanceof IndexedGeometryArrayRetained) && ((((GeometryArrayRetained)geometry.retained).vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0)) { if (geoRetained.dirtyFlag != 0) { - geoRetained.mirrorGeometry = (GeometryRetained) + geoRetained.mirrorGeometry = ((IndexedGeometryArrayRetained)geoRetained).cloneNonIndexedGeometry(); // Change the source geometry dirtyFlag // drawGeo.execute() will change the @@ -2030,7 +2009,7 @@ public class GraphicsContext3D extends Object { drawGeo = (GeometryRetained)geometry.retained; } - if (!toSimulateMultiTex) { + if (!toSimulateMultiTex) { drawGeo.execute(canvas3d, null, isNonUniformScale, false, alpha, ((canvas3d.view.getScreens()).length > 1), @@ -2038,30 +2017,19 @@ public class GraphicsContext3D extends Object { ignoreVertexColors, -1); } else { - // TODO: need to leverage the code in textureBin + // NOTE: we really should leverage the code in textureBin boolean startToSimulate = false; - if (numActiveTexUnit < 1) { - // no active texture unit - drawGeo.execute(canvas3d, null, isNonUniformScale, - false, alpha, - ((canvas3d.view.getScreens()).length > 1), - canvas3d.screen.screen, - ignoreVertexColors, - 0); - } else if (numActiveTexUnit == 1) { - // one active texture unit - drawGeo.execute(canvas3d, null, isNonUniformScale, - false, alpha, - ((canvas3d.view.getScreens()).length > 1), - canvas3d.screen.screen, - ignoreVertexColors, - lastActiveTexUnitIndex); - } else { + // simulate multiple texture units - AppearanceRetained app = - (AppearanceRetained)appearance.retained; + AppearanceRetained app = + (AppearanceRetained)appearance.retained; + + assert VirtualUniverse.mc.allowSimulatedMultiTexture; + assert numActiveTexUnit > 1; + assert app.texUnitState != null; + assert app.texUnitState.length > 1; - // first turn off fog + // first turn off fog if (fog != null) canvas3d.setFogEnableFlag(canvas3d.ctx, false); @@ -2088,16 +2056,20 @@ public class GraphicsContext3D extends Object { // adjust the depth test back to what it was // and adjust the blend func to what it it was - if (startToSimulate) { - app.transparencyAttributes.updateNative( - canvas3d.ctx, alpha, geometryType, - polygonMode, lineAA, pointAA); - } + if (startToSimulate) { + if (app.transparencyAttributes != null) { + app.transparencyAttributes.updateNative( + canvas3d.ctx, alpha, geometryType, + polygonMode, lineAA, pointAA); + } else { + canvas3d.resetTransparency(canvas3d.ctx, geometryType, + polygonMode, lineAA, pointAA); + } + } if (fog != null) { canvas3d.setFogEnableFlag(canvas3d.ctx, true); } - } } if (geoRetained != null) geoRetained.geomLock.unLock(); @@ -2229,7 +2201,7 @@ public class GraphicsContext3D extends Object { throw new IllegalSharingException(J3dI18N.getString("GraphicsContext3D21")); } - // TODO: implement illegal argument exception + // XXXX: implement illegal argument exception /* if (ras.image.byReference && !(ras.image.imageReference instanceof BufferedImage)) { @@ -2419,7 +2391,7 @@ public class GraphicsContext3D extends Object { if (canvas3d.enableMask != enableMask) { canvas3d.canvasDirty |= Canvas3D.LIGHTENABLES_DIRTY; - // TODO: 32 => renderBin.maxLights + // XXXX: 32 => renderBin.maxLights canvas3d.setLightEnables(canvas3d.ctx, enableMask, 32); canvas3d.enableMask = enableMask; } @@ -2481,16 +2453,16 @@ public class GraphicsContext3D extends Object { boolean updateState(RenderBin rb, int geometryType) { - boolean useAlpha = false;; - toSimulateMultiTex = true; - numActiveTexUnit = 0; + boolean useAlpha = false; + toSimulateMultiTex = false; + numActiveTexUnit = 0; lastActiveTexUnitIndex = 0; // Update Appearance if (appearance != null) { AppearanceRetained app = (AppearanceRetained) appearance.retained; - // If the material is not null then check if the one in the canvas + // If the material is not null then check if the one in the canvas // is equivalent to the one being sent down. If Yes, do nothing // Otherwise, cache the sent down material and mark the canvas // dirty flag so that the compiled/compiled-retained rendering @@ -2514,75 +2486,95 @@ public class GraphicsContext3D extends Object { } } + // Set flag indicating whether we are using shaders + boolean useShaders = false; + if (app instanceof ShaderAppearanceRetained) { + if (((ShaderAppearanceRetained)app).shaderProgram != null) { + useShaders = true; + } + } + + // Set the number of available texture units; this depends on + // whether or not shaders are being used. + int availableTextureUnits = + useShaders ? canvas3d.maxTextureImageUnits : canvas3d.maxTextureUnits; + int prevNumActiveTexUnit = canvas3d.getNumActiveTexUnit(); + // Get the number of active texture units. + // Note that this total number now includes disabled units. if (app.texUnitState != null) { - boolean d3dBlendMode = false; - TextureUnitStateRetained tus; for (int i = 0; i < app.texUnitState.length; i++) { tus = app.texUnitState[i]; if (tus != null && tus.isTextureEnabled()) { - numActiveTexUnit++; lastActiveTexUnitIndex = i; - useAlpha = useAlpha || - (tus.texAttrs.textureMode == - TextureAttributes.BLEND); - if (tus.needBlend2Pass(canvas3d)) { - // use multi-pass if one of the stage use blend mode - d3dBlendMode = true; - } + numActiveTexUnit = i + 1; + if (tus.texAttrs != null) { + useAlpha = useAlpha || + (tus.texAttrs.textureMode == + TextureAttributes.BLEND); + } } } - if (canvas3d.numTexUnitSupported >= numActiveTexUnit && - canvas3d.multiTexAccelerated && !d3dBlendMode) { - - int j = 0; + if (numActiveTexUnit <= availableTextureUnits) { + // Normal, single-pass rendering case // update all active texture unit states - for (int i = 0; i < app.texUnitState.length; i++) { - if ((app.texUnitState[i] != null) && + if (i >= availableTextureUnits) { + // This can happen if there are disabled units at + // the end of the array + break; + } + + if ((app.texUnitState[i] != null) && app.texUnitState[i].isTextureEnabled()) { - app.texUnitState[i].updateNative(j, canvas3d, + app.texUnitState[i].updateNative(i, canvas3d, false, false); - canvas3d.setTexUnitStateMap(i, j++); - } + } else { + canvas3d.resetTexture(canvas3d.ctx, i); + } } // reset the remaining texture units - - for (int i = j; i < prevNumActiveTexUnit; i++) { - if (canvas3d.texUnitState[i].texture != null) { - canvas3d.resetTexture(canvas3d.ctx, i); - canvas3d.texUnitState[i].texture = null; - } + for (int i = app.texUnitState.length; i < prevNumActiveTexUnit; i++) { + canvas3d.resetTexture(canvas3d.ctx, i); } // set the number active texture unit in Canvas3D canvas3d.setNumActiveTexUnit(numActiveTexUnit); - // set the active texture unit back to 0 - canvas3d.activeTextureUnit(canvas3d.ctx, 0); - - toSimulateMultiTex = false; - - } else { + } else if (!useShaders && VirtualUniverse.mc.allowSimulatedMultiTexture) { + // Simulated (multi-pass) multi-texture rendering + + toSimulateMultiTex = true; // will fall back to the multi-pass case; // reset all the texture units first + for (int i = 0; i < prevNumActiveTexUnit; i++) { + canvas3d.resetTexture(canvas3d.ctx, i); + } + // set the number active texture unit in Canvas3D + canvas3d.setNumActiveTexUnit(1); + } + else { + // Exceeded limit, and not using simulated multi-texture + + // disable all the texture units for (int i = 0; i < prevNumActiveTexUnit; i++) { - if (canvas3d.texUnitState[i].texture != null) { - canvas3d.resetTexture(canvas3d.ctx, i); - canvas3d.texUnitState[i].texture = null; - } + canvas3d.resetTexture(canvas3d.ctx, i); } + canvas3d.setNumActiveTexUnit(0); } + + // set the active texture unit back to 0 + canvas3d.activeTextureUnit(canvas3d.ctx, 0); } else { - // if texUnitState is null, let's disable + // if texUnitState is null, let's disable // all texture units first if (canvas3d.multiTexAccelerated) { if (canvas3d.texUnitState != null) { @@ -2599,9 +2591,9 @@ public class GraphicsContext3D extends Object { canvas3d.activeTextureUnit(canvas3d.ctx, 0); } - if ((canvas3d.texUnitState != null) && - (canvas3d.texUnitState[0] != null) && - (canvas3d.texUnitState[0].texture != app.texture)) { + if ((canvas3d.texUnitState != null) && + (canvas3d.texUnitState[0] != null) && + (canvas3d.texUnitState[0].texture != app.texture)) { // If the image is by reference, check if the image // should be processed @@ -2616,7 +2608,6 @@ public class GraphicsContext3D extends Object { } } app.texture.updateNative(canvas3d); - canvas3d.setTexUnitStateMap(0, 0); canvas3d.canvasDirty |= Canvas3D.TEXTUREBIN_DIRTY|Canvas3D.TEXTUREATTRIBUTES_DIRTY; numActiveTexUnit = 1; lastActiveTexUnitIndex = 0; @@ -2728,7 +2719,7 @@ public class GraphicsContext3D extends Object { if (app.renderingAttributes != null) { ignoreVertexColors =app.renderingAttributes.ignoreVertexColors; - app.renderingAttributes.updateNative(canvas3d.ctx, + app.renderingAttributes.updateNative(canvas3d, canvas3d.depthBufferWriteEnableOverride, canvas3d.depthBufferEnableOverride); canvas3d.canvasDirty |= Canvas3D.ATTRIBUTEBIN_DIRTY|Canvas3D.TEXTUREATTRIBUTES_DIRTY; diff --git a/src/classes/share/javax/media/j3d/Group.java b/src/classes/share/javax/media/j3d/Group.java index c7a71f2..b5c763b 100644 --- a/src/classes/share/javax/media/j3d/Group.java +++ b/src/classes/share/javax/media/j3d/Group.java @@ -60,6 +60,13 @@ public class Group extends Node { ALLOW_COLLISION_BOUNDS_WRITE = CapabilityBits.GROUP_ALLOW_COLLISION_BOUNDS_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_CHILDREN_READ, + ALLOW_COLLISION_BOUNDS_READ + }; + + /** * Creates the retained mode GroupRetained object that this * Group component object will point to. @@ -528,5 +535,7 @@ public class Group extends Node { * </ul> */ public Group() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } } diff --git a/src/classes/share/javax/media/j3d/GroupRetained.java b/src/classes/share/javax/media/j3d/GroupRetained.java index b300758..da9155a 100644 --- a/src/classes/share/javax/media/j3d/GroupRetained.java +++ b/src/classes/share/javax/media/j3d/GroupRetained.java @@ -238,6 +238,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { if(oldchildr != null) { oldchildr.setParent(null); checkClearLive(oldchildr, messages, 0, index, null); + universe.notifyStructureChangeListeners(false, this.source, (BranchGroup)oldchildr.source); } removeChildrenData(index); @@ -249,6 +250,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { return; } + universe.notifyStructureChangeListeners(true, this.source, (BranchGroup)child); NodeRetained childr = (NodeRetained) child.retained; childr.setParent(this); children.set(index, childr); @@ -276,6 +278,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { + universe.notifyStructureChangeListeners(true, this.source, (BranchGroup)child); doInsertChild(child, index); universe.setLiveState.clear(); } @@ -324,8 +327,10 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { + NodeRetained childr = (NodeRetained)children.get(index); doRemoveChild(index, null, 0); universe.setLiveState.clear(); + universe.notifyStructureChangeListeners(false, this.source, (BranchGroup)childr.source); } universe.waitForMC(); } else { @@ -454,6 +459,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { + universe.notifyStructureChangeListeners(true, this.source, (BranchGroup)child); doAddChild(child, null, 0); universe.setLiveState.clear(); } @@ -492,8 +498,13 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { if (this.source.isLive()) { universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { + GroupRetained oldParent = (GroupRetained)((BranchGroupRetained)bg.retained).parent; doMoveTo(bg); universe.setLiveState.clear(); + if (oldParent==null) + universe.notifyStructureChangeListeners(((BranchGroupRetained)bg.retained).locale, this.source, bg); + else + universe.notifyStructureChangeListeners(oldParent.source, this.source, bg); } universe.waitForMC(); } else { @@ -632,7 +643,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } /* - // TODO: lights may remove twice or more during clearLive(), + // XXXX: lights may remove twice or more during clearLive(), // one from itself and one call from every LightRetained // reference this. So there is case that this procedure get // called when light already removed. @@ -1828,7 +1839,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } s.transformTargets = newTargets; - // TODO - optimization for targetThreads computation, require + // XXXX: optimization for targetThreads computation, require // cleanup in GroupRetained.doSetLive() //s.transformTargetThreads = 0; } @@ -2441,14 +2452,23 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { return super.getEffectiveBounds(); } - // returns true if children cannot be read/written + // returns true if children cannot be read/written and none of the + // children can read their parent (i.e., "this") group node boolean isStaticChildren() { if (source.getCapability(Group.ALLOW_CHILDREN_READ) || source.getCapability(Group.ALLOW_CHILDREN_WRITE)) { return false; } + + for (int i = children.size() - 1; i >= 0; i--) { + SceneGraphObjectRetained nodeR = + (SceneGraphObjectRetained) children.get(i); + if (nodeR != null && nodeR.source.getCapability(Node.ALLOW_PARENT_READ)) { + return false; + } + } + return true; - } @@ -2644,7 +2664,7 @@ class GroupRetained extends NodeRetained implements BHLeafInterface { } } // Has its own copy - // TODO: Handle the case of + // XXXX: Handle the case of // was non-zero, gone to zero? if (savedParentLights != null) { if (allocatedLights) { diff --git a/src/classes/share/javax/media/j3d/ImageComponent.java b/src/classes/share/javax/media/j3d/ImageComponent.java index 37f4530..4f927cf 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent.java +++ b/src/classes/share/javax/media/j3d/ImageComponent.java @@ -195,10 +195,19 @@ public abstract class ImageComponent extends NodeComponent { public static final int ALLOW_IMAGE_WRITE = CapabilityBits.IMAGE_COMPONENT_ALLOW_IMAGE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SIZE_READ, + ALLOW_SIZE_READ, + ALLOW_FORMAT_READ + }; + /** * Not a public constructor, for internal use */ ImageComponent() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -220,6 +229,9 @@ public abstract class ImageComponent extends NodeComponent { * width or height are not positive. */ public ImageComponent(int format, int width, int height) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ImageComponentRetained)this.retained).processParams(format, width, height, 1); } @@ -249,6 +261,8 @@ public abstract class ImageComponent extends NodeComponent { int height, boolean byReference, boolean yUp) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); ((ImageComponentRetained)this.retained).setYUp(yUp); ((ImageComponentRetained)this.retained).setByReference(byReference); diff --git a/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java b/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java index 809884d..6037355 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java +++ b/src/classes/share/javax/media/j3d/ImageComponent2DRetained.java @@ -171,7 +171,7 @@ class ImageComponent2DRetained extends ImageComponentRetained { ((biType == BufferedImage.TYPE_BYTE_GRAY) && (format == ImageComponent.FORMAT_CHANNEL8)) || (is4ByteRGBAOr3ByteRGB(ri))) { - /* ||TODO: Don't do short for now! + /* ||XXXX: Don't do short for now! ((biType == BufferedImage.TYPE_USHORT_GRAY) && (format == ImageComponent.FORMAT_CHANNEL8) */ @@ -1293,7 +1293,7 @@ class ImageComponent2DRetained extends ImageComponentRetained { if (source.isLive()) { - //TODO: check whether this is needed + //XXXX: check whether this is needed freeSurface(); // send a SUBIMAGE_CHANGED message in order to @@ -1336,7 +1336,7 @@ class ImageComponent2DRetained extends ImageComponentRetained { if (source.isLive()) { - // TODO: check whether this is needed + // XXXX: check whether this is needed freeSurface(); // send a SUBIMAGE_CHANGED message in order to diff --git a/src/classes/share/javax/media/j3d/ImageComponent3D.java b/src/classes/share/javax/media/j3d/ImageComponent3D.java index 1cb4d9b..224d1f5 100644 --- a/src/classes/share/javax/media/j3d/ImageComponent3D.java +++ b/src/classes/share/javax/media/j3d/ImageComponent3D.java @@ -622,7 +622,7 @@ public class ImageComponent3D extends ImageComponent { rt.height, rt.depth); - // TODO : replace by this to duplicate other attributes + // XXXX : replace by this to duplicate other attributes /* ImageComponent3D img = new ImageComponent3D(rt.format, rt.width, diff --git a/src/classes/share/javax/media/j3d/IndexedGeometryArray.java b/src/classes/share/javax/media/j3d/IndexedGeometryArray.java index c1c4254..00a9aa8 100644 --- a/src/classes/share/javax/media/j3d/IndexedGeometryArray.java +++ b/src/classes/share/javax/media/j3d/IndexedGeometryArray.java @@ -17,7 +17,8 @@ import javax.vecmath.*; /** * The IndexedGeometryArray object contains separate integer arrays * that index into the arrays of positional coordinates, colors, - * normals, and texture coordinates. These index arrays specify how + * normals, texture coordinates, and vertex attributes. + * These index arrays specify how * vertices are connected to form geometry primitives. This class is * extended to create the various indexed primitive types (e.g., * lines, triangle strips, etc.). @@ -26,7 +27,10 @@ import javax.vecmath.*; public abstract class IndexedGeometryArray extends GeometryArray { // non-public, no parameter constructor - IndexedGeometryArray() {} + IndexedGeometryArray() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } /** * Specifies that this IndexedGeometryArray allows reading the array of @@ -85,6 +89,33 @@ public abstract class IndexedGeometryArray extends GeometryArray { ALLOW_TEXCOORD_INDEX_WRITE = CapabilityBits.INDEXED_GEOMETRY_ARRAY_ALLOW_TEXCOORD_INDEX_WRITE; /** + * Specifies that this IndexedGeometryArray allows reading the array of + * vertex attribute indices. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_VERTEX_ATTR_INDEX_READ = CapabilityBits.INDEXED_GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_INDEX_READ; + + /** + * Specifies that this IndexedGeometryArray allows writing the array of + * vertex attribute indices. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_VERTEX_ATTR_INDEX_WRITE = CapabilityBits.INDEXED_GEOMETRY_ARRAY_ALLOW_VERTEX_ATTR_INDEX_WRITE; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_COLOR_INDEX_READ, + ALLOW_COORDINATE_INDEX_READ, + ALLOW_NORMAL_INDEX_READ, + ALLOW_TEXCOORD_INDEX_READ, + ALLOW_VERTEX_ATTR_INDEX_READ + }; + + /** * Constructs an empty IndexedGeometryArray object with the specified * number of vertices, vertex format, and number of indices. * Defaults are used for all other parameters. The default values @@ -96,28 +127,31 @@ public abstract class IndexedGeometryArray extends GeometryArray { * all index array values : 0<br> * </ul> * - * @param vertexCount the number of vertex elements in this - * IndexedGeometryArray - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or - * TEXTURE_COORDINATE_4, to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * * @param indexCount the number of indices in this object. This * count is the maximum number of vertices that will be rendered. + * + * @exception IllegalArgumentException if <code>indexCount < 0</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public IndexedGeometryArray(int vertexCount, int vertexFormat, int indexCount) { super(vertexCount, vertexFormat); - ((IndexedGeometryArrayRetained)this.retained).createIndexedGeometryArrayData(indexCount); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((IndexedGeometryArrayRetained)this.retained).createIndexedGeometryArrayData(indexCount); } /** @@ -126,58 +160,30 @@ public abstract class IndexedGeometryArray extends GeometryArray { * sets, texture coordinate mapping array, and number of indices. * Defaults are used for all other parameters. * - * @param vertexCount the number of vertex elements in this - * IndexedGeometryArray<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D , 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. * * @param indexCount the number of indices in this object. This * count is the maximum number of vertices that will be rendered. * + * @exception IllegalArgumentException if <code>indexCount < 0</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown + * * @since Java 3D 1.2 */ public IndexedGeometryArray(int vertexCount, @@ -185,7 +191,61 @@ public abstract class IndexedGeometryArray extends GeometryArray { int texCoordSetCount, int[] texCoordSetMap, int indexCount) { - super(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap); + this(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap, 0, null, indexCount); + } + + /** + * Constructs an empty IndexedGeometryArray object with the + * specified number of vertices, vertex format, number of texture + * coordinate sets, texture coordinate mapping array, vertex + * attribute count, vertex attribute sizes array, and number of + * indices. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount the number of indices in this object. This + * count is the maximum number of vertices that will be rendered. + * + * @exception IllegalArgumentException if <code>indexCount < 0</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedGeometryArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((IndexedGeometryArrayRetained)this.retained).createIndexedGeometryArrayData(indexCount); } @@ -384,6 +444,20 @@ public abstract class IndexedGeometryArray extends GeometryArray { * This method is not supported for indexed geometry arrays. * Indexed primitives use an array of indices to determine how * to access the vertex array. + * + * @exception UnsupportedOperationException this method is not supported + * + * @since Java 3D 1.4 + */ + public void setInitialVertexAttrIndex(int vertexAttrNum, + int initialVertexAttrIndex) { + throw new UnsupportedOperationException(); + } + + /** + * This method is not supported for indexed geometry arrays. + * Indexed primitives use an array of indices to determine how + * to access the vertex array. * The validIndexCount attribute can be used to set the number of * valid indexed vertices rendered. * @@ -468,6 +542,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * colorIndex is out of range if it is less than 0 or is * greater than or equal to the number of vertices actually * defined for the color array. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public void setColorIndex(int index, int colorIndex) { if (isLiveOrCompiled()) @@ -495,6 +572,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * is out of range. An element is out of range if it is less than 0 * or is greater than or equal to the number of vertices actually * defined for the color array. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public void setColorIndices(int index, int colorIndices[]) { if (isLiveOrCompiled()) @@ -522,6 +602,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * normalIndex is out of range if it is less than 0 or is * greater than or equal to the number of vertices actually * defined for the normal array. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public void setNormalIndex(int index, int normalIndex) { if (isLiveOrCompiled()) @@ -549,6 +632,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * is out of range. An element is out of range if it is less than 0 * or is greater than or equal to the number of vertices actually * defined for the normal array. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public void setNormalIndices(int index, int normalIndices[]) { if (isLiveOrCompiled()) @@ -590,13 +676,16 @@ public abstract class IndexedGeometryArray extends GeometryArray { * greater than or equal to the number of vertices actually * defined for the texture coordinate array. * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * * @since Java 3D 1.2 */ public void setTextureCoordinateIndex(int texCoordSet, int index, int texCoordIndex) { if (isLiveOrCompiled()) - if(!this.getCapability(ALLOW_COORDINATE_INDEX_WRITE)) + if(!this.getCapability(ALLOW_TEXCOORD_INDEX_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray7")); ((IndexedGeometryArrayRetained)this.retained).setTextureCoordinateIndex(texCoordSet, index, texCoordIndex); @@ -634,18 +723,99 @@ public abstract class IndexedGeometryArray extends GeometryArray { * or is greater than or equal to the number of vertices actually * defined for the texture coordinate array. * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * * @since Java 3D 1.2 */ public void setTextureCoordinateIndices(int texCoordSet, int index, int texCoordIndices[]) { if (isLiveOrCompiled()) - if(!this.getCapability(ALLOW_COORDINATE_INDEX_WRITE)) + if(!this.getCapability(ALLOW_TEXCOORD_INDEX_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray7")); ((IndexedGeometryArrayRetained)this.retained).setTextureCoordinateIndices(texCoordSet, index, texCoordIndices); } + /** + * Sets the vertex attribute index associated with the vertex at + * the specified index for the specified vertex attribute number + * for this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index the vertex index + * @param vertexAttrIndex the new vertex attribute index + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception ArrayIndexOutOfBoundsException if index is in the range + * <code>[initialIndexIndex, initialIndexIndex+validIndexCount-1]</code> + * and the specified vertexAttrIndex is out of range. The + * vertexAttrIndex is out of range if it is less than 0 or is + * greater than or equal to the number of vertices actually + * defined for the vertex attribute array. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrIndex(int vertexAttrNum, + int index, + int vertexAttrIndex) { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_VERTEX_ATTR_INDEX_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray28")); + } + } + + ((IndexedGeometryArrayRetained)this.retained).setVertexAttrIndex(vertexAttrNum, index, vertexAttrIndex); + } + + /** + * Sets the vertex attribute indices associated with the vertices + * starting at the specified index for the specified vertex attribute number + * for this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index the vertex index + * @param vertexAttrIndices an array of vertex attribute indices + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception ArrayIndexOutOfBoundsException if any element of the + * vertexAttrIndices array whose destination position is in the range + * <code>[initialIndexIndex, initialIndexIndex+validIndexCount-1]</code> + * is out of range. An element is out of range if it is less than 0 + * or is greater than or equal to the number of vertices actually + * defined for the vertex attribute array. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * + * @since Java 3D 1.4 + */ + public void setVertexAttrIndices(int vertexAttrNum, + int index, + int[] vertexAttrIndices) { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_VERTEX_ATTR_INDEX_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray28")); + } + } + + ((IndexedGeometryArrayRetained)this.retained).setVertexAttrIndices(vertexAttrNum, index, vertexAttrIndices); + } + /** * Retrieves the coordinate index associated with the vertex at * the specified index for this object. @@ -685,6 +855,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * @return the color index * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public int getColorIndex(int index) { if (isLiveOrCompiled()) @@ -703,6 +876,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * @param colorIndices array that will receive the color indices * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public void getColorIndices(int index, int colorIndices[]) { if (isLiveOrCompiled()) @@ -719,6 +895,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * @return the normal index * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public int getNormalIndex(int index) { if (isLiveOrCompiled()) @@ -738,6 +917,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * @param normalIndices array that will receive the normal indices * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. */ public void getNormalIndices(int index, int normalIndices[]) { if (isLiveOrCompiled()) @@ -773,6 +955,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * <code>vertexFormat</code> or if the index or * texCoordSet is out of range. * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * * @since Java 3D 1.2 */ public int getTextureCoordinateIndex(int texCoordSet, int index) { @@ -812,6 +997,9 @@ public abstract class IndexedGeometryArray extends GeometryArray { * <code>vertexFormat</code> or if the index or * texCoordSet is out of range. * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * * @since Java 3D 1.2 */ public void getTextureCoordinateIndices(int texCoordSet, @@ -824,6 +1012,72 @@ public abstract class IndexedGeometryArray extends GeometryArray { ((IndexedGeometryArrayRetained)this.retained).getTextureCoordinateIndices(texCoordSet, index, texCoordIndices); } + /** + * Retrieves the vertex attribute index associated with the vertex at + * the specified index for the specified vertex attribute number + * for this object. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index the vertex index + * + * @return the vertex attribute index + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * + * @since Java 3D 1.4 + */ + public int getVertexAttrIndex(int vertexAttrNum, + int index) { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_VERTEX_ATTR_INDEX_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray29")); + } + } + + return ((IndexedGeometryArrayRetained)this.retained).getVertexAttrIndex(vertexAttrNum, index); + } + + /** + * Retrieves the vertex attribute indices associated with the vertices + * starting at the specified index for the specified vertex attribute number + * for this object. The vertex attribute indices + * are copied into the specified array. The array + * must be large enough to hold all of the indices. + * + * @param vertexAttrNum vertex attribute number in this geometry array + * @param index the vertex index + * @param vertexAttrIndices array that will receive the vertex attribute indices + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception ArrayIndexOutOfBoundsException if the index or + * vertexAttrNum is out of range. + * + * @exception NullPointerException if the <code>USE_COORD_INDEX_ONLY</code> + * bit is set in <code>vertexFormat</code>. + * + * @since Java 3D 1.4 + */ + public void getVertexAttrIndices(int vertexAttrNum, + int index, + int[] vertexAttrIndices) { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_VERTEX_ATTR_INDEX_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("IndexedGeometryArray29")); + } + } + + ((IndexedGeometryArrayRetained)this.retained).getVertexAttrIndices(vertexAttrNum, index, vertexAttrIndices); + } + /** * Copies all node information from <code>originalNodeComponent</code> into * the current node. This method is called from the @@ -854,30 +1108,39 @@ public abstract class IndexedGeometryArray extends GeometryArray { IndexedGeometryArrayRetained rt = (IndexedGeometryArrayRetained) retained; - int vformat = ga.getVertexFormat(); - int buffer[] = new int[ga.getIndexCount()]; - - if ((vformat & GeometryArray.COORDINATES) != 0) { - ga.getCoordinateIndices(0, buffer); - rt.setCoordinateIndices(0, buffer); - } - - if ((vformat & GeometryArray.NORMALS) != 0) { - ga.getNormalIndices(0, buffer); - rt.setNormalIndices(0, buffer); - } - - if ((vformat & GeometryArray.COLOR) != 0) { - ga.getColorIndices(0, buffer); - rt.setColorIndices(0, buffer); - } - - if ((vformat & GeometryArray.TEXTURE_COORDINATE) != 0) { - for (int i = 0; i < ga.texCoordSetCount; i++) { - ga.getTextureCoordinateIndices(i, 0, buffer); - rt.setTextureCoordinateIndices(i, 0, buffer); - } - } + int vformat = ga.getVertexFormat(); + int buffer[] = new int[ga.getIndexCount()]; + + if ((vformat & COORDINATES) != 0) { + ga.getCoordinateIndices(0, buffer); + rt.setCoordinateIndices(0, buffer); + } + + if ((vformat & USE_COORD_INDEX_ONLY) == 0) { + if ((vformat & NORMALS) != 0) { + ga.getNormalIndices(0, buffer); + rt.setNormalIndices(0, buffer); + } + + if ((vformat & COLOR) != 0) { + ga.getColorIndices(0, buffer); + rt.setColorIndices(0, buffer); + } + + if ((vformat & VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < ga.vertexAttrCount; i++) { + ga.getVertexAttrIndices(i, 0, buffer); + rt.setVertexAttrIndices(i, 0, buffer); + } + } + + if ((vformat & TEXTURE_COORDINATE) != 0) { + for (int i = 0; i < ga.texCoordSetCount; i++) { + ga.getTextureCoordinateIndices(i, 0, buffer); + rt.setTextureCoordinateIndices(i, 0, buffer); + } + } + } } } diff --git a/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java index 090de29..f6d443b 100644 --- a/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedGeometryArrayRetained.java @@ -30,11 +30,14 @@ import com.sun.j3d.internal.DoubleBufferWrapper; abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { - // arrays to save indices for coord, color, normal, texcoord - int indexCoord[], indexColor[], indexNormal[]; - Object indexTexCoord[]; + // arrays to save indices for coord, color, normal, texcoord, vertexAttr + int[] indexCoord; + int[] indexColor; + int[] indexNormal; + int[][] indexTexCoord; + int[][] indexVertexAttr; - int indexCount; + int indexCount = 0; int initialIndexIndex = 0; int validIndexCount = 0; @@ -47,65 +50,77 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { int maxColorIndex = 0; int maxNormalIndex = 0; int[] maxTexCoordIndices = null; - - void createIndexedGeometryArrayData(int indexCount) { - this.indexCount = indexCount; - this.validIndexCount = indexCount; + int[] maxVertexAttrIndices = null; + void createIndexedGeometryArrayData(int indexCount) { + this.indexCount = indexCount; + this.validIndexCount = indexCount; - boolean notUCIO = (this.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0; - - if((this.vertexFormat & GeometryArray.COORDINATES) != 0) - this.indexCoord = new int[indexCount]; - - if(((this.vertexFormat & GeometryArray.NORMALS) != 0) && notUCIO) - this.indexNormal = new int[indexCount]; - - if(((this.vertexFormat & GeometryArray.COLOR) != 0) && notUCIO) - this.indexColor = new int[indexCount]; - - if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { - this.indexTexCoord = new Object[this.texCoordSetCount]; - if(notUCIO) { - for (int i = 0; i < this.texCoordSetCount; i++) { - this.indexTexCoord[i] = new int[indexCount]; + // Only allocate color, normal, texCoord, and vertexAttr + // index arrays if USE_COORD_INDEX_ONLY is not set + boolean notUCIO = (this.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0; + + if((this.vertexFormat & GeometryArray.COORDINATES) != 0) + this.indexCoord = new int[indexCount]; + + if(((this.vertexFormat & GeometryArray.NORMALS) != 0) && notUCIO) + this.indexNormal = new int[indexCount]; + + if(((this.vertexFormat & GeometryArray.COLOR) != 0) && notUCIO) + this.indexColor = new int[indexCount]; + + if((this.vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { + this.indexTexCoord = new int[this.texCoordSetCount][]; + if(notUCIO) { + for (int i = 0; i < this.texCoordSetCount; i++) { + this.indexTexCoord[i] = new int[indexCount]; + } + } + maxTexCoordIndices = new int[texCoordSetCount]; + } + + if ((this.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + this.indexVertexAttr = new int[this.vertexAttrCount][]; + if (notUCIO) { + for (int i = 0; i < this.vertexAttrCount; i++) { + this.indexVertexAttr[i] = new int[indexCount]; + } } + this.maxVertexAttrIndices = new int[this.vertexAttrCount]; } - maxTexCoordIndices = new int[texCoordSetCount]; } - } - - Object cloneNonIndexedGeometry() { - GeometryArrayRetained obj = null; - int vOffset; - - switch (this.geoType) { - case GEO_TYPE_INDEXED_LINE_SET: - obj = new LineArrayRetained(); - break; - case GEO_TYPE_INDEXED_POINT_SET: - obj = new PointArrayRetained(); - break; - case GEO_TYPE_INDEXED_QUAD_SET: - obj = new QuadArrayRetained(); - break; - case GEO_TYPE_INDEXED_TRI_SET: - obj = new TriangleArrayRetained(); - break; - } - obj.createGeometryArrayData(validIndexCount, (vertexFormat & ~(GeometryArray.BY_REFERENCE|GeometryArray.INTERLEAVED|GeometryArray.USE_NIO_BUFFER)), - texCoordSetCount, texCoordSetMap); - obj.cloneSourceArray = this; - obj.unIndexify(this); - - return (Object)obj; - } - void execute(long ctx, RenderAtom ra, boolean isNonUniformScale, - boolean updateAlpha, float alpha) { - throw new RuntimeException(J3dI18N.getString("IndexedGeometryArrayRetained0")); - } + GeometryArrayRetained cloneNonIndexedGeometry() { + GeometryArrayRetained obj = null; + int vOffset; + + switch (this.geoType) { + case GEO_TYPE_INDEXED_LINE_SET: + obj = new LineArrayRetained(); + break; + case GEO_TYPE_INDEXED_POINT_SET: + obj = new PointArrayRetained(); + break; + case GEO_TYPE_INDEXED_QUAD_SET: + obj = new QuadArrayRetained(); + break; + case GEO_TYPE_INDEXED_TRI_SET: + obj = new TriangleArrayRetained(); + break; + default: + assert false; // Should never get here + } + + obj.createGeometryArrayData(validIndexCount, + (vertexFormat & ~(GeometryArray.BY_REFERENCE|GeometryArray.INTERLEAVED|GeometryArray.USE_NIO_BUFFER)), + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); + obj.cloneSourceArray = this; + obj.unIndexify(this); + + return obj; + } /** @@ -127,14 +142,19 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { doTexCoordCheck(newMax, i); } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + doVertexAttrCheck(newMax, i); + } + } if ((vertexFormat & GeometryArray.NORMALS) != 0) { doNormalCheck(newMax); - } - } + } + } } - + void doCoordCheck(int newMax) { - // Check to make sure that the array length defined by the user is ateast maxCoordIndex long + // Check to make sure that the array length defined by the user is ateast maxCoordIndex long if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { if (newMax >= vertexCount) { throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray23")); @@ -404,6 +424,43 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { } + void doVertexAttrCheck(int newMax, int vertexAttrNum) { + + // Check to make sure that the array length defined by the user is ateast maxVertexAttrIndex long + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) == 0) { + return; + } + + // Vertex attributes must not be interleaved + assert (vertexFormat & GeometryArray.INTERLEAVED) == 0; + + if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { + if (newMax >= vertexCount) { + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30")); + } + } else { + int multiplier = vertexAttrSizes[vertexAttrNum]; + + if(( vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { + switch (vertexType & VATTR_DEFINED) { + case AF: + if(multiplier * newMax >= floatBufferRefVertexAttrs[vertexAttrNum].limit()) { + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30")); + } + break; + } + } else { + switch (vertexType & VATTR_DEFINED) { + case AF: + if (multiplier * newMax >= floatRefVertexAttrs[vertexAttrNum].length) { + throw new ArrayIndexOutOfBoundsException(J3dI18N.getString("IndexedGeometryArray30")); + } + break; + } + } + } + } + /** * Sets the coordinate index associated with the vertex at @@ -426,6 +483,11 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { maxTexCoordIndices[i] = newMax; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = newMax; + } + } if ((vertexFormat & GeometryArray.NORMALS) != 0) { maxNormalIndex = newMax; } @@ -542,6 +604,11 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { maxTexCoordIndices[i] = newMax; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = newMax; + } + } if ((vertexFormat & GeometryArray.NORMALS) != 0) { maxNormalIndex = newMax; } @@ -568,33 +635,21 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { final void setColorIndex(int index, int colorIndex) { int newMax = maxColorIndex; - if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { - newMax = doIndexCheck(index, maxColorIndex, indexColor, colorIndex); - if (newMax > maxColorIndex) { - doColorCheck(newMax); - } - geomLock.getLock(); - // No need to set INDEX_CHANGED since IndexBuffer - // is used only when USE_COORD_INDEX_ONLY specified. - // In this case only coordinate index array is - // considered. - this.indexColor[index] = colorIndex; - maxColorIndex = newMax; - geomLock.unLock(); - if (!inUpdater && source != null && source.isLive()) { - sendDataChangedMessage(false); - } - } - else { - if ((vertexFormat & GeometryArray.COLOR) != 0) { - if (this.indexColor == null) { - this.indexColor = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained1")); - } - } - this.indexColor[index] = colorIndex; - } - + newMax = doIndexCheck(index, maxColorIndex, indexColor, colorIndex); + if (newMax > maxColorIndex) { + doColorCheck(newMax); + } + geomLock.getLock(); + // No need to set INDEX_CHANGED since IndexBuffer + // is used only when USE_COORD_INDEX_ONLY specified. + // In this case only coordinate index array is + // considered. + this.indexColor[index] = colorIndex; + maxColorIndex = newMax; + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } } /** @@ -606,34 +661,20 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { final void setColorIndices(int index, int colorIndices[]) { int i, j, num = colorIndices.length; int newMax; - - if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { - newMax = doIndicesCheck(index, maxColorIndex, indexColor, colorIndices); - if (newMax > maxColorIndex) { - doColorCheck(newMax); - } - geomLock.getLock(); - maxColorIndex = newMax; - for (i=0, j = index; i < num;i++, j++) { - this.indexColor[j] = colorIndices[i]; - } - geomLock.unLock(); - if (!inUpdater && source != null && source.isLive()) { - sendDataChangedMessage(false); - } - } - else { - if ((vertexFormat & GeometryArray.COLOR) != 0) { - if (this.indexColor == null) { - this.indexColor = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained1")); - } - } - for (i=0, j = index; i < num;i++, j++) { - this.indexColor[j] = colorIndices[i]; - } - } + newMax = doIndicesCheck(index, maxColorIndex, indexColor, colorIndices); + if (newMax > maxColorIndex) { + doColorCheck(newMax); + } + geomLock.getLock(); + maxColorIndex = newMax; + for (i=0, j = index; i < num;i++, j++) { + this.indexColor[j] = colorIndices[i]; + } + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } } /** @@ -644,30 +685,18 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { */ final void setNormalIndex(int index, int normalIndex) { int newMax; - - if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { - newMax = doIndexCheck(index, maxNormalIndex, indexNormal, normalIndex); - if (newMax > maxNormalIndex) { - doNormalCheck(newMax); - } - geomLock.getLock(); - maxNormalIndex = newMax; - this.indexNormal[index] = normalIndex; - geomLock.unLock(); - if (!inUpdater && source != null && source.isLive()) { - sendDataChangedMessage(false); - } - } - else { - if ((vertexFormat & GeometryArray.NORMALS) != 0) { - if (this.indexNormal == null) { - this.indexNormal = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained2")); - } - } - this.indexNormal[index] = normalIndex; - } + newMax = doIndexCheck(index, maxNormalIndex, indexNormal, normalIndex); + if (newMax > maxNormalIndex) { + doNormalCheck(newMax); + } + geomLock.getLock(); + maxNormalIndex = newMax; + this.indexNormal[index] = normalIndex; + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } } /** @@ -679,34 +708,20 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { final void setNormalIndices(int index, int normalIndices[]) { int i, j, num = normalIndices.length; int newMax; - - if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { - newMax = doIndicesCheck(index, maxNormalIndex, indexNormal, normalIndices); - if (newMax > maxNormalIndex) { - doNormalCheck(newMax); - } - geomLock.getLock(); - for (i=0, j = index; i < num;i++, j++) { - this.indexNormal[j] = normalIndices[i]; - } - maxNormalIndex = newMax; - geomLock.unLock(); - if (!inUpdater && source != null && source.isLive()) { - sendDataChangedMessage(false); - } - } - else { - if ((vertexFormat & GeometryArray.NORMALS) != 0) { - if (this.indexNormal == null) { - this.indexNormal = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained2")); - } - } - for (i=0, j = index; i < num;i++, j++) { - this.indexNormal[j] = normalIndices[i]; - } - } + newMax = doIndicesCheck(index, maxNormalIndex, indexNormal, normalIndices); + if (newMax > maxNormalIndex) { + doNormalCheck(newMax); + } + geomLock.getLock(); + for (i=0, j = index; i < num;i++, j++) { + this.indexNormal[j] = normalIndices[i]; + } + maxNormalIndex = newMax; + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } } /** @@ -718,33 +733,19 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { */ final void setTextureCoordinateIndex(int texCoordSet, int index, int texCoordIndex) { int newMax; - int [] indices = (int[])this.indexTexCoord[texCoordSet]; - - if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { - newMax = doIndexCheck(index, maxTexCoordIndices[texCoordSet],indices, texCoordIndex); - if (newMax > maxTexCoordIndices[texCoordSet]) { - doTexCoordCheck(newMax, texCoordSet); - } - geomLock.getLock(); - maxTexCoordIndices[texCoordSet] = newMax; - indices[index] = texCoordIndex; - geomLock.unLock(); - if (!inUpdater && source != null && source.isLive()) { - sendDataChangedMessage(false); - } - } - else { - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { - if (indices == null) { - indices = new int[indexCount]; - this.indexTexCoord[texCoordSet] = indices; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained3")); - } - } - indices[index] = texCoordIndex; - } - + int [] indices = this.indexTexCoord[texCoordSet]; + newMax = doIndexCheck(index, maxTexCoordIndices[texCoordSet],indices, texCoordIndex); + if (newMax > maxTexCoordIndices[texCoordSet]) { + doTexCoordCheck(newMax, texCoordSet); + } + geomLock.getLock(); + maxTexCoordIndices[texCoordSet] = newMax; + indices[index] = texCoordIndex; + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } } /** @@ -754,42 +755,80 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @param index the vertex index * @param texCoordIndices an array of texture coordinate indices */ - final void setTextureCoordinateIndices(int texCoordSet, int index, int texCoordIndices[]) { - int i, j, num = texCoordIndices.length; - int [] indices = (int[])this.indexTexCoord[texCoordSet]; + final void setTextureCoordinateIndices(int texCoordSet, int index, int texCoordIndices[]) { + int i, j, num = texCoordIndices.length; + int [] indices = this.indexTexCoord[texCoordSet]; - int newMax; - - if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { - newMax = doIndicesCheck(index, maxTexCoordIndices[texCoordSet], indices, texCoordIndices); - if (newMax > maxTexCoordIndices[texCoordSet]) { - doTexCoordCheck(newMax, texCoordSet); - } - geomLock.getLock(); - maxTexCoordIndices[texCoordSet] = newMax; - for (i=0, j = index; i < num;i++, j++) { - indices[j] = texCoordIndices[i]; - } - geomLock.unLock(); - if (!inUpdater && source != null && source.isLive()) { - sendDataChangedMessage(false); - } - - } - else { - if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { - if (indices == null) { - indices = new int[indexCount]; - this.indexTexCoord[texCoordSet] = indices; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained3")); - } - } - for (i=0, j = index; i < num;i++, j++) { - indices[j] = texCoordIndices[i]; - } - } + int newMax; - } + newMax = doIndicesCheck(index, maxTexCoordIndices[texCoordSet], indices, texCoordIndices); + if (newMax > maxTexCoordIndices[texCoordSet]) { + doTexCoordCheck(newMax, texCoordSet); + } + geomLock.getLock(); + maxTexCoordIndices[texCoordSet] = newMax; + for (i=0, j = index; i < num;i++, j++) { + indices[j] = texCoordIndices[i]; + } + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } + } + + /** + * Sets the vertex attribute index associated with the vertex at + * the specified index for the specified vertex attribute number + * for this object. + */ + public void setVertexAttrIndex(int vertexAttrNum, + int index, + int vertexAttrIndex) { + + int newMax; + int [] indices = this.indexVertexAttr[vertexAttrNum]; + + newMax = doIndexCheck(index, maxVertexAttrIndices[vertexAttrNum],indices, vertexAttrIndex); + if (newMax > maxVertexAttrIndices[vertexAttrNum]) { + doVertexAttrCheck(newMax, vertexAttrNum); + } + geomLock.getLock(); + maxVertexAttrIndices[vertexAttrNum] = newMax; + indices[index] = vertexAttrIndex; + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } + } + + /** + * Sets the vertex attribute indices associated with the vertices + * starting at the specified index for the specified vertex attribute number + * for this object. + */ + public void setVertexAttrIndices(int vertexAttrNum, + int index, + int[] vertexAttrIndices) { + + int i, j, num = vertexAttrIndices.length; + int [] indices = this.indexVertexAttr[vertexAttrNum]; + + int newMax; + + newMax = doIndicesCheck(index, maxVertexAttrIndices[vertexAttrNum], indices, vertexAttrIndices); + if (newMax > maxVertexAttrIndices[vertexAttrNum]) { + doVertexAttrCheck(newMax, vertexAttrNum); + } + geomLock.getLock(); + maxVertexAttrIndices[vertexAttrNum] = newMax; + for (i=0, j = index; i < num;i++, j++) { + indices[j] = vertexAttrIndices[i]; + } + geomLock.unLock(); + if (!inUpdater && source != null && source.isLive()) { + sendDataChangedMessage(false); + } + } /** * Retrieves the coordinate index associated with the vertex at @@ -807,14 +846,13 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @param index the vertex index * @param coordinateIndices array that will receive the coordinate indices */ - final void getCoordinateIndices(int index, int coordinateIndices[]) { - int i, j, num = coordinateIndices.length; + final void getCoordinateIndices(int index, int coordinateIndices[]) { + int i, j, num = coordinateIndices.length; - for (i=0, j = index;i < num;i++, j++) - { - coordinateIndices[i] = this.indexCoord[j]; - } - } + for (i=0, j = index;i < num;i++, j++) { + coordinateIndices[i] = this.indexCoord[j]; + } + } /** * Retrieves the color index associated with the vertex at @@ -823,13 +861,6 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @return the color index */ final int getColorIndex(int index) { - if (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) && - ((vertexFormat & GeometryArray.COLOR) != 0)) { - if (this.indexColor == null) { - this.indexColor = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained1")); - } - } return this.indexColor[index]; } @@ -839,22 +870,14 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @param index the vertex index * @param colorIndices array that will receive the color indices */ - final void getColorIndices(int index, int colorIndices[]) { - int i, j, num = colorIndices.length; - if (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) && - ((vertexFormat & GeometryArray.COLOR) != 0)) { - if (this.indexColor == null) { - this.indexColor = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained1")); + final void getColorIndices(int index, int colorIndices[]) { + int i, j, num = colorIndices.length; + + for (i=0, j = index;i < num;i++, j++) { + colorIndices[i] = this.indexColor[j]; } } - for (i=0, j = index;i < num;i++, j++) - { - colorIndices[i] = this.indexColor[j]; - } - } - /** * Retrieves the normal index associated with the vertex at * the specified index for this object. @@ -862,13 +885,6 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @return the normal index */ final int getNormalIndex(int index) { - if (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) && - ((vertexFormat & GeometryArray.NORMALS) != 0)) { - if (this.indexNormal == null) { - this.indexNormal = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained2")); - } - } return this.indexNormal[index]; } @@ -878,22 +894,14 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @param index the vertex index * @param normalIndices array that will receive the normal indices */ - final void getNormalIndices(int index, int normalIndices[]) { - int i, j, num = normalIndices.length; - if (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) && - ((vertexFormat & GeometryArray.NORMALS) != 0)) { - if (this.indexNormal == null) { - this.indexNormal = new int[indexCount]; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained2")); + final void getNormalIndices(int index, int normalIndices[]) { + int i, j, num = normalIndices.length; + + for (i=0, j = index;i < num;i++, j++) { + normalIndices[i] = this.indexNormal[j]; } } - for (i=0, j = index;i < num;i++, j++) - { - normalIndices[i] = this.indexNormal[j]; - } - } - /** * Retrieves the texture coordinate index associated with the vertex at * the specified index for this object. @@ -902,16 +910,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @return the texture coordinate index */ final int getTextureCoordinateIndex(int texCoordSet, int index) { - int [] indices = (int[])this.indexTexCoord[texCoordSet]; - if (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) && - ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0)) { - if (indices == null) { - indices = new int[indexCount]; - this.indexTexCoord[texCoordSet] = indices; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained3")); - } - } - return indices[index]; + int [] indices = this.indexTexCoord[texCoordSet]; + + return indices[index]; } /** @@ -921,120 +922,147 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { * @param index the vertex index * @param texCoordIndices array that will receive the texture coordinate indices */ - final void getTextureCoordinateIndices(int texCoordSet, int index, int texCoordIndices[]) { - int i, j, num = texCoordIndices.length; - int [] indices = (int[])this.indexTexCoord[texCoordSet]; - if (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) && - ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0)) { - if (indices == null) { - indices = new int[indexCount]; - this.indexTexCoord[texCoordSet] = indices; - System.err.println(J3dI18N.getString("IndexedGeometryArrayRetained3")); + final void getTextureCoordinateIndices(int texCoordSet, int index, int texCoordIndices[]) { + int i, j, num = texCoordIndices.length; + int [] indices = this.indexTexCoord[texCoordSet]; + + for (i=0, j = index;i < num;i++, j++) { + texCoordIndices[i] = indices[j]; } } - for (i=0, j = index;i < num;i++, j++) - { - texCoordIndices[i] = indices[j]; - } - } + /** + * Retrieves the vertex attribute index associated with the vertex at + * the specified index for the specified vertex attribute number + * for this object. + */ + public int getVertexAttrIndex(int vertexAttrNum, + int index) { + + int [] indices = this.indexVertexAttr[vertexAttrNum]; - // used for GeometryArrays - native void executeIndexedGeometry(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int indexCount, - int vertexCount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - float[] varray, float[] cdata, - int texUnitIndex, int cdirty, - int[] indexCoord); - - // used for interleaved, by reference, nio buffer - native void executeIndexedGeometryBuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean useAlpha, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int indexCount, - int vertexCount, int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetOffset, - int numActiveTexUnitState, - int[] texUnitStateMap, - Object varray, float[] cdata, - int texUnitIndex, int cdirty, - int[] indexCoord); + return indices[index]; + } + /** + * Retrieves the vertex attribute indices associated with the vertices + * starting at the specified index for the specified vertex attribute number + * for this object. + */ + public void getVertexAttrIndices(int vertexAttrNum, + int index, + int[] vertexAttrIndices) { - - native void executeIndexedGeometryVA(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int validIndexCount, - int vertexCount, - int vformat, - int vdefined, - float[] vfcoords, double[] vdcoords, - float[] cfdata, byte[] cbdata, - float[] ndata, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int texstride, Object[] texCoords, - int cdirty, - int[] indexCoord); + int i, j, num = vertexAttrIndices.length; + int [] indices = this.indexVertexAttr[vertexAttrNum]; + + for (i=0, j = index;i < num;i++, j++) { + vertexAttrIndices[i] = indices[j]; + } + } + + // by-copy or interleaved, by reference, Java arrays + private native void executeIndexedGeometry(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean multiScreen, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int texCoordSetMap[], + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int[] texUnitStateMap, + float[] varray, float[] cdata, + int texUnitIndex, int cdirty, + int[] indexCoord); + + // interleaved, by reference, nio buffer + private native void executeIndexedGeometryBuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean useAlpha, + boolean multiScreen, + boolean ignoreVertexColors, + int initialIndexIndex, + int indexCount, + int vertexCount, int vformat, + int texCoordSetCount, int texCoordSetMap[], + int texCoordSetMapLen, + int[] texCoordSetOffset, + int numActiveTexUnitState, + int[] texUnitStateMap, + Object varray, float[] cdata, + int texUnitIndex, int cdirty, + int[] indexCoord); + + // non interleaved, by reference, Java arrays + private native void executeIndexedGeometryVA(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean multiScreen, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + float[] vfcoords, double[] vdcoords, + float[] cfdata, byte[] cbdata, + float[] ndata, + int vertexAttrCount, int[] vertexAttrSizes, + float[][] vertexAttrData, + int pass, int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, int[] texunitstatemap, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord); // non interleaved, by reference, nio buffer - native void executeIndexedGeometryVABuffer(long ctx, - GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, - boolean multiScreen, - boolean ignoreVertexColors, - int initialIndexIndex, - int validIndexCount, - int vertexCount, - int vformat, - int vdefined, - Object vcoords, - Object cdataBuffer, - float[] cfdata, byte[] cbdata, - Object normal, - int pass, int texcoordmaplength, - int[] texcoordoffset, - int numActiveTexUnitState, int[] texunitstatemap, - int texstride, Object[] texCoords, - int cdirty, - int[] indexCoord); - - // used for IndexedGeometry - native void buildIndexedGeometry(long ctx, GeometryArrayRetained geo, int geo_type, - boolean isNonUniformScale, boolean updateAlpha, - float alpha, - boolean ignoreVertexColors, - int initialIndexIndex, - int validIndexCount, - int vertexCount, - int vformat, - int texCoordSetCount, int texCoordSetMap[], - int texCoordSetMapLen, - int[] texCoordSetMapOffset, - double[] xform, double[] nxform, - float[] varray, int[] indexCoord); + private native void executeIndexedGeometryVABuffer(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, + boolean multiScreen, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vdefined, + Object vcoords, + Object cdataBuffer, + float[] cfdata, byte[] cbdata, + Object normal, + int vertexAttrCount, int[] vertexAttrSizes, + Object[] vertexAttrData, + int pass, int texcoordmaplength, + int[] texcoordoffset, + int numActiveTexUnitState, int[] texunitstatemap, + int texstride, Object[] texCoords, + int cdirty, + int[] indexCoord); + + // by-copy geometry + private native void buildIndexedGeometry(long ctx, + GeometryArrayRetained geo, int geo_type, + boolean isNonUniformScale, boolean updateAlpha, + float alpha, + boolean ignoreVertexColors, + int initialIndexIndex, + int validIndexCount, + int vertexCount, + int vformat, + int vertexAttrCount, int[] vertexAttrSizes, + int texCoordSetCount, int texCoordSetMap[], + int texCoordSetMapLen, + int[] texCoordSetMapOffset, + double[] xform, double[] nxform, + float[] varray, int[] indexCoord); void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, @@ -1081,23 +1109,24 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { // RenderBin render the geometry. So it is safe // just to set the dirty flag here dirtyFlag = 0; - } - - executeIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, - useAlpha, - multiScreen, - ignoreVertexColors, - initialIndexIndex, - validIndexCount, - // Vertex Count is maxCoordIndex + 1 - maxCoordIndex + 1, - ((vertexFormat & GeometryArray.COLOR) != 0)?(vertexFormat|GeometryArray.COLOR_4):vertexFormat, - texCoordSetCount, texCoordSetMap, - (texCoordSetMap == null) ? 0 : texCoordSetMap.length, - texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, - vdata, null, - pass, cdirty, indexCoord); + } + + executeIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, + useAlpha, + multiScreen, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + // Vertex Count is maxCoordIndex + 1 + maxCoordIndex + 1, + ((vertexFormat & GeometryArray.COLOR) != 0)?(vertexFormat|GeometryArray.COLOR_4):vertexFormat, + vertexAttrCount, vertexAttrSizes, + texCoordSetCount, texCoordSetMap, + (texCoordSetMap == null) ? 0 : texCoordSetMap.length, + texCoordSetMapOffset, + cv.numActiveTexUnit, cv.texUnitStateMap, + vdata, null, + pass, cdirty, indexCoord); } // end of non by reference @@ -1127,31 +1156,34 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { } dirtyFlag = 0; } - - executeIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, - useAlpha, - multiScreen, - ignoreVertexColors, - initialIndexIndex, - validIndexCount, - maxCoordIndex + 1, - vertexFormat, - texCoordSetCount, texCoordSetMap, - (texCoordSetMap == null) ? 0 : texCoordSetMap.length, - texCoordSetMapOffset, - cv.numActiveTexUnit, cv.texUnitStateMap, - interLeavedVertexData, cdata, - pass, cdirty, indexCoord); + + executeIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, + useAlpha, + multiScreen, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + maxCoordIndex + 1, + vertexFormat, + vertexAttrCount, vertexAttrSizes, + texCoordSetCount, texCoordSetMap, + (texCoordSetMap == null) ? 0 : texCoordSetMap.length, + texCoordSetMapOffset, + cv.numActiveTexUnit, cv.texUnitStateMap, + interLeavedVertexData, cdata, + pass, cdirty, indexCoord); } //end of interleaved - else { - // Check if a vertexformat is set, but the array is null + else { + // Check if a vertexformat is set, but the array is null // if yes, don't draw anything if ((vertexType == 0) || ((vertexType & VERTEX_DEFINED) == 0) || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0) || (((vertexFormat & GeometryArray.NORMALS) != 0) && - (vertexType & NORMAL_DEFINED) == 0) || + (vertexType & NORMAL_DEFINED) == 0) || + (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && + (vertexType & VATTR_DEFINED) == 0) || (((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) { return; @@ -1215,29 +1247,32 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { vdefined |= COLOR_BYTE; if((vertexType & NORMAL_DEFINED) != 0) vdefined |= NORMAL_FLOAT; - if((vertexType & TEXCOORD_DEFINED) != 0) - vdefined |= TEXCOORD_FLOAT; - - executeIndexedGeometryVA(cv.ctx, this, geoType, isNonUniformScale, - multiScreen, - ignoreVertexColors, - initialIndexIndex, - validIndexCount, - maxCoordIndex + 1, - (vertexFormat | c4fAllocated), - vdefined, - mirrorFloatRefCoords, mirrorDoubleRefCoords, - cfdata, cbdata, - mirrorFloatRefNormals, - pass, - ((texCoordSetMap == null) ? 0:texCoordSetMap.length), - texCoordSetMap, - cv.numActiveTexUnit, - cv.texUnitStateMap, - texCoordStride, - mirrorRefTexCoords, cdirty, indexCoord); - - } + if((vertexType & VATTR_DEFINED) != 0) + vdefined |= VATTR_FLOAT; + if((vertexType & TEXCOORD_DEFINED) != 0) + vdefined |= TEXCOORD_FLOAT; + + executeIndexedGeometryVA(cv.ctx, this, geoType, isNonUniformScale, + multiScreen, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + maxCoordIndex + 1, + (vertexFormat | c4fAllocated), + vdefined, + mirrorFloatRefCoords, mirrorDoubleRefCoords, + cfdata, cbdata, + mirrorFloatRefNormals, + vertexAttrCount, vertexAttrSizes, + mirrorFloatRefVertexAttrs, + pass, + ((texCoordSetMap == null) ? 0:texCoordSetMap.length), + texCoordSetMap, + cv.numActiveTexUnit, + cv.texUnitStateMap, + texCoordStride, + mirrorRefTexCoords, cdirty, indexCoord); + } } // end of non interleaved and by reference }//end of non io buffer @@ -1284,15 +1319,17 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { interleavedFloatBufferImpl.getBufferAsObject(), cdata, pass, cdirty, indexCoord); } //end of interleaved - else { - // Check if a vertexformat is set, but the array is null + else { + // Check if a vertexformat is set, but the array is null // if yes, don't draw anything if ((vertexType == 0) || ((vertexType & VERTEX_DEFINED) == 0) || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0) || (((vertexFormat & GeometryArray.NORMALS) != 0) && - (vertexType & NORMAL_DEFINED) == 0) || + (vertexType & NORMAL_DEFINED) == 0) || + (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && + (vertexType & VATTR_DEFINED) == 0) || (((vertexFormat& GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) { return; @@ -1311,7 +1348,7 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { cdirty |= COLOR_CHANGED; } } else { - // TODO: handle transparency case + // XXXX: handle transparency case //cfdata = null; cfdata = mirrorFloatRefColors[0]; // if transparency switch between on/off @@ -1334,7 +1371,7 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { cdirty |= COLOR_CHANGED; } } else { - // TODO: handle transparency case + // XXXX: handle transparency case // cbdata = null; cbdata = mirrorUnsignedByteRefColors[0]; // if transparency switch between on/off @@ -1371,29 +1408,37 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { vdefined |= NORMAL_FLOAT; normal = floatBufferRefNormals.getBufferAsObject(); } - - if((vertexType & TEXCOORD_DEFINED) != 0) - vdefined |= TEXCOORD_FLOAT; - - executeIndexedGeometryVABuffer(cv.ctx, this, geoType, isNonUniformScale, - multiScreen, - ignoreVertexColors, - initialIndexIndex, - validIndexCount, - maxCoordIndex + 1, - (vertexFormat | c4fAllocated), - vdefined, - vcoord, - cdataBuffer, - cfdata, cbdata, - normal, - pass, - ((texCoordSetMap == null) ? 0:texCoordSetMap.length), - texCoordSetMap, - cv.numActiveTexUnit, - cv.texUnitStateMap, - texCoordStride, - refTexCoords, cdirty, indexCoord); + + if ((vertexType & VATTR_DEFINED) != 0) { + vdefined |= VATTR_FLOAT; + } + + if ((vertexType & TEXCOORD_DEFINED) != 0) { + vdefined |= TEXCOORD_FLOAT; + } + + executeIndexedGeometryVABuffer(cv.ctx, + this, geoType, isNonUniformScale, + multiScreen, + ignoreVertexColors, + initialIndexIndex, + validIndexCount, + maxCoordIndex + 1, + (vertexFormat | c4fAllocated), + vdefined, + vcoord, + cdataBuffer, + cfdata, cbdata, + normal, + vertexAttrCount, vertexAttrSizes, + nioFloatBufferRefVertexAttrs, + pass, + ((texCoordSetMap == null) ? 0:texCoordSetMap.length), + texCoordSetMap, + cv.numActiveTexUnit, + cv.texUnitStateMap, + texCoordStride, + refTexCoords, cdirty, indexCoord); } } // end of non interleaved and by reference @@ -1413,7 +1458,7 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { else { if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) { - float[] vdata; + float[] vdata; // System.out.println("by-copy"); synchronized (this) { cdirty = dirtyFlag; @@ -1443,19 +1488,26 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { dirtyFlag = 0; } - buildIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, - updateAlpha, alpha, ignoreVertexColors, - initialIndexIndex, - validIndexCount, - maxCoordIndex + 1, - vertexFormat, - texCoordSetCount, texCoordSetMap, - (texCoordSetMap == null) ? 0 : texCoordSetMap.length, - texCoordSetMapOffset, - (xform == null) ? null : xform.mat, - (nxform == null) ? null : nxform.mat, - vdata, indexCoord); + buildIndexedGeometry(cv.ctx, this, geoType, isNonUniformScale, + updateAlpha, alpha, ignoreVertexColors, + initialIndexIndex, + validIndexCount, + maxCoordIndex + 1, + vertexFormat, + vertexAttrCount, vertexAttrSizes, + texCoordSetCount, texCoordSetMap, + (texCoordSetMap == null) ? 0 : texCoordSetMap.length, + texCoordSetMapOffset, + (xform == null) ? null : xform.mat, + (nxform == null) ? null : nxform.mat, + vdata, indexCoord); } + // XXXX: Note that there is no "else" clause here, and no + // buildIndexedGeometryForByRef() method. + // We would need to create one if we ever wanted to support by-ref + // indexed geometry in display lists. Better yet, we could fix + // canBeInDisplayList so that unindexified by-ref geometry could + // go into a display list. } } @@ -1478,11 +1530,12 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { indexColor = new int[indexCount]; if ((vertexFormat & GeometryArray.NORMALS) != 0) indexNormal = new int[indexCount]; - // We only merge if texCoordSetCount = 1 + // We only merge if the texCoordSetCount is 1 and there are no + // vertex attrs if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { - indexTexCoord = new Object[1]; + indexTexCoord = new int[1][]; indexTexCoord[0] = new int[indexCount]; - texCoord = (int[])indexTexCoord[0]; + texCoord = indexTexCoord[0]; } } int curDataOffset = 0; @@ -1500,7 +1553,7 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { if ((vertexFormat & GeometryArray.NORMALS) != 0) indexNormal[j+curIndexOffset] = geo.indexNormal[j+geo.initialIndexIndex]+curDataOffset; if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) - texCoord[j+curIndexOffset] = ((int[])geo.indexTexCoord[0])[j+geo.initialIndexIndex]+curDataOffset; + texCoord[j+curIndexOffset] = geo.indexTexCoord[0][j+geo.initialIndexIndex]+curDataOffset; } } maxCoordIndex = geo.maxCoordIndex +curDataOffset; @@ -1517,12 +1570,14 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { boolean isWriteStatic() { - if (!super.isWriteStatic() || - source.getCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_WRITE ) || - source.getCapability(IndexedGeometryArray.ALLOW_COLOR_INDEX_WRITE) || - source.getCapability(IndexedGeometryArray.ALLOW_NORMAL_INDEX_WRITE) || - source.getCapability(IndexedGeometryArray.ALLOW_TEXCOORD_INDEX_WRITE)) - return false; + if (!super.isWriteStatic() || + source.getCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_WRITE ) || + source.getCapability(IndexedGeometryArray.ALLOW_COLOR_INDEX_WRITE) || + source.getCapability(IndexedGeometryArray.ALLOW_NORMAL_INDEX_WRITE) || + source.getCapability(IndexedGeometryArray.ALLOW_VERTEX_ATTR_INDEX_WRITE) || + source.getCapability(IndexedGeometryArray.ALLOW_TEXCOORD_INDEX_WRITE)) { + return false; + } return true; } @@ -1556,8 +1611,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { int newCoordMax =0; int newColorIndex=0; int newNormalIndex=0; - int newTexCoordIndex[]=null; - + int[] newTexCoordIndex = null; + int[] newVertexAttrIndex = null; + newCoordMax = computeMaxIndex(initialIndexIndex, validIndexCount,indexCoord ); doErrorCheck(newCoordMax); if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { @@ -1569,10 +1625,19 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { newTexCoordIndex = new int[texCoordSetCount]; for (int i = 0; i < texCoordSetCount; i++) { newTexCoordIndex[i] = computeMaxIndex(initialIndexIndex,validIndexCount, - (int[])indexTexCoord[i]); + indexTexCoord[i]); doTexCoordCheck(newTexCoordIndex[i], i); } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + newVertexAttrIndex = new int[vertexAttrCount]; + for (int i = 0; i < vertexAttrCount; i++) { + newVertexAttrIndex[i] = computeMaxIndex(initialIndexIndex, + validIndexCount, + indexVertexAttr[i]); + doVertexAttrCheck(newVertexAttrIndex[i], i); + } + } if ((vertexFormat & GeometryArray.NORMALS) != 0) { newNormalIndex = computeMaxIndex(initialIndexIndex, validIndexCount, indexNormal); doNormalCheck(newNormalIndex); @@ -1589,6 +1654,11 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { maxTexCoordIndices[i] = newTexCoordIndex[i]; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = newVertexAttrIndex[i]; + } + } maxNormalIndex = newNormalIndex; } else { @@ -1599,6 +1669,11 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { maxTexCoordIndices[i] = maxCoordIndex; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = maxCoordIndex; + } + } } geomLock.unLock(); // bbox is computed for the entries list. @@ -1616,8 +1691,9 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { int newCoordMax =0; int newColorIndex=0; int newNormalIndex=0; - int newTexCoordIndex[]=null; - + int[] newTexCoordIndex = null; + int[] newVertexAttrIndex = null; + newCoordMax = computeMaxIndex(initialIndexIndex, validIndexCount, indexCoord); doErrorCheck(newCoordMax); if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) { @@ -1629,10 +1705,19 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { newTexCoordIndex = new int[texCoordSetCount]; for (int i = 0; i < texCoordSetCount; i++) { newTexCoordIndex[i] = computeMaxIndex(initialIndexIndex,validIndexCount, - (int[])indexTexCoord[i]); + indexTexCoord[i]); doTexCoordCheck(newTexCoordIndex[i], i); } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + newVertexAttrIndex = new int[vertexAttrCount]; + for (int i = 0; i < vertexAttrCount; i++) { + newVertexAttrIndex[i] = computeMaxIndex(initialIndexIndex, + validIndexCount, + indexVertexAttr[i]); + doVertexAttrCheck(newVertexAttrIndex[i], i); + } + } if ((vertexFormat & GeometryArray.NORMALS) != 0) { newNormalIndex = computeMaxIndex(initialIndexIndex, validIndexCount, indexNormal); doNormalCheck(newNormalIndex); @@ -1650,6 +1735,11 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { maxTexCoordIndices[i] = newTexCoordIndex[i]; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = newVertexAttrIndex[i]; + } + } maxNormalIndex = newNormalIndex; } else { @@ -1660,6 +1750,11 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { maxTexCoordIndices[i] = maxCoordIndex; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (int i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = maxCoordIndex; + } + } } geomLock.unLock(); // bbox is computed for the entries list. @@ -1676,6 +1771,7 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { int getValidIndexCount() { return validIndexCount; } + void handleFrequencyChange(int bit) { if ((bit == IndexedGeometryArray.ALLOW_COORDINATE_INDEX_WRITE) || (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) && @@ -1684,10 +1780,14 @@ abstract class IndexedGeometryArrayRetained extends GeometryArrayRetained { (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) && ((vertexFormat & GeometryArray.NORMALS) != 0) && bit == IndexedGeometryArray.ALLOW_NORMAL_INDEX_WRITE) || + (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0)&& + ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0)&& + bit == IndexedGeometryArray.ALLOW_VERTEX_ATTR_INDEX_WRITE) || (((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0)&& ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0)&& bit == IndexedGeometryArray.ALLOW_TEXCOORD_INDEX_WRITE)) { - setFrequencyChangeMask(bit, 0x1); + + setFrequencyChangeMask(bit, 0x1); } else { super.handleFrequencyChange(bit); diff --git a/src/classes/share/javax/media/j3d/IndexedGeometryStripArray.java b/src/classes/share/javax/media/j3d/IndexedGeometryStripArray.java index adce5e3..8f9073d 100644 --- a/src/classes/share/javax/media/j3d/IndexedGeometryStripArray.java +++ b/src/classes/share/javax/media/j3d/IndexedGeometryStripArray.java @@ -27,21 +27,19 @@ public abstract class IndexedGeometryStripArray extends IndexedGeometryArray { * Constructs an empty IndexedGeometryStripArray object with the specified * number of vertices, vertex format, number of indices, and * array of per-strip index counts. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * * @param stripIndexCounts array that specifies * the count of the number of indices for each separate strip. * The length of this array is the number of separate strips. @@ -49,7 +47,10 @@ public abstract class IndexedGeometryStripArray extends IndexedGeometryArray { * of valid indexed vertices that are rendered (validIndexCount). * * @exception IllegalArgumentException if - * <code>validIndexCount > indexCount</code> + * <code>validIndexCount > indexCount</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public IndexedGeometryStripArray(int vertexCount, int vertexFormat, @@ -67,56 +68,25 @@ public abstract class IndexedGeometryStripArray extends IndexedGeometryArray { * sets, texture coordinate mapping array, number of indices, and * array of per-strip index counts. * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered.<p> + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. * * @param stripIndexCounts array that specifies * the count of the number of indices for each separate strip. @@ -125,7 +95,10 @@ public abstract class IndexedGeometryStripArray extends IndexedGeometryArray { * of valid indexed vertices that are rendered (validIndexCount). * * @exception IllegalArgumentException if - * <code>validIndexCount > indexCount</code> + * <code>validIndexCount > indexCount</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -143,6 +116,69 @@ public abstract class IndexedGeometryStripArray extends IndexedGeometryArray { setStripIndexCounts(stripIndexCounts); } + /** + * Constructs an empty IndexedGeometryStripArray object with the + * specified number of vertices, vertex format, number of texture + * coordinate sets, texture coordinate mapping array, vertex + * attribute count, vertex attribute sizes array, number of + * indices, and array of per-strip index counts. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @param stripIndexCounts array that specifies + * the count of the number of indices for each separate strip. + * The length of this array is the number of separate strips. + * The sum of the elements in this array defines the total number + * of valid indexed vertices that are rendered (validIndexCount). + * + * @exception IllegalArgumentException if + * <code>validIndexCount > indexCount</code> + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedGeometryStripArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount, + int[] stripIndexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, + indexCount); + + ((IndexedGeometryStripArrayRetained)this.retained). + setStripIndexCounts(stripIndexCounts); + } + /** * Get number of strips in the GeometryStripArray * @return numStrips number of strips diff --git a/src/classes/share/javax/media/j3d/IndexedGeometryStripArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedGeometryStripArrayRetained.java index 0b7958a..7e6c09d 100644 --- a/src/classes/share/javax/media/j3d/IndexedGeometryStripArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedGeometryStripArrayRetained.java @@ -32,15 +32,10 @@ abstract class IndexedGeometryStripArrayRetained extends IndexedGeometryArrayRet /** * Set stripIndexCount data into local array */ - void setStripIndexCounts(int stripIndexCounts[]){ - + void setStripIndexCounts(int stripIndexCounts[]) { int i, num = stripIndexCounts.length, total = 0; - - - - - for (i=0; i < num; i++) { + for (i=0; i < num; i++) { total += stripIndexCounts[i]; if (this instanceof IndexedLineStripArrayRetained) { if (stripIndexCounts[i] < 2) { @@ -65,7 +60,8 @@ abstract class IndexedGeometryStripArrayRetained extends IndexedGeometryArrayRet int newCoordMax =0; int newColorIndex=0; int newNormalIndex=0; - int newTexCoordIndex[]=null; + int[] newTexCoordIndex = null; + int[] newVertexAttrIndex = null; newCoordMax = computeMaxIndex(initialIndexIndex, total, indexCoord); doErrorCheck(newCoordMax); @@ -78,10 +74,19 @@ abstract class IndexedGeometryStripArrayRetained extends IndexedGeometryArrayRet newTexCoordIndex = new int[texCoordSetCount]; for (i = 0; i < texCoordSetCount; i++) { newTexCoordIndex[i] = computeMaxIndex(initialIndexIndex,total, - (int[])indexTexCoord[i]); + indexTexCoord[i]); doTexCoordCheck(newTexCoordIndex[i], i); } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + newVertexAttrIndex = new int[vertexAttrCount]; + for (i = 0; i < vertexAttrCount; i++) { + newVertexAttrIndex[i] = computeMaxIndex(initialIndexIndex, + total, + indexVertexAttr[i]); + doTexCoordCheck(newVertexAttrIndex[i], i); + } + } if ((vertexFormat & GeometryArray.NORMALS) != 0) { newNormalIndex = computeMaxIndex(initialIndexIndex, total, indexNormal); doNormalCheck(newNormalIndex); @@ -103,6 +108,11 @@ abstract class IndexedGeometryStripArrayRetained extends IndexedGeometryArrayRet maxTexCoordIndices[i] = newTexCoordIndex[i]; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = newVertexAttrIndex[i]; + } + } maxNormalIndex = newNormalIndex; } else { @@ -113,6 +123,11 @@ abstract class IndexedGeometryStripArrayRetained extends IndexedGeometryArrayRet maxTexCoordIndices[i] = maxCoordIndex; } } + if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + for (i = 0; i < vertexAttrCount; i++) { + maxVertexAttrIndices[i] = maxCoordIndex; + } + } } geomLock.unLock(); // bbox is computed for the entries list. @@ -123,7 +138,7 @@ abstract class IndexedGeometryStripArrayRetained extends IndexedGeometryArrayRet } - Object cloneNonIndexedGeometry() { + GeometryArrayRetained cloneNonIndexedGeometry() { GeometryStripArrayRetained obj = null; int i; switch (this.geoType) { @@ -137,11 +152,14 @@ abstract class IndexedGeometryStripArrayRetained extends IndexedGeometryArrayRet obj = new TriangleStripArrayRetained(); break; } - obj.createGeometryArrayData(validIndexCount, (vertexFormat & ~(GeometryArray.BY_REFERENCE|GeometryArray.INTERLEAVED|GeometryArray.USE_NIO_BUFFER)), texCoordSetCount, texCoordSetMap); + obj.createGeometryArrayData(validIndexCount, + (vertexFormat & ~(GeometryArray.BY_REFERENCE|GeometryArray.INTERLEAVED|GeometryArray.USE_NIO_BUFFER)), + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); obj.unIndexify(this); obj.setStripVertexCounts(stripIndexCounts); - return (Object)obj; + return obj; } diff --git a/src/classes/share/javax/media/j3d/IndexedLineArray.java b/src/classes/share/javax/media/j3d/IndexedLineArray.java index a28e613..28d267a 100644 --- a/src/classes/share/javax/media/j3d/IndexedLineArray.java +++ b/src/classes/share/javax/media/j3d/IndexedLineArray.java @@ -25,113 +25,142 @@ public class IndexedLineArray extends IndexedGeometryArray { } /** - * Constructs an empty IndexedLineArray object with the specified - * number of vertices, vertex format, and number of indices. - * @param vertexCount the number of vertex elements in this object - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedLineArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 2, or indexCount is <i>not</i> * a multiple of 2 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public IndexedLineArray(int vertexCount, int vertexFormat, int indexCount) { super(vertexCount,vertexFormat, indexCount); - if (vertexCount < 1) - throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray0")); + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray0")); - if (indexCount < 2 || ((indexCount%2) != 0)) + if (indexCount < 2 || ((indexCount%2) != 0)) throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray1")); } /** - * Constructs an empty IndexedLineArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, and number of indices. - * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3 or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedLineArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 2, or indexCount is <i>not</i> * a multiple of 2 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ public IndexedLineArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int indexCount) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + indexCount); + + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray0")); + + if (indexCount < 2 || ((indexCount%2) != 0)) + throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray1")); + } + + /** + * Constructs an empty IndexedLineArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1, + * or indexCount is less than 2, or indexCount is <i>not</i> + * a multiple of 2 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedLineArray(int vertexCount, int vertexFormat, int texCoordSetCount, int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, int indexCount) { super(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, indexCount); - if (vertexCount < 1) - throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray0")); + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray0")); - if (indexCount < 2 || ((indexCount%2) != 0)) + if (indexCount < 2 || ((indexCount%2) != 0)) throw new IllegalArgumentException(J3dI18N.getString("IndexedLineArray1")); } @@ -148,22 +177,26 @@ public class IndexedLineArray extends IndexedGeometryArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - IndexedLineArrayRetained rt = (IndexedLineArrayRetained) retained; - int texSetCount = rt.getTexCoordSetCount(); - IndexedLineArray l; - if (texSetCount == 0) { - l = new IndexedLineArray(rt.getVertexCount(), - rt.getVertexFormat(), - rt.getIndexCount()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - l = new IndexedLineArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - rt.getIndexCount()); - } + IndexedLineArrayRetained rt = (IndexedLineArrayRetained) retained; + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + IndexedLineArray l = new IndexedLineArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + rt.getIndexCount()); l.duplicateNodeComponent(this); return l; } diff --git a/src/classes/share/javax/media/j3d/IndexedLineArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedLineArrayRetained.java index 54b4f14..bb9731f 100644 --- a/src/classes/share/javax/media/j3d/IndexedLineArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedLineArrayRetained.java @@ -25,15 +25,16 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { IndexedLineArrayRetained() { this.geoType = GEO_TYPE_INDEXED_LINE_SET; } - - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { - Point3d pnts[] = new Point3d[2]; + + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { + Point3d pnts[] = new Point3d[2]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; - int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? + int count = 0; + int minICount = 0; + int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); - pnts[0] = new Point3d(); pnts[1] = new Point3d(); @@ -44,15 +45,16 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); - + count += 2; if (intersectLineAndRay(pnts[0], pnts[1], pickRay.origin, pickRay.direction, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -70,20 +72,21 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); + count += 2; if (intersectLineAndRay(pnts[0], pnts[1], pickSegment.start, dir, sdist, iPnt) && (sdist[0] <= 1.0)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; } - } } break; @@ -94,12 +97,14 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); + count += 2; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -115,12 +120,14 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); + count += 2; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -135,12 +142,14 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); + count += 2; if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -154,12 +163,14 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); + count += 2; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -173,12 +184,14 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); + count += 2; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -194,15 +207,22 @@ class IndexedLineArrayRetained extends IndexedGeometryArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=2); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[2]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 2; + vertexIndices[1] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; - return true; + return true; } return false; - } + } boolean intersect(Point3d[] pnts) { Point3d[] points = new Point3d[2]; diff --git a/src/classes/share/javax/media/j3d/IndexedLineStripArray.java b/src/classes/share/javax/media/j3d/IndexedLineStripArray.java index 6a32086..34dbf3b 100644 --- a/src/classes/share/javax/media/j3d/IndexedLineStripArray.java +++ b/src/classes/share/javax/media/j3d/IndexedLineStripArray.java @@ -30,35 +30,36 @@ public class IndexedLineStripArray extends IndexedGeometryStripArray { } /** - * Constructs an empty IndexedLineStripArray object with the specified - * number of vertices, vertex format, number of indices, and - * array of per-strip index counts. - * @param vertexCount the number of vertex elements in this object - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. - * @param stripIndexCounts array that specifies - * the count of the number of indices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty IndexedLineStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[])} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 2, * or any element in the stripIndexCounts array is less than 2 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[])} + * for more exceptions that can be thrown */ public IndexedLineStripArray(int vertexCount, - int vertexFormat, - int indexCount, - int stripIndexCounts[]) { + int vertexFormat, + int indexCount, + int[] stripIndexCounts) { super(vertexCount, vertexFormat, indexCount, stripIndexCounts); @@ -70,81 +71,113 @@ public class IndexedLineStripArray extends IndexedGeometryStripArray { } /** - * Constructs an empty IndexedLineStripArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, number of indices, and - * array of per-strip index counts. - * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered.<p> - * - * @param stripIndexCounts array that specifies - * the count of the number of indices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty IndexedLineStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 2, * or any element in the stripIndexCounts array is less than 2 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ public IndexedLineStripArray(int vertexCount, - int vertexFormat, - int texCoordSetCount, - int[] texCoordSetMap, - int indexCount, - int stripIndexCounts[]) { + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int indexCount, + int[] stripIndexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + indexCount, stripIndexCounts); + + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedLineStripArray0")); + + if (indexCount < 2 ) + throw new IllegalArgumentException(J3dI18N.getString("IndexedLineStripArray1")); + } + + /** + * Constructs an empty IndexedLineStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[],int,int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1, + * or indexCount is less than 2, + * or any element in the stripIndexCounts array is less than 2 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedLineStripArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount, + int[] stripIndexCounts) { super(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, indexCount, stripIndexCounts); if (vertexCount < 1) @@ -168,29 +201,30 @@ public class IndexedLineStripArray extends IndexedGeometryStripArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - IndexedLineStripArrayRetained rt = - (IndexedLineStripArrayRetained) retained; + IndexedLineStripArrayRetained rt = + (IndexedLineStripArrayRetained) retained; int stripIndexCounts[] = new int[rt.getNumStrips()]; - rt.getStripIndexCounts(stripIndexCounts); - int texSetCount = rt.getTexCoordSetCount(); - IndexedLineStripArray l; - - if (texSetCount == 0) { - l = new IndexedLineStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - rt.getIndexCount(), - stripIndexCounts); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - l = new IndexedLineStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - rt.getIndexCount(), - stripIndexCounts); - - } + rt.getStripIndexCounts(stripIndexCounts); + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + IndexedLineStripArray l = new IndexedLineStripArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + rt.getIndexCount(), + stripIndexCounts); l.duplicateNodeComponent(this); return l; } diff --git a/src/classes/share/javax/media/j3d/IndexedLineStripArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedLineStripArrayRetained.java index 7a91bd5..8791b9f 100644 --- a/src/classes/share/javax/media/j3d/IndexedLineStripArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedLineStripArrayRetained.java @@ -29,14 +29,14 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { geoType = GEO_TYPE_INDEXED_LINE_STRIP_SET; } - - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[2]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int scount, j, i = 0; int count = 0; + int minICount = 0; pnts[0] = new Point3d(); pnts[1] = new Point3d(); @@ -54,14 +54,15 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { if (intersectLineAndRay(pnts[0], pnts[1], pickRay.origin, pickRay.direction, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -85,14 +86,15 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { pickSegment.start, dir, sdist, iPnt) && (sdist[0] <= 1.0)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -111,14 +113,15 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { getVertexData(indexCoord[count++], pnts[1]); if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -138,14 +141,15 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { getVertexData(indexCoord[count++], pnts[1]); if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -164,14 +168,15 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { getVertexData(indexCoord[count++], pnts[1]); if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -189,14 +194,15 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { getVertexData(indexCoord[count++], pnts[1]); if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -214,14 +220,15 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { getVertexData(indexCoord[count++], pnts[1]); if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -236,14 +243,20 @@ class IndexedLineStripArrayRetained extends IndexedGeometryStripArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=2); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[2]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 2; + vertexIndices[1] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; return true; } return false; - } // intersect pnts[] with every triangle in this object diff --git a/src/classes/share/javax/media/j3d/IndexedPointArray.java b/src/classes/share/javax/media/j3d/IndexedPointArray.java index c780d34..7f01bd2 100644 --- a/src/classes/share/javax/media/j3d/IndexedPointArray.java +++ b/src/classes/share/javax/media/j3d/IndexedPointArray.java @@ -26,25 +26,26 @@ public class IndexedPointArray extends IndexedGeometryArray { } /** - * Constructs an empty IndexedPointArray object with the specified - * number of vertices, vertex format, and number of indices. - * @param vertexCount the number of vertex elements in this object - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedPointArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1 * or indexCount is less than 1 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public IndexedPointArray(int vertexCount, int vertexFormat, int indexCount) { super(vertexCount,vertexFormat, indexCount); @@ -57,63 +58,34 @@ public class IndexedPointArray extends IndexedGeometryArray { } /** - * Constructs an empty IndexedPointArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, and number of indices. - * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3 or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedPointArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1 * or indexCount is less than 1 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -135,6 +107,62 @@ public class IndexedPointArray extends IndexedGeometryArray { } /** + * Constructs an empty IndexedPointArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1 + * or indexCount is less than 1 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedPointArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, + indexCount); + + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedPointArray0")); + + if (indexCount < 1 ) + throw new IllegalArgumentException(J3dI18N.getString("IndexedPointArray1")); + } + + /** * Creates the retained mode IndexedPointArrayRetained object that this * IndexedPointArray object will point to. */ @@ -148,22 +176,26 @@ public class IndexedPointArray extends IndexedGeometryArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - IndexedPointArrayRetained rt = (IndexedPointArrayRetained) retained; - int texSetCount = rt.getTexCoordSetCount(); - IndexedPointArray p; - if (texSetCount == 0) { - p = new IndexedPointArray(rt.getVertexCount(), - rt.getVertexFormat(), - rt.getIndexCount()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - p = new IndexedPointArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - rt.getIndexCount()); - } + IndexedPointArrayRetained rt = (IndexedPointArrayRetained) retained; + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + IndexedPointArray p = new IndexedPointArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + rt.getIndexCount()); p.duplicateNodeComponent(this); return p; } diff --git a/src/classes/share/javax/media/j3d/IndexedPointArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedPointArrayRetained.java index 8c63a73..f7289c5 100644 --- a/src/classes/share/javax/media/j3d/IndexedPointArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedPointArrayRetained.java @@ -25,10 +25,12 @@ class IndexedPointArrayRetained extends IndexedGeometryArrayRetained { this.geoType = GEO_TYPE_INDEXED_POINT_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { - double sdist[] = new double[1]; + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { + double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; + int count = 0; + int minICount = 0; Point3d pnt = new Point3d(); int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); @@ -39,13 +41,15 @@ class IndexedPointArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnt); + count++; if (intersectPntAndRay(pnt, pickRay.origin, pickRay.direction, sdist)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -62,19 +66,20 @@ class IndexedPointArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnt); + count++; if (intersectPntAndRay(pnt, pickSegment.start, dir, sdist) && (sdist[0] <= 1.0)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; } - } } break; @@ -85,33 +90,35 @@ class IndexedPointArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnt); + count++; if (bounds.intersect(pnt)) { - if (dist == null) { + if (flags == 0) { return true; } sdist[0] = pickShape.distance(pnt); if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; } } } - break; case PickShape.PICKCYLINDER: PickCylinder pickCylinder= (PickCylinder) pickShape; while (i < validVertexCount) { getVertexData(indexCoord[i++], pnt); - + count++; if (intersectCylinder(pnt, pickCylinder, sdist)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -124,13 +131,14 @@ class IndexedPointArrayRetained extends IndexedGeometryArrayRetained { while (i < validVertexCount) { getVertexData(indexCoord[i++], pnt); - + count++; if (intersectCone(pnt, pickCone, sdist)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -146,7 +154,13 @@ class IndexedPointArrayRetained extends IndexedGeometryArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=1); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[1]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; diff --git a/src/classes/share/javax/media/j3d/IndexedQuadArray.java b/src/classes/share/javax/media/j3d/IndexedQuadArray.java index 4368340..1c94c4b 100644 --- a/src/classes/share/javax/media/j3d/IndexedQuadArray.java +++ b/src/classes/share/javax/media/j3d/IndexedQuadArray.java @@ -27,26 +27,27 @@ public class IndexedQuadArray extends IndexedGeometryArray { } /** - * Constructs an empty IndexedQuadArray object with the specified - * number of vertices, vertex format, and number of indices. - * @param vertexCount the number of vertex elements in this object - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedQuadArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 4, or indexCount is <i>not</i> * a multiple of 4 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public IndexedQuadArray(int vertexCount, int vertexFormat, int indexCount) { super(vertexCount,vertexFormat, indexCount); @@ -59,64 +60,35 @@ public class IndexedQuadArray extends IndexedGeometryArray { } /** - * Constructs an empty IndexedQuadArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, and number of indices. - * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedQuadArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 4, or indexCount is <i>not</i> * a multiple of 4 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -138,6 +110,63 @@ public class IndexedQuadArray extends IndexedGeometryArray { } /** + * Constructs an empty IndexedQuadArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1, + * or indexCount is less than 4, or indexCount is <i>not</i> + * a multiple of 4 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedQuadArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, + indexCount); + + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedQuadArray0")); + + if (indexCount < 4 || ((indexCount%4) != 0)) + throw new IllegalArgumentException(J3dI18N.getString("IndexedQuadArray1")); + } + + /** * Creates the retained mode IndexedQuadArrayRetained object that this * IndexedQuadArray object will point to. */ @@ -151,23 +180,26 @@ public class IndexedQuadArray extends IndexedGeometryArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - IndexedQuadArrayRetained rt = (IndexedQuadArrayRetained) retained; - int texSetCount = rt.getTexCoordSetCount(); - IndexedQuadArray q; - - if (texSetCount == 0) { - q = new IndexedQuadArray(rt.getVertexCount(), - rt.getVertexFormat(), - rt.getIndexCount()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - q = new IndexedQuadArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - rt.getIndexCount()); - } + IndexedQuadArrayRetained rt = (IndexedQuadArrayRetained) retained; + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + IndexedQuadArray q = new IndexedQuadArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + rt.getIndexCount()); q.duplicateNodeComponent(this); return q; } diff --git a/src/classes/share/javax/media/j3d/IndexedQuadArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedQuadArrayRetained.java index f06c62d..355f471 100644 --- a/src/classes/share/javax/media/j3d/IndexedQuadArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedQuadArrayRetained.java @@ -27,15 +27,15 @@ class IndexedQuadArrayRetained extends IndexedGeometryArrayRetained { this.geoType = GEO_TYPE_INDEXED_QUAD_SET; } - - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[4]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; + int count = 0; + int minICount = 0; int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? - initialVertexIndex : initialCoordIndex); - + initialVertexIndex : initialCoordIndex); pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); @@ -50,12 +50,14 @@ class IndexedQuadArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); getVertexData(indexCoord[i++], pnts[3]); + count += 4; if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -71,18 +73,19 @@ class IndexedQuadArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); getVertexData(indexCoord[i++], pnts[3]); + count += 4; if (intersectSegment(pnts, pickSegment.start, pickSegment.end, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } - + } } } break; @@ -94,108 +97,108 @@ class IndexedQuadArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); getVertexData(indexCoord[i++], pnts[3]); - + count += 4; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } } - break; case PickShape.PICKBOUNDINGSPHERE: BoundingSphere bsphere = (BoundingSphere) ((PickBounds) pickShape).bounds; - while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); getVertexData(indexCoord[i++], pnts[3]); - + count += 4; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } } break; case PickShape.PICKBOUNDINGPOLYTOPE: - BoundingPolytope bpolytope = (BoundingPolytope) ((PickBounds) pickShape).bounds; - while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); getVertexData(indexCoord[i++], pnts[3]); - + count += 4; if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } } break; case PickShape.PICKCYLINDER: PickCylinder pickCylinder= (PickCylinder) pickShape; - while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); getVertexData(indexCoord[i++], pnts[3]); - + count += 4; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } } break; case PickShape.PICKCONE: PickCone pickCone= (PickCone) pickShape; - while (i < validVertexCount) { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); getVertexData(indexCoord[i++], pnts[3]); + count += 4; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } } break; @@ -207,7 +210,16 @@ class IndexedQuadArrayRetained extends IndexedGeometryArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >= 4); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[4]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 4; + vertexIndices[1] = minICount - 3; + vertexIndices[2] = minICount - 2; + vertexIndices[3] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; @@ -215,8 +227,7 @@ class IndexedQuadArrayRetained extends IndexedGeometryArrayRetained { } return false; - } - + } // intersect pnts[] with every quad in this object boolean intersect(Point3d[] pnts) { diff --git a/src/classes/share/javax/media/j3d/IndexedTriangleArray.java b/src/classes/share/javax/media/j3d/IndexedTriangleArray.java index 300a812..3f923a4 100644 --- a/src/classes/share/javax/media/j3d/IndexedTriangleArray.java +++ b/src/classes/share/javax/media/j3d/IndexedTriangleArray.java @@ -27,32 +27,32 @@ public class IndexedTriangleArray extends IndexedGeometryArray { } /** - * Constructs an empty IndexedTriangleArray object with the specified - * number of vertices, vertex format, and number of indices. - * @param vertexCount the number of vertex elements in this object - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedTriangleArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 3, or indexCount is <i>not</i> * a multiple of 3 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ - public IndexedTriangleArray(int vertexCount, int vertexFormat, - int indexCount) { + public IndexedTriangleArray(int vertexCount, int vertexFormat, int indexCount) { super(vertexCount,vertexFormat, indexCount); - if (vertexCount < 1) + if (vertexCount < 1) throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleArray0")); if (indexCount < 3 || ((indexCount%3) != 0)) @@ -60,64 +60,35 @@ public class IndexedTriangleArray extends IndexedGeometryArray { } /** - * Constructs an empty IndexedTriangleArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, and number of indices. - * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. + * Constructs an empty IndexedTriangleArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 3, or indexCount is <i>not</i> * a multiple of 3 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -131,7 +102,64 @@ public class IndexedTriangleArray extends IndexedGeometryArray { texCoordSetCount, texCoordSetMap, indexCount); - if (vertexCount < 1) + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleArray0")); + + if (indexCount < 3 || ((indexCount%3) != 0)) + throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleArray1")); + } + + /** + * Constructs an empty IndexedTriangleArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1, + * or indexCount is less than 3, or indexCount is <i>not</i> + * a multiple of 3 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedTriangleArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, + indexCount); + + if (vertexCount < 1) throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleArray0")); if (indexCount < 3 || ((indexCount%3) != 0)) @@ -152,23 +180,26 @@ public class IndexedTriangleArray extends IndexedGeometryArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - IndexedTriangleArrayRetained rt = (IndexedTriangleArrayRetained) retained; - int texSetCount = rt.getTexCoordSetCount(); - IndexedTriangleArray t; - - if (texSetCount == 0) { - t = new IndexedTriangleArray(rt.getVertexCount(), - rt.getVertexFormat(), - rt.getIndexCount()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - t = new IndexedTriangleArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - rt.getIndexCount()); - } + IndexedTriangleArrayRetained rt = (IndexedTriangleArrayRetained) retained; + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + IndexedTriangleArray t = new IndexedTriangleArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + rt.getIndexCount()); t.duplicateNodeComponent(this); return t; } diff --git a/src/classes/share/javax/media/j3d/IndexedTriangleArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedTriangleArrayRetained.java index f76dc69..d977894 100644 --- a/src/classes/share/javax/media/j3d/IndexedTriangleArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedTriangleArrayRetained.java @@ -27,14 +27,15 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { this.geoType = GEO_TYPE_INDEXED_TRI_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[3]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; + int count = 0; + int minICount = 0; int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); - pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); @@ -47,15 +48,17 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); + count += 3; if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } } @@ -66,18 +69,19 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); - if (intersectSegment(pnts, pickSegment.start, - pickSegment.end, sdist, iPnt) - && (sdist[0] <= 1.0)) { - if (dist == null) { + count += 3; + if (intersectSegment(pnts, pickSegment.start, + pickSegment.end, sdist, iPnt)) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; - } + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; + } } } break; @@ -89,15 +93,17 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); + count += 3; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } } @@ -110,15 +116,17 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); + count += 3; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } } @@ -131,16 +139,18 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); - if (intersectBoundingPolytope(pnts, bpolytope, + count += 3; + if (intersectBoundingPolytope(pnts, bpolytope, sdist,iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } } @@ -151,16 +161,18 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); + count += 3; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } } @@ -172,15 +184,17 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { getVertexData(indexCoord[i++], pnts[0]); getVertexData(indexCoord[i++], pnts[1]); getVertexData(indexCoord[i++], pnts[2]); + count += 3; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } } @@ -194,7 +208,15 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >= 3); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[3]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 3; + vertexIndices[1] = minICount - 2; + vertexIndices[2] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; @@ -203,7 +225,6 @@ class IndexedTriangleArrayRetained extends IndexedGeometryArrayRetained { return false; } - // intersect pnts[] with every triangle in this object boolean intersect(Point3d[] pnts) { Point3d[] points = new Point3d[3]; diff --git a/src/classes/share/javax/media/j3d/IndexedTriangleFanArray.java b/src/classes/share/javax/media/j3d/IndexedTriangleFanArray.java index 795de14..d094859 100644 --- a/src/classes/share/javax/media/j3d/IndexedTriangleFanArray.java +++ b/src/classes/share/javax/media/j3d/IndexedTriangleFanArray.java @@ -29,39 +29,40 @@ public class IndexedTriangleFanArray extends IndexedGeometryStripArray { IndexedTriangleFanArray() {} /** - * Constructs an empty IndexedTriangleFanArray object with the specified - * number of vertices, vertex format, number of indices, and - * array of per-strip index counts. - * @param vertexCount the number of vertex elements in this object - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. - * @param stripIndexCounts array that specifies - * the count of the number of indices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty IndexedTriangleFanArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[])} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 3, * or any element in the stripIndexCounts array is less than 3 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[])} + * for more exceptions that can be thrown */ public IndexedTriangleFanArray(int vertexCount, int vertexFormat, int indexCount, - int stripIndexCounts[]) { + int[] stripIndexCounts) { super(vertexCount, vertexFormat, indexCount, stripIndexCounts); - if (vertexCount < 1) + if (vertexCount < 1) throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleFanArray0")); if (indexCount < 3 ) @@ -69,69 +70,39 @@ public class IndexedTriangleFanArray extends IndexedGeometryStripArray { } /** - * Constructs an empty IndexedTriangleFanArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, number of indices, and - * array of per-strip index counts. - * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3 or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered.<p> - * - * @param stripIndexCounts array that specifies - * the count of the number of indices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty IndexedTriangleFanArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 3, * or any element in the stripIndexCounts array is less than 3 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -140,13 +111,75 @@ public class IndexedTriangleFanArray extends IndexedGeometryStripArray { int texCoordSetCount, int[] texCoordSetMap, int indexCount, - int stripIndexCounts[]) { + int[] stripIndexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + indexCount, stripIndexCounts); + + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleFanArray0")); + + if (indexCount < 3 ) + throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleFanArray1")); + } + + /** + * Constructs an empty IndexedTriangleFanArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[],int,int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1, + * or indexCount is less than 3, + * or any element in the stripIndexCounts array is less than 3 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedTriangleFanArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount, + int[] stripIndexCounts) { super(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, indexCount, stripIndexCounts); - if (vertexCount < 1) + if (vertexCount < 1) throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleFanArray0")); if (indexCount < 3 ) @@ -167,29 +200,30 @@ public class IndexedTriangleFanArray extends IndexedGeometryStripArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - IndexedTriangleFanArrayRetained rt = - (IndexedTriangleFanArrayRetained) retained; - int stripIndexCounts[] = new int[rt.getNumStrips()]; - rt.getStripIndexCounts(stripIndexCounts); - int texSetCount = rt.getTexCoordSetCount(); - IndexedTriangleFanArray t; - - if (texSetCount == 0) { - t = new IndexedTriangleFanArray(rt.getVertexCount(), - rt.getVertexFormat(), - rt.getIndexCount(), - stripIndexCounts); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - t = new IndexedTriangleFanArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - rt.getIndexCount(), - stripIndexCounts); - } - + IndexedTriangleFanArrayRetained rt = + (IndexedTriangleFanArrayRetained) retained; + int stripIndexCounts[] = new int[rt.getNumStrips()]; + rt.getStripIndexCounts(stripIndexCounts); + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + IndexedTriangleFanArray t = new IndexedTriangleFanArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + rt.getIndexCount(), + stripIndexCounts); t.duplicateNodeComponent(this); return t; } diff --git a/src/classes/share/javax/media/j3d/IndexedTriangleFanArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedTriangleFanArrayRetained.java index b4f0066..c6e37f7 100644 --- a/src/classes/share/javax/media/j3d/IndexedTriangleFanArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedTriangleFanArrayRetained.java @@ -32,15 +32,16 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained geoType = GEO_TYPE_INDEXED_TRI_FAN_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[3]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int i = 0; - int j, scount, count = 0; - - pnts[0] = new Point3d(); + int j, scount, count = 0, fSCount; + int minICount = 0; + int minFSCount = 0; + pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); @@ -48,22 +49,25 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained case PickShape.PICKRAY: PickRay pickRay= (PickRay) pickShape; - while (i < stripIndexCounts.length) { + while (i < stripIndexCounts.length) { + fSCount = count; getVertexData(indexCoord[count++], pnts[0]); getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -74,21 +78,24 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained PickSegment pickSegment = (PickSegment) pickShape; while (i < stripIndexCounts.length) { + fSCount = count; getVertexData(indexCoord[count++], pnts[0]); getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(j++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectSegment(pnts, pickSegment.start, pickSegment.end, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -100,20 +107,23 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained ((PickBounds) pickShape).bounds; while (i < stripIndexCounts.length) { + fSCount = count; getVertexData(indexCoord[count++], pnts[0]); getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -125,22 +135,25 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained ((PickBounds) pickShape).bounds; while (i < stripIndexCounts.length) { + fSCount = count; getVertexData(indexCoord[count++], pnts[0]); getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -152,22 +165,25 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained ((PickBounds) pickShape).bounds; while (i < stripIndexCounts.length) { + fSCount = count; getVertexData(indexCoord[count++], pnts[0]); getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -178,21 +194,24 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained PickCylinder pickCylinder= (PickCylinder) pickShape; while (i < stripIndexCounts.length) { + fSCount = count; getVertexData(indexCoord[count++], pnts[0]); getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -203,21 +222,24 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained PickCone pickCone= (PickCone) pickShape; while (i < stripIndexCounts.length) { + fSCount = count; getVertexData(indexCoord[count++], pnts[0]); getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -232,14 +254,22 @@ class IndexedTriangleFanArrayRetained extends IndexedGeometryStripArrayRetained } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >= 3); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[3]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minFSCount; + vertexIndices[1] = minICount - 2; + vertexIndices[2] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; - return true; + return true; } return false; - } + } // intersect pnts[] with every triangle in this object boolean intersect(Point3d[] pnts) { diff --git a/src/classes/share/javax/media/j3d/IndexedTriangleStripArray.java b/src/classes/share/javax/media/j3d/IndexedTriangleStripArray.java index 13970bb..b5395db 100644 --- a/src/classes/share/javax/media/j3d/IndexedTriangleStripArray.java +++ b/src/classes/share/javax/media/j3d/IndexedTriangleStripArray.java @@ -31,35 +31,36 @@ public class IndexedTriangleStripArray extends IndexedGeometryStripArray { } /** - * Constructs an empty IndexedTriangleStripArray object with the specified - * number of vertices, vertex format, number of indices, and - * array of per-strip index counts. - * @param vertexCount the number of vertex elements in this object - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered. - * @param stripIndexCounts array that specifies - * the count of the number of indices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty IndexedTriangleStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[])} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 3, * or any element in the stripIndexCounts array is less than 3 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[])} + * for more exceptions that can be thrown */ public IndexedTriangleStripArray(int vertexCount, int vertexFormat, int indexCount, - int stripIndexCounts[]) { + int[] stripIndexCounts) { super(vertexCount, vertexFormat, indexCount, stripIndexCounts); @@ -71,69 +72,39 @@ public class IndexedTriangleStripArray extends IndexedGeometryStripArray { } /** - * Constructs an empty IndexedTriangleStripArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, number of indices, and - * array of per-strip index counts. - * - * @param vertexCount the number of vertex elements in this object<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code> or - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param indexCount the number of indices in this object. This - * count is the maximum number of vertices that will be rendered.<p> - * - * @param stripIndexCounts array that specifies - * the count of the number of indices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty IndexedTriangleStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1, * or indexCount is less than 3, * or any element in the stripIndexCounts array is less than 3 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -142,10 +113,72 @@ public class IndexedTriangleStripArray extends IndexedGeometryStripArray { int texCoordSetCount, int[] texCoordSetMap, int indexCount, - int stripIndexCounts[]) { + int[] stripIndexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + indexCount, stripIndexCounts); + + if (vertexCount < 1) + throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleStripArray0")); + + if (indexCount < 3 ) + throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleStripArray1")); + } + + /** + * Constructs an empty IndexedTriangleStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param indexCount + * see {@link IndexedGeometryArray#IndexedGeometryArray(int,int,int,int[],int,int[],int)} + * for a description of this parameter. + * + * @param stripIndexCounts + * see {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[],int,int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1, + * or indexCount is less than 3, + * or any element in the stripIndexCounts array is less than 3 + * ;<br> + * See {@link IndexedGeometryStripArray#IndexedGeometryStripArray(int,int,int,int[],int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public IndexedTriangleStripArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int indexCount, + int[] stripIndexCounts) { super(vertexCount, vertexFormat, texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, indexCount, stripIndexCounts); if (vertexCount < 1) @@ -169,28 +202,31 @@ public class IndexedTriangleStripArray extends IndexedGeometryStripArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - IndexedTriangleStripArrayRetained rt = - (IndexedTriangleStripArrayRetained) retained; + IndexedTriangleStripArrayRetained rt = + (IndexedTriangleStripArrayRetained) retained; int stripIndexCounts[] = new int[rt.getNumStrips()]; - rt.getStripIndexCounts(stripIndexCounts); - int texSetCount = rt.getTexCoordSetCount(); - IndexedTriangleStripArray l; - if (texSetCount == 0) { - l = new IndexedTriangleStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - rt.getIndexCount(), - stripIndexCounts); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - l = new IndexedTriangleStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - rt.getIndexCount(), - stripIndexCounts); - } - l.duplicateNodeComponent(this); - return l; + rt.getStripIndexCounts(stripIndexCounts); + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + IndexedTriangleStripArray t = new IndexedTriangleStripArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + rt.getIndexCount(), + stripIndexCounts); + t.duplicateNodeComponent(this); + return t; } } diff --git a/src/classes/share/javax/media/j3d/IndexedTriangleStripArrayRetained.java b/src/classes/share/javax/media/j3d/IndexedTriangleStripArrayRetained.java index 5e2b017..888b0de 100644 --- a/src/classes/share/javax/media/j3d/IndexedTriangleStripArrayRetained.java +++ b/src/classes/share/javax/media/j3d/IndexedTriangleStripArrayRetained.java @@ -31,14 +31,14 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine geoType = GEO_TYPE_INDEXED_TRI_STRIP_SET; } - - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[3]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int i = 0; int j, scount, count = 0; + int minICount = 0; pnts[0] = new Point3d(); pnts[1] = new Point3d(); @@ -54,17 +54,18 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; - } + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; + } } pnts[0].set(pnts[1]); pnts[1].set(pnts[2]); @@ -79,17 +80,18 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(j++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectSegment(pnts, pickSegment.start, pickSegment.end, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -106,16 +108,17 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine getVertexData(indexCoord[count++], pnts[1]); scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -133,17 +136,18 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -161,17 +165,18 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -188,16 +193,17 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -214,16 +220,17 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine scount = stripIndexCounts[i++]; for (j=2; j < scount; j++) { - getVertexData(count++, pnts[2]); + getVertexData(indexCoord[count++], pnts[2]); if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -239,15 +246,23 @@ class IndexedTriangleStripArrayRetained extends IndexedGeometryStripArrayRetaine } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=3); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[3]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 3; + vertexIndices[1] = minICount - 2; + vertexIndices[2] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; - return true; + return true; } return false; } - + // intersect pnts[] with every triangle in this object boolean intersect(Point3d[] pnts) { int j, end; diff --git a/src/classes/share/javax/media/j3d/IndexedUnorderSet.java b/src/classes/share/javax/media/j3d/IndexedUnorderSet.java index 89d3a4a..54e4b36 100644 --- a/src/classes/share/javax/media/j3d/IndexedUnorderSet.java +++ b/src/classes/share/javax/media/j3d/IndexedUnorderSet.java @@ -60,7 +60,7 @@ package javax.media.j3d; class IndexedUnorderSet implements Cloneable, java.io.Serializable { - // TODO: set to false when release + // XXXX: set to false when release final static boolean debug = false; /** diff --git a/src/classes/share/javax/media/j3d/J3DBuffer.java b/src/classes/share/javax/media/j3d/J3DBuffer.java index 6422dc1..6cc97cf 100644 --- a/src/classes/share/javax/media/j3d/J3DBuffer.java +++ b/src/classes/share/javax/media/j3d/J3DBuffer.java @@ -25,21 +25,11 @@ import com.sun.j3d.internal.ByteOrderWrapper; * <code>rewind</code> on the read-only view, so that elements 0 * through <code>buffer.limit()-1</code> will be available internally. * - * <p> - * NOTE: Use of this class requires version 1.4 of the - * Java<sup><font size="-2">TM</font></sup> 2 Platform. - * Any attempt to access this class on an earlier version of the - * Java 2 Platform will fail with a NoClassDefFoundError. - * Refer to the documentation for version 1.4 of the Java 2 SDK - * for a description of the - * <code> - * <a href="http://java.sun.com/j2se/1.4/docs/api/java/nio/package-summary.html">java.nio</a> - * </code> package. - * * @see GeometryArray#setCoordRefBuffer(J3DBuffer) * @see GeometryArray#setColorRefBuffer(J3DBuffer) * @see GeometryArray#setNormalRefBuffer(J3DBuffer) * @see GeometryArray#setTexCoordRefBuffer(int,J3DBuffer) + * @see GeometryArray#setVertexAttrRefBuffer(int,J3DBuffer) * @see GeometryArray#setInterleavedVertexBuffer(J3DBuffer) * @see CompressedGeometry#CompressedGeometry(CompressedGeometryHeader,J3DBuffer) * diff --git a/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java b/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java index 2ed6814..439b0f7 100644 --- a/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java +++ b/src/classes/share/javax/media/j3d/J3DGraphics2DImpl.java @@ -140,7 +140,7 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { } } // Behavior Scheduler or other threads - // TODO: may not be legal for behaviorScheduler + // XXXX: may not be legal for behaviorScheduler // May cause deadlock if it is in behaviorScheduler // and we wait for Renderer to finish boolean renderRun = (Thread.currentThread() != @@ -589,13 +589,13 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { public final void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawArc(x, y, width, height, startAngle, arcAngle); } public final void drawGlyphVector(GlyphVector g, float x, float y) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawGlyphVector(g, x, y); } @@ -619,29 +619,29 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { } validate(minx, miny, maxx, maxy); } else { - // TODO: call validate with bounding box of primitive - // TODO: Need to consider Stroke width + // XXXX: call validate with bounding box of primitive + // XXXX: Need to consider Stroke width validate(); } offScreenGraphics2D.drawLine(x1, y1, x2, y2); } public final void drawOval(int x, int y, int width, int height) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawOval(x, y, width, height); } public final void drawPolygon(int xPoints[], int yPoints[], int nPoints) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawPolygon(xPoints, yPoints, nPoints); } public final void drawPolyline(int xPoints[], int yPoints[], int nPoints) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawPolyline(xPoints, yPoints, nPoints); } @@ -661,7 +661,7 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { public final void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawRoundRect(x, y, width, height, arcWidth, arcHeight); @@ -669,14 +669,14 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { public final void drawString(AttributedCharacterIterator iterator, int x, int y) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawString(iterator, x, y); } public final void drawString(AttributedCharacterIterator iterator, float x, float y) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawString(iterator, x, y); } @@ -706,20 +706,20 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { public final void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.fillArc(x, y, width, height, startAngle, arcAngle); } public final void fillOval(int x, int y, int width, int height) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.fillOval(x, y, width, height); } public final void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.fillRoundRect(x, y, width, height, arcWidth, arcHeight); @@ -810,59 +810,59 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { public void draw3DRect(int x, int y, int width, int height, boolean raised) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.draw3DRect(x, y, width, height, raised); } public void drawBytes(byte data[], int offset, int length, int x, int y) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawBytes(data, offset, length, x, y); } public void drawChars(char data[], int offset, int length, int x, int y) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawChars(data, offset, length, x, y); } public void drawPolygon(Polygon p) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.drawPolygon(p); } public void drawRect(int x, int y, int width, int height) { - // TODO: call validate with bounding box of primitive - // TODO: need to consider Stroke width + // XXXX: call validate with bounding box of primitive + // XXXX: need to consider Stroke width validate(); offScreenGraphics2D.drawRect(x, y, width, height); } public void fill3DRect(int x, int y, int width, int height, boolean raised) { - // TODO: call validate with bounding box of primitive - // TODO: need to consider Stroke width + // XXXX: call validate with bounding box of primitive + // XXXX: need to consider Stroke width validate(); offScreenGraphics2D.fill3DRect(x, y, width, height, raised); } public void fillPolygon(Polygon p) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.fillPolygon(p); } public final void fillPolygon(int xPoints[], int yPoints[], int nPoints) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.fillPolygon(xPoints, yPoints, nPoints); } public final void fillRect(int x, int y, int width, int height) { - // TODO: call validate with bounding box of primitive + // XXXX: call validate with bounding box of primitive validate(); offScreenGraphics2D.fillRect(x, y, width, height); } @@ -888,7 +888,7 @@ final class J3DGraphics2DImpl extends J3DGraphics2D { doDrawAndFlushImage(img, x, y, observer); } else { // Behavior Scheduler or other threads - // TODO: may not be legal for behaviorScheduler + // XXXX: may not be legal for behaviorScheduler // May cause deadlock if it is in behaviorScheduler // and we wait for Renderer to finish boolean renderRun = (Thread.currentThread() != diff --git a/src/classes/share/javax/media/j3d/J3dMessage.java b/src/classes/share/javax/media/j3d/J3dMessage.java index 625f2df..d2d073d 100644 --- a/src/classes/share/javax/media/j3d/J3dMessage.java +++ b/src/classes/share/javax/media/j3d/J3dMessage.java @@ -84,6 +84,9 @@ class J3dMessage extends Object { static final int ORDERED_GROUP_TABLE_CHANGED = 59; static final int BEHAVIOR_REEVALUATE = 60; static final int CREATE_OFFSCREENBUFFER = 61; + static final int SHADER_ATTRIBUTE_CHANGED = 62; + static final int SHADER_ATTRIBUTE_SET_CHANGED = 63; + static final int SHADER_APPEARANCE_CHANGED = 64; /** * This is the time snapshot at which this change occured diff --git a/src/classes/share/javax/media/j3d/J3dNotification.java b/src/classes/share/javax/media/j3d/J3dNotification.java new file mode 100644 index 0000000..8560295 --- /dev/null +++ b/src/classes/share/javax/media/j3d/J3dNotification.java @@ -0,0 +1,42 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * J3dNotification is used to hold data for asynchronous error notification. + */ + +class J3dNotification extends Object { + /** + * The various notification types. + */ + static final int INVALID_TYPE = -1; + static final int SHADER_ERROR = 0; + + /** + * This holds the type of this message + */ + int type = INVALID_TYPE; + + /** + * The universe that this message originated from + */ + VirtualUniverse universe; + + /** + * The arguements for a message, 6 for now + */ + static final int MAX_ARGS = 6; + + Object[] args = new Object[MAX_ARGS]; +} diff --git a/src/classes/share/javax/media/j3d/Light.java b/src/classes/share/javax/media/j3d/Light.java index 2588607..47c479a 100644 --- a/src/classes/share/javax/media/j3d/Light.java +++ b/src/classes/share/javax/media/j3d/Light.java @@ -220,6 +220,14 @@ public abstract class Light extends Leaf { public static final int ALLOW_SCOPE_WRITE = CapabilityBits.LIGHT_ALLOW_SCOPE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_STATE_READ, + ALLOW_COLOR_READ, + ALLOW_INFLUENCING_BOUNDS_READ, + ALLOW_SCOPE_READ + }; + /** * Constructs a Light node with default parameters. The default * values are as follows: @@ -232,6 +240,8 @@ public abstract class Light extends Leaf { * </ul> */ public Light() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -239,7 +249,10 @@ public abstract class Light extends Leaf { * @param color the color of the light source */ public Light(Color3f color) { - ((LightRetained)this.retained).initColor(color); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((LightRetained)this.retained).initColor(color); } /** @@ -249,7 +262,10 @@ public abstract class Light extends Leaf { * @param color the color of the light source */ public Light(boolean lightOn, Color3f color) { - ((LightRetained)this.retained).initEnable(lightOn); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((LightRetained)this.retained).initEnable(lightOn); ((LightRetained)this.retained).initColor(color); } diff --git a/src/classes/share/javax/media/j3d/LineArray.java b/src/classes/share/javax/media/j3d/LineArray.java index f2d0e12..da484d1 100644 --- a/src/classes/share/javax/media/j3d/LineArray.java +++ b/src/classes/share/javax/media/j3d/LineArray.java @@ -27,23 +27,22 @@ public class LineArray extends GeometryArray { } /** - * Constructs an empty LineArray object with the specified - * number of vertices, and vertex format. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. + * Constructs an empty LineArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 2 * or vertexCount is <i>not</i> a multiple of 2 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public LineArray(int vertexCount, int vertexFormat) { super(vertexCount,vertexFormat); @@ -53,60 +52,30 @@ public class LineArray extends GeometryArray { } /** - * Constructs an empty LineArray object with the specified - * number of vertices, and vertex format, number of texture coordinate - * sets, and texture coordinate mapping array. - * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used. + * Constructs an empty LineArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 2 * or vertexCount is <i>not</i> a multiple of 2 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -123,6 +92,53 @@ public class LineArray extends GeometryArray { } /** + * Constructs an empty LineArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 2 + * or vertexCount is <i>not</i> a multiple of 3 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public LineArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); + + if (vertexCount < 2 || ((vertexCount%2) != 0)) + throw new IllegalArgumentException(J3dI18N.getString("LineArray0")); + } + + /** * Creates the retained mode LineArrayRetained object that this * LineArray object will point to. */ @@ -137,23 +153,24 @@ public class LineArray extends GeometryArray { */ public NodeComponent cloneNodeComponent() { LineArrayRetained rt = (LineArrayRetained) retained; - - - int texSetCount = rt.getTexCoordSetCount(); - LineArray l; - if (texSetCount == 0) { - l = new LineArray(rt.getVertexCount(), - rt.getVertexFormat()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - l = new LineArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap); - - } - + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + LineArray l = new LineArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes); l.duplicateNodeComponent(this); return l; } diff --git a/src/classes/share/javax/media/j3d/LineArrayRetained.java b/src/classes/share/javax/media/j3d/LineArrayRetained.java index b29597a..2b07b54 100644 --- a/src/classes/share/javax/media/j3d/LineArrayRetained.java +++ b/src/classes/share/javax/media/j3d/LineArrayRetained.java @@ -25,15 +25,16 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { LineArrayRetained() { this.geoType = GEO_TYPE_LINE_SET; } - - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[2]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; + int count = 0; + int minICount = 0; int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); - pnts[0] = new Point3d(); pnts[1] = new Point3d(); @@ -44,18 +45,20 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); + count += 2; if (intersectLineAndRay(pnts[0], pnts[1], pickRay.origin, pickRay.direction, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } } break; @@ -69,20 +72,21 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); + count += 2; if (intersectLineAndRay(pnts[0], pnts[1], pickSegment.start, dir, sdist, iPnt) && (sdist[0] <= 1.0)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; } - } } break; @@ -92,12 +96,14 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); + count += 2; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -113,12 +119,14 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); + count += 2; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -133,12 +141,14 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); + count += 2; if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -152,12 +162,14 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); + count += 2; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -171,12 +183,14 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); + count += 2; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -192,7 +206,14 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=2); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[2]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 2; + vertexIndices[1] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; @@ -200,8 +221,7 @@ class LineArrayRetained extends GeometryArrayRetained implements Cloneable { } return false; - } - + } boolean intersect(Point3d[] pnts) { Point3d[] points = new Point3d[2]; diff --git a/src/classes/share/javax/media/j3d/LineAttributes.java b/src/classes/share/javax/media/j3d/LineAttributes.java index ca2d569..c60a68c 100644 --- a/src/classes/share/javax/media/j3d/LineAttributes.java +++ b/src/classes/share/javax/media/j3d/LineAttributes.java @@ -169,7 +169,13 @@ public class LineAttributes extends NodeComponent { */ public static final int PATTERN_USER_DEFINED = 4; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_ANTIALIASING_READ, + ALLOW_PATTERN_READ, + ALLOW_WIDTH_READ + }; + /** * Constructs a LineAttributes object with default parameters. * The default values are as follows: @@ -182,6 +188,8 @@ public class LineAttributes extends NodeComponent { * </ul> */ public LineAttributes(){ + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -197,6 +205,9 @@ public class LineAttributes extends NodeComponent { if (linePattern < PATTERN_SOLID || linePattern > PATTERN_DASH_DOT) throw new IllegalArgumentException(J3dI18N.getString("LineAttributes0")); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((LineAttributesRetained)this.retained).initLineWidth(lineWidth); ((LineAttributesRetained)this.retained).initLinePattern(linePattern); ((LineAttributesRetained)this.retained).initLineAntialiasingEnable(lineAntialiasing); diff --git a/src/classes/share/javax/media/j3d/LineStripArray.java b/src/classes/share/javax/media/j3d/LineStripArray.java index ef9ce5a..00581d2 100644 --- a/src/classes/share/javax/media/j3d/LineStripArray.java +++ b/src/classes/share/javax/media/j3d/LineStripArray.java @@ -30,28 +30,26 @@ public class LineStripArray extends GeometryStripArray { } /** - * Constructs an empty LineStripArray object with the specified - * number of vertices, vertex format, and - * array of per-strip vertex counts. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param stripVertexCounts array that specifies - * the count of the number of vertices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty LineStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 2 * or any element in the stripVertexCounts array is less than 2 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int[])} + * for more exceptions that can be thrown */ public LineStripArray(int vertexCount, int vertexFormat, @@ -64,65 +62,34 @@ public class LineStripArray extends GeometryStripArray { } /** - * Constructs an empty LineStripArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, and - * array of per-strip vertex counts. - * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param stripVertexCounts array that specifies - * the count of the number of vertices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty LineStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 2 * or any element in the stripVertexCounts array is less than 2 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -141,6 +108,59 @@ public class LineStripArray extends GeometryStripArray { } /** + * Constructs an empty LineStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int,int[],int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 2 + * or any element in the stripVertexCounts array is less than 2 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int,int[],int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public LineStripArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int[] stripVertexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, + stripVertexCounts); + + if (vertexCount < 2 ) + throw new IllegalArgumentException(J3dI18N.getString("LineStripArray0")); + } + + /** * Creates the retained mode LineStripArrayRetained object that this * LineStripArray object will point to. */ @@ -153,24 +173,28 @@ public class LineStripArray extends GeometryStripArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - LineStripArrayRetained rt = (LineStripArrayRetained) retained; + LineStripArrayRetained rt = (LineStripArrayRetained) retained; int stripcounts[] = new int[rt.getNumStrips()]; - rt.getStripVertexCounts(stripcounts); - int texSetCount = rt.getTexCoordSetCount(); - LineStripArray l; - if (texSetCount == 0) { - l = new LineStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - stripcounts); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - l = new LineStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - stripcounts); - } + rt.getStripVertexCounts(stripcounts); + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + LineStripArray l = new LineStripArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + stripcounts); l.duplicateNodeComponent(this); return l; } diff --git a/src/classes/share/javax/media/j3d/LineStripArrayRetained.java b/src/classes/share/javax/media/j3d/LineStripArrayRetained.java index 4270d74..69fa80b 100644 --- a/src/classes/share/javax/media/j3d/LineStripArrayRetained.java +++ b/src/classes/share/javax/media/j3d/LineStripArrayRetained.java @@ -30,14 +30,15 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { this.geoType = GEO_TYPE_LINE_STRIP_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[2]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int j, end; int i = 0; - + int count = 0; + int minICount = 0; pnts[0] = new Point3d(); pnts[1] = new Point3d(); @@ -49,20 +50,22 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); + count++; while (j < end) { getVertexData(j++, pnts[1]); - + count++; if (intersectLineAndRay(pnts[0], pnts[1], pickRay.origin, pickRay.direction, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -80,21 +83,23 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); - while (j < end) { + count++; + while (j < end) { getVertexData(j++, pnts[1]); - + count++; if (intersectLineAndRay(pnts[0], pnts[1], pickSegment.start, dir, sdist, iPnt) && (sdist[0] <= 1.0)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -109,17 +114,20 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); + count++; while (j < end) { getVertexData(j++, pnts[1]); + count++; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -135,17 +143,20 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); + count++; while (j < end) { getVertexData(j++, pnts[1]); + count++; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -160,17 +171,20 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); + count++; while (j < end) { getVertexData(j++, pnts[1]); + count++; if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -184,18 +198,20 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); + count++; while (j < end) { getVertexData(j++, pnts[1]); - + count++; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -209,17 +225,20 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); + count++; while (j < end) { getVertexData(j++, pnts[1]); + count++; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[0].set(pnts[1]); @@ -234,14 +253,20 @@ class LineStripArrayRetained extends GeometryStripArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >= 2); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[2]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 2; + vertexIndices[1] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; return true; } - return false; - + return false; } boolean intersect(Point3d[] pnts) { diff --git a/src/classes/share/javax/media/j3d/LinearFog.java b/src/classes/share/javax/media/j3d/LinearFog.java index 5232d32..4aa543f 100644 --- a/src/classes/share/javax/media/j3d/LinearFog.java +++ b/src/classes/share/javax/media/j3d/LinearFog.java @@ -25,14 +25,16 @@ import javax.vecmath.Color3f; * the node, but the actual fog equation will ideally take place in eye * coordinates. * <P> - * The linear fog blending factor, f, is computed as follows: - * <P><UL> - * f = backDistance - z / backDistance - frontDistance<P> - * where - * <ul>z is the distance from the viewpoint.<br> - * frontDistance is the distance at which fog starts obscuring objects.<br> - * backDistance is the distance at which fog totally obscurs objects. - * </ul><P></UL> + * The linear fog blending factor, <code>f</code>, is computed as follows: + * <ul> + * <code>f = (backDistance - z) / (backDistance - frontDistance)</code> + * </ul> + * where: + * <ul> + * <code>z</code> is the distance from the viewpoint.<br> + * <code>frontDistance</code> is the distance at which fog starts obscuring objects.<br> + * <code>backDistance</code> is the distance at which fog totally obscurs objects. + * </ul> */ public class LinearFog extends Fog { /** @@ -49,6 +51,11 @@ public class LinearFog extends Fog { public static final int ALLOW_DISTANCE_WRITE = CapabilityBits.LINEAR_FOG_ALLOW_DISTANCE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_DISTANCE_READ + }; + /** * Constructs a LinearFog node with default parameters. * The default values are as follows: @@ -59,6 +66,8 @@ public class LinearFog extends Fog { */ public LinearFog() { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -67,6 +76,9 @@ public class LinearFog extends Fog { */ public LinearFog(Color3f color) { super(color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -77,6 +89,10 @@ public class LinearFog extends Fog { */ public LinearFog(Color3f color, double frontDistance, double backDistance) { super(color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((LinearFogRetained)this.retained).initFrontDistance(frontDistance); ((LinearFogRetained)this.retained).initBackDistance(backDistance); } @@ -89,6 +105,9 @@ public class LinearFog extends Fog { */ public LinearFog(float r, float g, float b) { super(r, g, b); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -102,6 +121,10 @@ public class LinearFog extends Fog { public LinearFog(float r, float g, float b, double frontDistance, double backDistance) { super(r, g, b); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((LinearFogRetained)this.retained).initFrontDistance(frontDistance); ((LinearFogRetained)this.retained).initBackDistance(backDistance); } diff --git a/src/classes/share/javax/media/j3d/LinearFogRetained.java b/src/classes/share/javax/media/j3d/LinearFogRetained.java index 4f7b723..4eff1ec 100644 --- a/src/classes/share/javax/media/j3d/LinearFogRetained.java +++ b/src/classes/share/javax/media/j3d/LinearFogRetained.java @@ -24,12 +24,10 @@ class LinearFogRetained extends FogRetained { /** * Fog front and back distance */ - double frontDistance = 0.1; - double backDistance = 1.0; - double localToVworldScale = 1.0; - double frontDistanceInEc; - double backDistanceInEc; - double vworldToCoexistenceScale; + private double frontDistance = 0.1; + private double backDistance = 1.0; + private double frontDistanceInEc; + private double backDistanceInEc; // dirty bits for LinearFog static final int FRONT_DISTANCE_CHANGED = FogRetained.LAST_DEFINED_BIT << 1; @@ -169,29 +167,21 @@ class LinearFogRetained extends FogRetained { ((LinearFogRetained)mirrorFog).backDistance = ((Double)((Object[])objs[4])[5]).doubleValue(); } - ((LinearFogRetained)mirrorFog).localToVworldScale = - getLastLocalToVworld().getDistanceScale(); - + ((LinearFogRetained)mirrorFog).setLocalToVworldScale(getLastLocalToVworld().getDistanceScale()); super.updateMirrorObject(objs); } /** * Scale distances from local to eye coordinate - */ - - void validateDistancesInEc(double vworldToCoexistenceScale) { + */ + protected void validateDistancesInEc(double vworldToCoexistenceScale) { // vworldToCoexistenceScale can be used here since // CoexistenceToEc has a unit scale - double localToEcScale = localToVworldScale * vworldToCoexistenceScale; + double localToEcScale = getLocalToVworldScale() * vworldToCoexistenceScale; frontDistanceInEc = frontDistance * localToEcScale; backDistanceInEc = backDistance * localToEcScale; } - // Called on mirror object - void updateTransformChange() { - super.updateTransformChange(); - localToVworldScale = sgFog.getLastLocalToVworld().getDistanceScale(); - } } diff --git a/src/classes/share/javax/media/j3d/Link.java b/src/classes/share/javax/media/j3d/Link.java index 151952c..549c3aa 100644 --- a/src/classes/share/javax/media/j3d/Link.java +++ b/src/classes/share/javax/media/j3d/Link.java @@ -34,11 +34,18 @@ public class Link extends Leaf { public static final int ALLOW_SHARED_GROUP_WRITE = CapabilityBits.LINK_ALLOW_SHARED_GROUP_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SHARED_GROUP_READ + }; + /** * Constructs a Link node object that does not yet point to a * SharedGroup node. */ public Link() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -47,7 +54,10 @@ public class Link extends Leaf { * @param sharedGroup the SharedGroup node */ public Link(SharedGroup sharedGroup) { - ((LinkRetained)this.retained).setSharedGroup(sharedGroup); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((LinkRetained)this.retained).setSharedGroup(sharedGroup); } /** diff --git a/src/classes/share/javax/media/j3d/LinkRetained.java b/src/classes/share/javax/media/j3d/LinkRetained.java index f9dafb5..9ba765c 100644 --- a/src/classes/share/javax/media/j3d/LinkRetained.java +++ b/src/classes/share/javax/media/j3d/LinkRetained.java @@ -293,7 +293,7 @@ class LinkRetained extends LeafRetained { super.compile(compState); - // TODO: for now keep the static transform in the parent tg + // XXXX: for now keep the static transform in the parent tg compState.keepTG = true; // don't remove this group node diff --git a/src/classes/share/javax/media/j3d/Locale.java b/src/classes/share/javax/media/j3d/Locale.java index ecb4c86..157cbde 100644 --- a/src/classes/share/javax/media/j3d/Locale.java +++ b/src/classes/share/javax/media/j3d/Locale.java @@ -158,6 +158,7 @@ public class Locale extends Object { throw new MultipleParentException(J3dI18N.getString("Locale0")); } + universe.notifyStructureChangeListeners(true, this, branchGroup); universe.resetWaitMCFlag(); synchronized (universe.sceneGraphLock) { doAddBranchGraph(branchGroup); @@ -377,6 +378,7 @@ public class Locale extends Object { universe); } universe.setLiveState.reset(null); // cleanup memory + universe.notifyStructureChangeListeners(false, this, branchGroup); } /** @@ -408,10 +410,12 @@ public class Locale extends Object { throw new MultipleParentException(J3dI18N.getString("Locale3")); } universe.resetWaitMCFlag(); + universe.notifyStructureChangeListeners(true, this, newGroup); synchronized (universe.sceneGraphLock) { doReplaceBranchGraph(oldGroup, newGroup); universe.setLiveState.reset(this); } + universe.notifyStructureChangeListeners(false, this, oldGroup); universe.waitForMC(); } @@ -494,7 +498,7 @@ public class Locale extends Object { createMessage.args[4] = universe.setLiveState.ogCIOTableList.toArray(); VirtualUniverse.mc.processMessage(createMessage); - // TODO: make these two into one message + // XXXX: make these two into one message createMessage = VirtualUniverse.mc.getMessage(); createMessage.threads = universe.setLiveState.notifyThreads; createMessage.type = J3dMessage.INSERT_NODES; @@ -525,11 +529,8 @@ public class Locale extends Object { createMessage.universe = universe; VirtualUniverse.mc.processMessage(createMessage); - // Free up memory. universe.setLiveState.reset(null); - - } /** @@ -553,7 +554,47 @@ public class Locale extends Object { return branchGroups.elements(); } + + void validateModeFlagAndPickShape(int mode, int flags, PickShape pickShape) { + + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + if((mode != PickInfo.PICK_BOUNDS) && (mode != PickInfo.PICK_GEOMETRY)) { + + throw new IllegalArgumentException(J3dI18N.getString("Locale5")); + } + + if((pickShape instanceof PickPoint) && (mode == PickInfo.PICK_GEOMETRY)) { + throw new IllegalArgumentException(J3dI18N.getString("Locale6")); + } + + if(((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) && + ((flags & PickInfo.ALL_GEOM_INFO) != 0)) { + throw new IllegalArgumentException(J3dI18N.getString("Locale7")); + } + + if((mode == PickInfo.PICK_BOUNDS) && + (((flags & (PickInfo.CLOSEST_GEOM_INFO | + PickInfo.ALL_GEOM_INFO | + PickInfo.CLOSEST_DISTANCE | + PickInfo.CLOSEST_INTERSECTION_POINT)) != 0))) { + + throw new IllegalArgumentException(J3dI18N.getString("Locale8")); + } + + if((pickShape instanceof PickBounds) && + (((flags & (PickInfo.CLOSEST_GEOM_INFO | + PickInfo.ALL_GEOM_INFO | + PickInfo.CLOSEST_DISTANCE | + PickInfo.CLOSEST_INTERSECTION_POINT)) != 0))) { + + throw new IllegalArgumentException(J3dI18N.getString("Locale9")); + } + } + /** * Returns an array referencing all the items that are pickable below this * <code>Locale</code> that intersect with PickShape. @@ -571,12 +612,103 @@ public class Locale extends Object { throw new IllegalStateException(J3dI18N.getString("Locale4")); } - return Picking.pickAll( this, pickShape ); + PickInfo[] pickInfoArr = pickAll( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfoArr == null) { + return null; + } + SceneGraphPath[] sgpArr = new SceneGraphPath[pickInfoArr.length]; + for( int i=0; i<sgpArr.length; i++) { + sgpArr[i] = pickInfoArr[i].getSceneGraphPath(); + } + + return sgpArr; + } /** - * Returns a sorted array of references to all the Pickable items + * Returns an array unsorted references to all the PickInfo objects that are pickable + * below this <code>Locale</code> that intersect with PickShape. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickAll(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo[] pickAll( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + + GeometryAtom geomAtoms[] = universe.geometryStructure.pickAll(this, pickShape); + + return PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ALL); + + } + + /** + * Returns a sorted array of references to all the pickable items * that intersect with the pickShape. Element [0] references the * item closest to <i>origin</i> of PickShape successive array * elements are further from the <i>origin</i> @@ -596,9 +728,118 @@ public class Locale extends Object { throw new IllegalStateException(J3dI18N.getString("Locale4")); } - return Picking.pickAllSorted( this, pickShape ); + PickInfo[] pickInfoArr = pickAllSorted( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfoArr == null) { + return null; + } + SceneGraphPath[] sgpArr = new SceneGraphPath[pickInfoArr.length]; + for( int i=0; i<sgpArr.length; i++) { + sgpArr[i] = pickInfoArr[i].getSceneGraphPath(); + } + + return sgpArr; + } + /** + * Returns a sorted array of PickInfo references to all the pickable + * items that intersect with the pickShape. Element [0] references + * the item closest to <i>origin</i> of PickShape successive array + * elements are further from the <i>origin</i> + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickAllSorted(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo[] pickAllSorted( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + GeometryAtom geomAtoms[] = universe.geometryStructure.pickAll(this, pickShape); + + if ((geomAtoms == null) || (geomAtoms.length == 0)) { + return null; + } + + PickInfo[] pickInfoArr = null; + + if (mode == PickInfo.PICK_GEOMETRY) { + // Need to have closestDistance set + flags |= PickInfo.CLOSEST_DISTANCE; + pickInfoArr= PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ALL); + if (pickInfoArr != null) { + PickInfo.sortPickInfoArray(pickInfoArr); + } + } + else { + PickInfo.sortGeomAtoms(geomAtoms, pickShape); + pickInfoArr= PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ALL); + } + + return pickInfoArr; + } /** * Returns a SceneGraphPath which references the pickable item @@ -615,13 +856,101 @@ public class Locale extends Object { * @see BranchGroup#pickClosest */ public SceneGraphPath pickClosest( PickShape pickShape ) { - if (universe == null) { - throw new IllegalStateException(J3dI18N.getString("Locale4")); - } + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } - return Picking.pickClosest( this, pickShape ); + PickInfo pickInfo = pickClosest( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfo == null) { + return null; + } + return pickInfo.getSceneGraphPath(); } + /** + * Returns a PickInfo which references the pickable item + * which is closest to the origin of <code>pickShape</code>. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickClosest(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo pickClosest( int mode, int flags, PickShape pickShape ) { + + PickInfo[] pickInfoArr = null; + + pickInfoArr = pickAllSorted( mode, flags, pickShape ); + + if(pickInfoArr == null) { + return null; + } + + return pickInfoArr[0]; + + } /** * Returns a reference to any item that is Pickable below this @@ -638,10 +967,100 @@ public class Locale extends Object { if (universe == null) { throw new IllegalStateException(J3dI18N.getString("Locale4")); } - - return Picking.pickAny( this, pickShape ); + + PickInfo pickInfo = pickAny( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfo == null) { + return null; + } + return pickInfo.getSceneGraphPath(); + } + /** + * Returns a PickInfo which references the pickable item below this + * Locale which intersects with <code>pickShape</code>. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickAny(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo pickAny( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + GeometryAtom geomAtoms[] = universe.geometryStructure.pickAll(this, pickShape); + + PickInfo[] pickInfoArr = PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ANY); + + if(pickInfoArr == null) { + return null; + } + + return pickInfoArr[0]; + + } /** * Cleans up resources associated with this Locale diff --git a/src/classes/share/javax/media/j3d/MasterControl.java b/src/classes/share/javax/media/j3d/MasterControl.java index c70b268..8e15f3f 100644 --- a/src/classes/share/javax/media/j3d/MasterControl.java +++ b/src/classes/share/javax/media/j3d/MasterControl.java @@ -20,6 +20,8 @@ package javax.media.j3d; import java.util.*; import java.awt.*; +import java.io.File; + class MasterControl { @@ -77,6 +79,8 @@ class MasterControl { static final Integer SET_QUERYPROPERTIES = new Integer(20); static final Integer SET_VIEW = new Integer(21); + private static boolean librariesLoaded = false; + /** * reference to MasterControl thread */ @@ -197,6 +201,9 @@ class MasterControl { // Only one Timer thread in the system. TimerThread timerThread; + // Only one Notification thread in the system. + private NotificationThread notificationThread; + /** * This flag indicates that MC is running */ @@ -305,9 +312,11 @@ class MasterControl { // This is a time stamp used when context is created private long contextTimeStamp = 0; - - // This is a counter for canvas bit - private int canvasBitCount = 0; + + // This is an array of canvasIds in used + private boolean[] canvasIds = null; + private int canvasFreeIndex = 0; + private Object canvasIdLock = new Object(); // This is a counter for rendererBit private int rendererCount = 0; @@ -335,15 +344,28 @@ class MasterControl { // Flag that indicates whether separate specular color is disabled or not boolean disableSeparateSpecularColor = false; - // Maximum number of texture units - int textureUnitMax = 100; - // Flag that indicates whether DisplayList is used or not boolean isDisplayList = true; // If this flag is set, then by-ref geometry will not be // put in display list boolean buildDisplayListIfPossible = false; + + // If this flag is set, then geometry arrays with vertex attributes can + // be in display list. + boolean vertexAttrsInDisplayList = false; + + // The global shading language being used. Using a ShaderProgram + // with a shading language other than the one specified by + // globalShadingLanguage will cause a ShaderError to be generated, + static int globalShadingLanguage = Shader.SHADING_LANGUAGE_GLSL; + + // Flags indicating whether the Cg or GLSL libraries are available; we still need + // to check for the actual extension support when the Canvas3D with its associated context + // is created. Note that these are qualifed by the above globalShadingLanguage, so at + // most one of these two flags will be true; + static boolean cgLibraryAvailable = false; + static boolean glslLibraryAvailable = false; // REQUESTCLEANUP messages argument @@ -390,6 +412,9 @@ class MasterControl { // False to disable rescale normal if OGL support boolean isForceNormalized = false; + // True to allow simulated (multi-pass) multi-texture + boolean allowSimulatedMultiTexture = false; + // Hashtable that maps a GraphicsDevice to its associated // Screen3D--this is only used for on-screen Canvas3Ds Hashtable deviceScreenMap = new Hashtable(); @@ -417,6 +442,13 @@ class MasterControl { private ArrayList timestampUpdateList = new ArrayList(3); private UnorderList freeMessageList = new UnorderList(8); + + // System properties containing the native library search PATH + // The order listed is the order in which they will be searched + private static final String[] systemPathProps = { + "sun.boot.library.path", + "java.library.path" + }; long awt; native long getAWT(); @@ -424,6 +456,9 @@ class MasterControl { // Method to initialize the native J3D library private native boolean initializeJ3D(boolean disableXinerama); + // Method to verify whether the native Cg library is available + private static native boolean loadNativeCgLibrary(String[] libpath); + // Method to get number of procesor private native int getNumberOfProcessor(); @@ -464,7 +499,8 @@ class MasterControl { * VirtualUniverse. */ MasterControl() { - + assert librariesLoaded; + // Get AWT handle awt = getAWT(); @@ -522,23 +558,6 @@ class MasterControl { System.err.println("Java 3D: separate specular color disabled if possible"); } - // Get the maximum number of texture units - final int defaultTextureUnitMax = textureUnitMax; - Integer textureUnitLimit = - (Integer) java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - return Integer.getInteger("j3d.textureUnitMax", - defaultTextureUnitMax); - } - }); - - textureUnitMax = textureUnitLimit.intValue(); - if (textureUnitMax != defaultTextureUnitMax) { - System.err.println("Java 3D: maximum number of texture units = " + - textureUnitMax); - } - isDisplayList = getBooleanProperty("j3d.displaylist", isDisplayList, "display list"); @@ -553,24 +572,41 @@ class MasterControl { "compiled vertex array"); isForceNormalized = - getBooleanProperty("j3d.forceNormalized", isForceNormalized, + getBooleanProperty("j3d.forceNormalized", + isForceNormalized, "force normalized"); + allowSimulatedMultiTexture = + getBooleanProperty("j3d.simulatedMultiTexture", + allowSimulatedMultiTexture, + "simulated multi-texture"); + + if (allowSimulatedMultiTexture) { + System.err.println("************************************************************************"); + System.err.println(J3dI18N.getString("MasterControl2")); + System.err.println(J3dI18N.getString("MasterControl3")); + System.err.println("************************************************************************"); + } - boolean j3dOptimizeSpace = + boolean j3dOptimizeSpace = getBooleanProperty("j3d.optimizeForSpace", true, "optimize for space"); - // Build Display list for by-ref geometry and infrequently changing geometry - // ONLY IF (isDisplayList is true and optimizeForSpace if False) - if (isDisplayList && !j3dOptimizeSpace) { - buildDisplayListIfPossible = true; - } - else { - buildDisplayListIfPossible = false; - } + if (isDisplayList) { + // Build Display list for by-ref geometry + // ONLY IF optimizeForSpace is false + if (!j3dOptimizeSpace) { + buildDisplayListIfPossible = true; + } + + // Build display lists for geometry with vertex attributes + // ONLY if we are in GLSL mode and GLSL shaders are available + if (glslLibraryAvailable) { + vertexAttrsInDisplayList = true; + } + } - // Check to see whether Renderer can run without DSI lock + // Check to see whether Renderer can run without DSI lock doDsiRenderLock = getBooleanProperty("j3d.renderLock", doDsiRenderLock, "render lock"); @@ -682,6 +718,16 @@ class MasterControl { // create the freelists FreeListManager.createFreeLists(); + + // create an array canvas use registers + // The 32 limit can be lifted once the + // resourceXXXMasks in other classes + // are change not to use integer. + canvasIds = new boolean[32]; + for(int i=0; i<canvasIds.length; i++) { + canvasIds[i] = false; + } + canvasFreeIndex = 0; } private static String getProperty(final String prop) { @@ -728,7 +774,9 @@ class MasterControl { * the MasterControl object is created. */ static void loadLibraries() { - // This works around a native load library bug + assert !librariesLoaded; + + // This works around a native load library bug try { java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit(); toolkit = null; // just making sure GC collects this @@ -745,37 +793,113 @@ class MasterControl { }); // Load the native J3D library - java.security.AccessController.doPrivileged(new + final String oglLibraryName = "j3dcore-ogl"; + final String d3dLibraryName = "j3dcore-d3d"; + final String libraryName = (String) + java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { public Object run() { - + String libName = oglLibraryName; + + // If it is a Windows OS, we want to support dynamic native library selection (ogl, d3d) String osName = System.getProperty("os.name"); - // System.err.println(" os.name is " + osName ); - // If it is a Windows OS, we want to support - // dynamic native library selection (ogl, d3d) - if((osName.length() > 8) && - ((osName.substring(0,7)).equals("Windows"))){ - - // TODO : Will support a more flexible dynamic - // selection scheme via the use of Preferences API. + if (osName != null && osName.startsWith("Windows")) { + // XXXX : Should eventually support a more flexible dynamic + // selection scheme via an API call. String str = System.getProperty("j3d.rend"); - if ((str == null) || (!str.equals("d3d"))) { - // System.err.println("(1) ogl case : j3d.rend is " + str ); - System.loadLibrary("j3dcore-ogl"); - - } - else { - // System.err.println("(2) d3d case : j3d.rend is " + str); - System.loadLibrary("j3dcore-d3d"); + if (str != null && str.equals("d3d")) { + libName = d3dLibraryName; } } - else { - // System.err.println("(3) ogl case"); - System.loadLibrary("j3dcore-ogl"); - } - return null; + + System.loadLibrary(libName); + return libName; } }); + + // Get the global j3d.shadingLanguage property + final String slStr = getProperty("j3d.shadingLanguage"); + if (slStr != null) { + boolean found = false; + if (slStr.equals("GLSL")) { + globalShadingLanguage = Shader.SHADING_LANGUAGE_GLSL; + found = true; + } + else if (slStr.equals("Cg")) { + globalShadingLanguage = Shader.SHADING_LANGUAGE_CG; + found = true; + } + + if (found) { + System.err.println("Java 3D: Setting global shading language to " + slStr); + } + else { + System.err.println("Java 3D: Unrecognized shading language: " + slStr); + } + } + + // Check whether the Cg library is available + if (globalShadingLanguage == Shader.SHADING_LANGUAGE_CG) { + String cgLibraryName = libraryName + "-cg"; + String[] libpath = setupLibPath(systemPathProps, cgLibraryName); + if (loadNativeCgLibrary(libpath)) { + cgLibraryAvailable = true; + } + } + + // Check whether the GLSL library is available + if (globalShadingLanguage == Shader.SHADING_LANGUAGE_GLSL) { + if (libraryName == oglLibraryName) { + // No need to verify that GLSL is available, since GLSL is part + // of OpenGL as an extension (or part of core in 2.0) + glslLibraryAvailable = true; + } + } + + assert !(glslLibraryAvailable && cgLibraryAvailable) : + "ERROR: cannot support both GLSL and CG at the same time"; + + librariesLoaded = true; + } + + + /** + * Parse the specified System properties containing a PATH and return an + * array of Strings, where each element is an absolute filename consisting of + * the individual component of the path concatenated with the (relative) + * library file name. Only those absolute filenames that exist are included. + * If no absolute filename is found, we will try the relative library name. + */ + private static String[] setupLibPath(String[] props, String libName) { + ArrayList pathList = new ArrayList(); + + String filename = System.mapLibraryName(libName); + for (int n = 0; n < props.length; n++) { + String pathString = getProperty(props[n]); + boolean done = false; + int posStart = 0; + while (!done) { + int posEnd = pathString.indexOf(File.pathSeparator, posStart); + if (posEnd == -1) { + posEnd = pathString.length(); + done = true; + } + String pathDir = pathString.substring(posStart, posEnd); + File pathFile = new File(pathDir, filename); + if (pathFile.exists()) { + pathList.add(pathFile.getAbsolutePath()); + } + + posStart = posEnd + 1; + } + } + + // If no absolute path names exist, add in the relative library name + if (pathList.size() == 0) { + pathList.add(filename); + } + + return (String[])pathList.toArray(new String[0]); } @@ -837,6 +961,14 @@ class MasterControl { return (1 << rendererCount++); } + + /** + * This returns the a unused renderer bit + */ + int getRendererId() { + return rendererCount++; + } + /** * This returns a context creation time stamp * Note: this has to be called under the contextCreationLock @@ -900,28 +1032,39 @@ class MasterControl { FreeListManager.freeObject(FreeListManager.TEXTURE3D, new Integer(id)); } - int getCanvasBit() { - // Master control need to keep count itself - MemoryFreeList cbId = - FreeListManager.getFreeList(FreeListManager.CANVASBIT); - if (cbId.size() > 0) { - return ((Integer)FreeListManager. - getObject(FreeListManager.CANVASBIT)).intValue(); - } - else { - if (canvasBitCount > 31) { + int getCanvasId() { + int i; + + synchronized(canvasIdLock) { + // Master control need to keep count itself + for(i=canvasFreeIndex; i<canvasIds.length; i++) { + if(canvasIds[i] == false) + break; + } + + if ( canvasFreeIndex >= canvasIds.length) { throw new RuntimeException("Cannot render to more than 32 Canvas3Ds"); } - return (1 << canvasBitCount++); + + canvasIds[i] = true; + canvasFreeIndex = i + 1; } + + return i; + } + void freeCanvasId(int canvasId) { + // Valid range is [0, 31] + synchronized(canvasIdLock) { - void freeCanvasBit(int canvasBit) { - FreeListManager.freeObject(FreeListManager.CANVASBIT, - new Integer(canvasBit)); + canvasIds[canvasId] = false; + if(canvasFreeIndex > canvasId) { + canvasFreeIndex = canvasId; + } + } } - + Transform3D getTransform3D(Transform3D val) { Transform3D t; t = (Transform3D) @@ -1096,6 +1239,10 @@ class MasterControl { timerThread.finish(); timerThread = null; } + if (notificationThread != null) { + notificationThread.finish(); + notificationThread = null; + } requestObjList.clear(); requestTypeList.clear(); return true; @@ -1210,7 +1357,14 @@ class MasterControl { } setWork(); } - + + /** + * This takes the specified notification message and sends it to the + * notification thread for processing. + */ + void sendNotification(J3dNotification notification) { + notificationThread.addNotification(notification); + } /** * Create and start the MasterControl Thread. @@ -2050,6 +2204,19 @@ class MasterControl { } }); timerThread.start(); + + // Create notification thread + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + synchronized (rootThreadGroup) { + notificationThread = new NotificationThread(rootThreadGroup); + notificationThread.setPriority(threadPriority); + } + return null; + } + }); + notificationThread.start(); } /** @@ -2099,6 +2266,10 @@ class MasterControl { timerThread.finish(); timerThread = null; } + if (notificationThread != null) { + notificationThread.finish(); + notificationThread = null; + } // shouldn't all of these be synchronized ??? synchronized (VirtualUniverse.mc.deviceScreenMap) { @@ -2112,8 +2283,11 @@ class MasterControl { // list here because other structure may release them // later - FreeListManager.clearList(FreeListManager.CANVASBIT); - canvasBitCount = 0; + for(int i=0; i<canvasIds.length; i++) { + canvasIds[i] = false; + } + canvasFreeIndex = 0; + renderOnceList.clear(); timestampUpdateList.clear(); @@ -3441,7 +3615,7 @@ class MasterControl { static { /* // Determine whether the JVM is version JDK1.5 or later. - // TODO: replace this with code that checks for the existence + // XXXX: replace this with code that checks for the existence // of a class or method that is defined in 1.5, but not in 1.4 String versionString = (String) java.security.AccessController.doPrivileged( diff --git a/src/classes/share/javax/media/j3d/Material.java b/src/classes/share/javax/media/j3d/Material.java index d35c1d5..deacac9 100644 --- a/src/classes/share/javax/media/j3d/Material.java +++ b/src/classes/share/javax/media/j3d/Material.java @@ -103,7 +103,11 @@ public class Material extends NodeComponent { */ public static final int AMBIENT_AND_DIFFUSE = 4; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_COMPONENT_READ + }; + /** * Constructs and initializes a Material object using default parameters. * The default values are as follows: @@ -119,6 +123,8 @@ public class Material extends NodeComponent { */ public Material() { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -139,7 +145,10 @@ public class Material extends NodeComponent { Color3f diffuseColor, Color3f specularColor, float shininess) { - ((MaterialRetained)this.retained).createMaterial(ambientColor, + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((MaterialRetained)this.retained).createMaterial(ambientColor, emissiveColor, diffuseColor, specularColor, shininess); } @@ -602,7 +611,8 @@ public class Material extends NodeComponent { * Capability read bit set will be displayed. */ public String toString() { - StringBuffer str=new StringBuffer("Material Object:"); + StringBuffer str = new StringBuffer(getNamePrefix()); + str.append("javax.media.j3d.Material: "); Color3f color=new Color3f(); try { getAmbientColor(color); diff --git a/src/classes/share/javax/media/j3d/MediaContainer.java b/src/classes/share/javax/media/j3d/MediaContainer.java index 10e1502..e2c6e39 100644 --- a/src/classes/share/javax/media/j3d/MediaContainer.java +++ b/src/classes/share/javax/media/j3d/MediaContainer.java @@ -60,6 +60,12 @@ public class MediaContainer extends NodeComponent { public static final int ALLOW_URL_WRITE = CapabilityBits.MEDIA_CONTAINER_ALLOW_URL_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_CACHE_READ, + ALLOW_URL_READ + }; + /** * Constructs a MediaContainer object with default parameters. * The default values are as follows: @@ -72,6 +78,8 @@ public class MediaContainer extends NodeComponent { */ public MediaContainer() { // Just use default values + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -81,6 +89,9 @@ public class MediaContainer extends NodeComponent { * @exception SoundException if the URL is not valid or cannot be opened */ public MediaContainer(String path) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((MediaContainerRetained)this.retained).setURLString(path); } @@ -91,6 +102,9 @@ public class MediaContainer extends NodeComponent { * @exception SoundException if the URL is not valid or cannot be opened */ public MediaContainer(URL url) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((MediaContainerRetained)this.retained).setURLObject(url); } @@ -102,6 +116,9 @@ public class MediaContainer extends NodeComponent { * @since Java 3D 1.2 */ public MediaContainer(InputStream stream) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((MediaContainerRetained)this.retained).setInputStream(stream); } diff --git a/src/classes/share/javax/media/j3d/MediaContainerRetained.java b/src/classes/share/javax/media/j3d/MediaContainerRetained.java index 19f2547..f120902 100644 --- a/src/classes/share/javax/media/j3d/MediaContainerRetained.java +++ b/src/classes/share/javax/media/j3d/MediaContainerRetained.java @@ -141,7 +141,7 @@ class MediaContainerRetained extends NodeComponentRetained { * @param stream InputStream that references the sound data */ void setInputStream(InputStream stream, boolean forceLoad) { - // %%% TODO AudioDevice not intellegent enough to process InputStreams yet + // XXXX: AudioDevice not intellegent enough to process InputStreams yet // can NOT set stream field unless the other related fields are null if (stream != null) { if (url != null || urlString != null) diff --git a/src/classes/share/javax/media/j3d/ModelClip.java b/src/classes/share/javax/media/j3d/ModelClip.java index 308af79..6895c2d 100644 --- a/src/classes/share/javax/media/j3d/ModelClip.java +++ b/src/classes/share/javax/media/j3d/ModelClip.java @@ -109,7 +109,14 @@ public class ModelClip extends Leaf { public static final int ALLOW_SCOPE_WRITE = CapabilityBits.MODEL_CLIP_ALLOW_SCOPE_WRITE; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SCOPE_READ, + ALLOW_ENABLE_READ, + ALLOW_INFLUENCING_BOUNDS_READ, + ALLOW_PLANE_READ + }; + /** * Constructs a ModelClip node with default parameters. The default * values are as follows: @@ -128,6 +135,9 @@ public class ModelClip extends Leaf { */ public ModelClip() { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } @@ -137,7 +147,10 @@ public class ModelClip extends Leaf { * @param planes an array of 6 model clipping planes */ public ModelClip(Vector4d[] planes) { - ((ModelClipRetained)this.retained).initPlanes(planes); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((ModelClipRetained)this.retained).initPlanes(planes); } @@ -149,6 +162,9 @@ public class ModelClip extends Leaf { * @param enables an array of 6 enable flags */ public ModelClip(Vector4d[] planes, boolean[] enables) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((ModelClipRetained)this.retained).initPlanes(planes); ((ModelClipRetained)this.retained).initEnables(enables); } diff --git a/src/classes/share/javax/media/j3d/Morph.java b/src/classes/share/javax/media/j3d/Morph.java index 9cabaa8..a03edec 100644 --- a/src/classes/share/javax/media/j3d/Morph.java +++ b/src/classes/share/javax/media/j3d/Morph.java @@ -77,6 +77,8 @@ import javax.vecmath.*; * <i>before</i> the indexes are applied. Only the indexes in the * first geometry array (geometry[0]) are used when rendering the * geometry. + * + * @deprecated As of Java 3D version 1.4. */ public class Morph extends Leaf { @@ -149,9 +151,19 @@ public class Morph extends Leaf { public static final int ALLOW_APPEARANCE_OVERRIDE_WRITE = CapabilityBits.MORPH_ALLOW_APPEARANCE_OVERRIDE_WRITE; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_GEOMETRY_ARRAY_READ, + ALLOW_APPEARANCE_READ, + ALLOW_WEIGHTS_READ, + ALLOW_COLLISION_BOUNDS_READ, + ALLOW_APPEARANCE_OVERRIDE_READ + }; + // non public default constructor Morph() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -171,6 +183,7 @@ public class Morph extends Leaf { * a null or zero-length array of GeometryArray objects is * permitted, and specifies that no geometry is drawn. In this case, * the array of weights is initialized to a zero-length array. + * * @exception IllegalArgumentException if any of the specified * geometry array objects differ from each other in any of the * following ways: @@ -187,19 +200,28 @@ public class Morph extends Leaf { * (coord, color, normal, texcoord), * for indexed geometry by-reference</li> * </ul> + * + * @exception UnsupportedOperationException if the specified + * geometry arrays contain vertex attributes (that is, if their + * vertexFormat includes the <code>VERTEX_ATTRIBUTES</code> flag). */ public Morph(GeometryArray geometryArrays[]) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((MorphRetained)retained).setGeometryArrays(geometryArrays); } /** * Constructs and initializes a Morph node with the specified array * of GeometryArray objects and the specified appearance object. + * * @param geometryArrays the geometry components of the Morph node * a null or zero-length array of GeometryArray objects is * permitted, and specifies that no geometry is drawn. In this case, * the array of weights is initialized to a zero-length array. * @param appearance the appearance component of the Morph node + * * @exception IllegalArgumentException if any of the specified * geometry array objects differ from each other in any of the * following ways: @@ -216,9 +238,16 @@ public class Morph extends Leaf { * (coord, color, normal, texcoord), * for indexed geometry by-reference</li> * </ul> + * + * @exception UnsupportedOperationException if the specified + * geometry arrays contain vertex attributes (that is, if their + * vertexFormat includes the <code>VERTEX_ATTRIBUTES</code> flag). */ public Morph(GeometryArray geometryArrays[], Appearance appearance) { - ((MorphRetained)retained).setGeometryArrays(geometryArrays); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((MorphRetained)retained).setGeometryArrays(geometryArrays); ((MorphRetained)this.retained).setAppearance(appearance); } @@ -303,6 +332,10 @@ public class Morph extends Leaf { * (coord, color, normal, texcoord), * for indexed geometry by-reference</li> * </ul> + * + * @exception UnsupportedOperationException if the specified + * geometry arrays contain vertex attributes (that is, if their + * vertexFormat includes the <code>VERTEX_ATTRIBUTES</code> flag). */ public void setGeometryArrays(GeometryArray geometryArrays[]) { @@ -642,7 +675,8 @@ public class Morph extends Leaf { // have the bit set. private void checkForAllowIntersect() { MorphRetained morphR = ((MorphRetained)this.retained); - for (int i = 0; i < morphR.numGeometryArrays; i++) { + int numGeometryArrays = morphR.getNumGeometryArrays(); + for (int i = 0; i < numGeometryArrays; i++) { if (!morphR.geometryArrays[i].source. getCapability(Geometry.ALLOW_INTERSECT)) { diff --git a/src/classes/share/javax/media/j3d/MorphRetained.java b/src/classes/share/javax/media/j3d/MorphRetained.java index 34633f7..351122f 100644 --- a/src/classes/share/javax/media/j3d/MorphRetained.java +++ b/src/classes/share/javax/media/j3d/MorphRetained.java @@ -56,7 +56,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { */ GeometryArrayRetained geometryArrays[]; - int numGeometryArrays = 0; + private int numGeometryArrays = 0; /** * The weight vector the morph node. @@ -200,6 +200,13 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { } doErrorCheck(prevGeo, geo); } + + // Check the first one for vertex attributes + geo = (GeometryArrayRetained)geometryArrays[0].retained; + if ((geo.vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) { + throw new UnsupportedOperationException(J3dI18N.getString("MorphRetained9")); + } + // Check if the first one is in Immediate context if (geometryArrays[0] != null) { geo = (GeometryArrayRetained)geometryArrays[0].retained; @@ -452,8 +459,58 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { boolean getAppearanceOverrideEnable() { return appearanceOverrideEnable; } + + boolean intersect(PickInfo pickInfo, PickShape pickShape, int flags ) { + + Transform3D localToVworld = pickInfo.getLocalToVWorldRef(); + + Transform3D vworldToLocal = new Transform3D(); + vworldToLocal.invert(localToVworld); + PickShape newPS = pickShape.transform(vworldToLocal); + GeometryRetained geo = (GeometryRetained) (morphedGeometryArray.retained); + if (geo.mirrorGeometry != null) { + geo = geo.mirrorGeometry; + } + + if (((flags & PickInfo.CLOSEST_INTERSECTION_POINT) == 0) && + ((flags & PickInfo.CLOSEST_DISTANCE) == 0) && + ((flags & PickInfo.CLOSEST_GEOM_INFO) == 0) && + ((flags & PickInfo.ALL_GEOM_INFO) == 0)) { + return geo.intersect(newPS, null, 0, null); + } else { + Point3d closestIPnt = new Point3d(); + Point3d iPnt = new Point3d(); + Point3d iPntVW = new Point3d(); + PickInfo.IntersectionInfo intersectionInfo + = pickInfo.createIntersectionInfo(); + + if (geo.intersect(newPS, intersectionInfo, flags, iPnt)) { + + iPntVW.set(iPnt); + localToVworld.transform(iPntVW); + double distance = pickShape.distance(iPntVW); + if ((flags & PickInfo.CLOSEST_DISTANCE) != 0) { + pickInfo.setClosestDistance(distance); + } + if((flags & PickInfo.CLOSEST_INTERSECTION_POINT) != 0) { + pickInfo.setClosestIntersectionPoint(iPnt); + } else if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { + intersectionInfo.setGeometry((Geometry) geo.source); + intersectionInfo.setGeometryIndex(0); + intersectionInfo.setIntersectionPoint(iPnt); + intersectionInfo.setDistance(distance); + // VertexIndices has been computed in intersect method. + pickInfo.insertIntersectionInfo(intersectionInfo); + } + return true; + } + } + return false; + } + + /** * Check if the geometry component of this shape node under path * intersects with the pickShape. @@ -461,48 +518,38 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { * contains the closest distance of intersection if it is not * equal to null. */ - boolean intersect(SceneGraphPath path, PickShape pickShape, - double[] dist) { - + boolean intersect(SceneGraphPath path, + PickShape pickShape, double[] dist) { + // This method will not do bound intersect check, as it assume caller // has already done that. ( For performance and code simplification // reasons. ) - Transform3D localToVworld = path.getTransform(); - + int flags; + PickInfo pickInfo = new PickInfo(); + + Transform3D localToVworld = path.getTransform(); if (localToVworld == null) { throw new RuntimeException(J3dI18N.getString("MorphRetained5")); } - Transform3D vworldToLocal = VirtualUniverse.mc.getTransform3D(null); - vworldToLocal.invert(localToVworld); - PickShape newPS = pickShape.transform(vworldToLocal); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, vworldToLocal); - - Point3d iPnt = Shape3DRetained.getPoint3d(); - - GeometryRetained geo = (GeometryRetained) (morphedGeometryArray.retained); - - if (geo.mirrorGeometry != null) { - geo = geo.mirrorGeometry; - } - - boolean isIntersect; - if (dist != null) { - isIntersect = geo.intersect(newPS, dist, iPnt); - if (isIntersect) { - // compute the real distance since the dist return - // above distance may scaled (non-uniform) by transform3d - localToVworld.transform(iPnt); - dist[0] = pickShape.distance(iPnt); - } - } else { - isIntersect = geo.intersect(newPS, null, iPnt); - } - Shape3DRetained.freePoint3d(iPnt); - return isIntersect; - } - + pickInfo.setLocalToVWorldRef( localToVworld); + //System.out.println("MorphRetained.intersect() : "); + if (dist == null) { + //System.out.println(" no dist request ...."); + return intersect(pickInfo, pickShape, 0); + } + + flags = PickInfo.CLOSEST_DISTANCE; + if (intersect(pickInfo, pickShape, flags)) { + dist[0] = pickInfo.getClosestDistance(); + return true; + } + + return false; + + } + /** * Sets the Morph node's weight vector * @param wieghts the new vector of weights for the morph node @@ -571,8 +618,8 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { } else { return super.getBounds(); } - } - + } + Bounds getEffectiveBounds() { if(boundsAutoCompute) { return getBounds(); @@ -604,6 +651,11 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { } } + // Return the number of geometry arrays in this MorphRetained object. + int getNumGeometryArrays() { + return numGeometryArrays; + } + // If the geometry of a morph changes, make sure that the // validVertexCount has not changed void updateMorphedGeometryArray(GeometryArrayRetained geo, boolean coordinatesChanged) { @@ -1767,8 +1819,8 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { } if ((vFormat & GeometryArray.TEXTURE_COORDINATE) != 0) { for (k = 0; k < texCoordSetCount; k++) { - morphedGeo.setTextureCoordinateIndices(k, 0, - (int[]) igeo.indexTexCoord[k]); + morphedGeo.setTextureCoordinateIndices(k, 0, + igeo.indexTexCoord[k]); } } } @@ -1797,7 +1849,7 @@ class MorphRetained extends LeafRetained implements GeometryUpdater { super.compile(compState); - // TODO: for now keep the static transform in the parent tg + // XXXX: for now keep the static transform in the parent tg compState.keepTG = true; if (J3dDebug.devPhase && J3dDebug.debug) { diff --git a/src/classes/share/javax/media/j3d/Node.java b/src/classes/share/javax/media/j3d/Node.java index 9be9ab3..3853a63 100644 --- a/src/classes/share/javax/media/j3d/Node.java +++ b/src/classes/share/javax/media/j3d/Node.java @@ -109,7 +109,34 @@ public abstract class Node extends SceneGraphObject { */ public static final int ALLOW_LOCAL_TO_VWORLD_READ = CapabilityBits.NODE_ALLOW_LOCAL_TO_VWORLD_READ; - + + /** + * Specifies that this Node allows read access to its parent Group node. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_PARENT_READ = CapabilityBits.NODE_ALLOW_PARENT_READ; + + /** + * Specifies that this Node allows read access to its Locale. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_LOCALE_READ = CapabilityBits.NODE_ALLOW_LOCALE_READ; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_BOUNDS_READ, + ALLOW_PICKABLE_READ, + ALLOW_COLLIDABLE_READ, + ALLOW_AUTO_COMPUTE_BOUNDS_READ, + ALLOW_LOCAL_TO_VWORLD_READ, + ALLOW_PARENT_READ, + ALLOW_LOCALE_READ + }; + // for checking for cycles private boolean visited = false; @@ -125,18 +152,22 @@ public abstract class Node extends SceneGraphObject { * </ul> */ public Node() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** - * Retrieves the parent of this Node. This method is only valid - * during the construction of the scene graph. + * @return the parent of this node, or null if this node has no parent - * @exception RestrictedAccessException if this object is part of live - * or compiled scene graph + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph */ public Node getParent() { - if (isLiveOrCompiled()) - throw new RestrictedAccessException(J3dI18N.getString("Node0")); + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_PARENT_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("Node0")); + } + } NodeRetained nr = ((NodeRetained)this.retained).getParent(); return (nr == null ? null : (Node) nr.getSource()); @@ -245,24 +276,36 @@ public abstract class Node extends SceneGraphObject { * of all transforms in the scene graph from the root down to * <code>this</code> node. It is only valid * for nodes that are part of a live scene graph. + * If the node is not part of a live scene graph then the coordinates are + * calculated as if the graph was attached at the origin of a locale. * @param t the object that will receive the local coordinates to * Vworld coordinates transform. - * @exception RestrictedAccessException if the node is <em>not</em> + * @exception RestrictedAccessException if the node is compiled but not * part of a live scene graph * @exception CapabilityNotSetException if appropriate capability is - * not set and this node is part of live scene graph + * not set and this node is part of live or compiled scene graph * @exception IllegalSharingException if the node is a descendant * of a SharedGroup node. */ public void getLocalToVworld(Transform3D t) { - if (!isLive()) - throw new RestrictedAccessException(J3dI18N.getString("Node7")); - - if(!this.getCapability(ALLOW_LOCAL_TO_VWORLD_READ)) - throw new CapabilityNotSetException(J3dI18N.getString("Node8")); - - ((NodeRetained)this.retained).getLocalToVworld(t); + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_LOCAL_TO_VWORLD_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("Node8")); + } + + if (!isLive()) { + // TODO Support compiled graphs + if (isCompiled()) + throw new RestrictedAccessException(J3dI18N.getString("Node7")); + + // In 1.4 we support getLocalToVworld for non live nodes + ((NodeRetained)this.retained).computeNonLiveLocalToVworld(t, this); + //throw new RestrictedAccessException(J3dI18N.getString("Node7")); + } else { + ((NodeRetained)this.retained).getLocalToVworld(t); + } } + /** * Retrieves the local coordinates to virtual world coordinates @@ -281,15 +324,44 @@ public abstract class Node extends SceneGraphObject { * @exception IllegalArgumentException if the specified path does * not contain a valid Locale, or if the last node in the path is * different from this node + * @exception IllegalSharingException if the node is not a descendant + * of a SharedGroup node. */ public void getLocalToVworld(SceneGraphPath path, Transform3D t) { - if (!isLive()) + if (!isLive()) { throw new RestrictedAccessException(J3dI18N.getString("Node7")); - - if(!this.getCapability(ALLOW_LOCAL_TO_VWORLD_READ)) - throw new CapabilityNotSetException(J3dI18N.getString("Node8")); + } + + if(!this.getCapability(ALLOW_LOCAL_TO_VWORLD_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("Node8")); ((NodeRetained)this.retained).getLocalToVworld(path,t); + + } + + /** + * Retrieves the locale to which this node is attached. If the + * node is not part of a live scene graph, null is returned. + * + * @return the locale to which this node is attached. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this node is part of live scene graph + * @exception IllegalSharingException if the node is a descendant + * of a SharedGroup node. + * + * @since Java 3D 1.4 + */ + public Locale getLocale() { + if (!isLive()) { + return null; + } + + if(!this.getCapability(ALLOW_LOCALE_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("Node17")); + } + + return ((NodeRetained)this.retained).getLocale(); } /** diff --git a/src/classes/share/javax/media/j3d/NodeData.java b/src/classes/share/javax/media/j3d/NodeData.java index 90505e2..5c927c6 100644 --- a/src/classes/share/javax/media/j3d/NodeData.java +++ b/src/classes/share/javax/media/j3d/NodeData.java @@ -15,7 +15,7 @@ package javax.media.j3d; class NodeData { // per path node data - // TODO: replace per path mirror objects with node data - // TODO: move other basic node's data here + // XXXX: replace per path mirror objects with node data + // XXXX: move other basic node's data here SwitchState switchState = null; } diff --git a/src/classes/share/javax/media/j3d/NodeRetained.java b/src/classes/share/javax/media/j3d/NodeRetained.java index de91ce4..a8d9467 100644 --- a/src/classes/share/javax/media/j3d/NodeRetained.java +++ b/src/classes/share/javax/media/j3d/NodeRetained.java @@ -374,7 +374,26 @@ abstract class NodeRetained extends SceneGraphObjectRetained implements NnuId { return; } - + /** + * Compute the LocalToVworld of this node even though it is not live. We + * assume the graph is attached at the origin of a locale + */ + void computeNonLiveLocalToVworld(Transform3D t, Node caller) { + NodeRetained n = getParent(); + + if (n==null) + t.setIdentity(); + else + n.computeNonLiveLocalToVworld(t, caller); + + if (this instanceof TransformGroupRetained && this.source!=caller) { + Transform3D trans = new Transform3D(); + ((TransformGroupRetained)this).getTransform(trans); + t.mul(trans); + } + + } + /** * Get the localToVworld transform for a node. */ @@ -413,7 +432,19 @@ abstract class NodeRetained extends SceneGraphObjectRetained implements NnuId { HashKey newKey = new HashKey(key); computeLocalToVworld(this, this, newKey, t); } - + + + /** + * Get the Locale to which the node is attached + */ + Locale getLocale() { + if (inSharedGroup) { + throw new IllegalSharingException(J3dI18N.getString("NodeRetained0")); + } + + return locale; + } + /** * Get the current localToVworld transform for a node @@ -868,6 +899,7 @@ abstract class NodeRetained extends SceneGraphObjectRetained implements NnuId { boolean isStatic() { if (source.getCapability(Node.ALLOW_LOCAL_TO_VWORLD_READ) || + source.getCapability(Node.ALLOW_PARENT_READ) || source.getCapability(Node.ENABLE_PICK_REPORTING) || source.getCapability(Node.ENABLE_COLLISION_REPORTING) || source.getCapability(Node.ALLOW_BOUNDS_READ) || diff --git a/src/classes/share/javax/media/j3d/NotificationThread.java b/src/classes/share/javax/media/j3d/NotificationThread.java new file mode 100644 index 0000000..1d7a44f --- /dev/null +++ b/src/classes/share/javax/media/j3d/NotificationThread.java @@ -0,0 +1,120 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.LinkedList; + +/** + * The NotificationThread class is used for asynchronous error notification, + * such as notifying ShaderError listeners. + */ +class NotificationThread extends Thread { + // action flag for runMonitor + private static final int WAIT = 0; + private static final int NOTIFY = 1; + private static final int STOP = 2; + + private volatile boolean running = true; + private boolean waiting = false; + private boolean ready = false; + + private LinkedList notificationQueue = new LinkedList(); + + /** + * Creates a new instance of NotificationThread + */ + NotificationThread(ThreadGroup t) { + // Only one notification thread for the entire system + super(t, "J3D-NotificationThread"); + } + + /** + * Adds a notification message to the queue + */ + synchronized void addNotification(J3dNotification n) { + notificationQueue.add(n); + runMonitor(NOTIFY); + } + + /** + * Gets the list of queued notification messages + */ + private synchronized J3dNotification[] getNotifications() { + J3dNotification[] notifications = (J3dNotification[])notificationQueue.toArray(new J3dNotification[0]); + notificationQueue.clear(); + return notifications; + } + + /** + * Processes all pending notification messages + */ + private void processNotifications() { + J3dNotification[] notifications = getNotifications(); + + for (int i = 0; i < notifications.length; i++) { + J3dNotification n = notifications[i]; + switch (n.type) { + case J3dNotification.SHADER_ERROR: + n.universe.notifyShaderErrorListeners((ShaderError)n.args[0]); + break; + default: + System.err.println("J3dNotification.processNotifications: unrecognized type = " + n.type); + } + } + } + + // Called from MasterControlThread + void finish() { + runMonitor(STOP); + } + + public void run() { + while (running) { + runMonitor(WAIT); + + processNotifications(); + } +// System.err.println("Notification thread finished"); + } + + + private synchronized void runMonitor(int action) { + switch (action) { + case WAIT: + while (running && !ready) { + waiting = true; + try { + wait(); + } catch (InterruptedException e) { + } + waiting = false; + } + ready = false; + break; + case NOTIFY: + ready = true; + if (waiting) { + notify(); + } + break; + case STOP: + running = false; + notify(); + break; + default: + // Should never get here... + assert(false); + } + } + +} diff --git a/src/classes/share/javax/media/j3d/OrderedGroup.java b/src/classes/share/javax/media/j3d/OrderedGroup.java index e3d4e87..1ffdd93 100644 --- a/src/classes/share/javax/media/j3d/OrderedGroup.java +++ b/src/classes/share/javax/media/j3d/OrderedGroup.java @@ -72,6 +72,10 @@ public class OrderedGroup extends Group { public static final int ALLOW_CHILD_INDEX_ORDER_WRITE = CapabilityBits.ORDERED_GROUP_ALLOW_CHILD_INDEX_ORDER_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_CHILD_INDEX_ORDER_READ + }; /** * Constructs and initializes a new OrderedGroup node object. @@ -79,6 +83,8 @@ public class OrderedGroup extends Group { * that its children are rendered in increasing index order. */ public OrderedGroup() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } diff --git a/src/classes/share/javax/media/j3d/OrientedShape3D.java b/src/classes/share/javax/media/j3d/OrientedShape3D.java index bea85dd..478eb71 100644 --- a/src/classes/share/javax/media/j3d/OrientedShape3D.java +++ b/src/classes/share/javax/media/j3d/OrientedShape3D.java @@ -144,6 +144,14 @@ public class OrientedShape3D extends Shape3D { CapabilityBits.ORIENTED_SHAPE3D_ALLOW_SCALE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_MODE_READ, + ALLOW_AXIS_READ, + ALLOW_POINT_READ, + ALLOW_SCALE_READ + }; + /** * Constructs an OrientedShape3D node with default parameters. * The default values are as follows: @@ -157,6 +165,8 @@ public class OrientedShape3D extends Shape3D { */ public OrientedShape3D() { super(); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } @@ -182,6 +192,10 @@ public class OrientedShape3D extends Shape3D { Vector3f axis) { super(geometry, appearance); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((OrientedShape3DRetained)retained).initAlignmentMode(mode); ((OrientedShape3DRetained)retained).initAlignmentAxis(axis); } @@ -203,6 +217,10 @@ public class OrientedShape3D extends Shape3D { Point3f point) { super(geometry, appearance); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((OrientedShape3DRetained)retained).initAlignmentMode(mode); ((OrientedShape3DRetained)retained).initRotationPoint(point); @@ -240,6 +258,9 @@ public class OrientedShape3D extends Shape3D { super(geometry, appearance); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((OrientedShape3DRetained)retained).initAlignmentMode(mode); ((OrientedShape3DRetained)retained).initAlignmentAxis(axis); ((OrientedShape3DRetained)retained). @@ -272,6 +293,9 @@ public class OrientedShape3D extends Shape3D { super(geometry, appearance); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((OrientedShape3DRetained)retained).initAlignmentMode(mode); ((OrientedShape3DRetained)retained).initRotationPoint(point); ((OrientedShape3DRetained)retained). diff --git a/src/classes/share/javax/media/j3d/PhysicalBody.java b/src/classes/share/javax/media/j3d/PhysicalBody.java index 442e44f..40de532 100644 --- a/src/classes/share/javax/media/j3d/PhysicalBody.java +++ b/src/classes/share/javax/media/j3d/PhysicalBody.java @@ -128,7 +128,7 @@ public class PhysicalBody extends Object { synchronized void notifyUsers() { for (int i=users.size()-1; i>=0; i--) { View view = (View)users.get(i); - // TODO: notifyUsers should have a parameter denoting field changed + // XXXX: notifyUsers should have a parameter denoting field changed if (view.soundScheduler != null) { view.soundScheduler.setListenerFlag( SoundScheduler.EAR_POSITIONS_CHANGED | diff --git a/src/classes/share/javax/media/j3d/PickConeRay.java b/src/classes/share/javax/media/j3d/PickConeRay.java index ebc2d6a..7821e1e 100644 --- a/src/classes/share/javax/media/j3d/PickConeRay.java +++ b/src/classes/share/javax/media/j3d/PickConeRay.java @@ -204,7 +204,7 @@ public final class PickConeRay extends PickCone { double distToEdge; for (i=0;i<ptope.nVerts;i++) { for (j=i;i<ptope.nVerts;i++) { - // TODO: make BoundingPolytope.pointInPolytope available to package + // XXXX: make BoundingPolytope.pointInPolytope available to package // scope midpt.x = (ptope.verts[i].x + ptope.verts[j].x) * 0.5; midpt.y = (ptope.verts[i].y + ptope.verts[j].y) * 0.5; diff --git a/src/classes/share/javax/media/j3d/PickConeSegment.java b/src/classes/share/javax/media/j3d/PickConeSegment.java index fe2c45b..11adb80 100644 --- a/src/classes/share/javax/media/j3d/PickConeSegment.java +++ b/src/classes/share/javax/media/j3d/PickConeSegment.java @@ -233,7 +233,7 @@ public final class PickConeSegment extends PickCone { double distToEdge; for (i=0;i<ptope.nVerts;i++) { for (j=i;i<ptope.nVerts;i++) { - // TODO: make BoundingPolytope.pointInPolytope available to package + // XXXX: make BoundingPolytope.pointInPolytope available to package // scope midpt.x = (ptope.verts[i].x + ptope.verts[j].x) * 0.5; midpt.y = (ptope.verts[i].y + ptope.verts[j].y) * 0.5; diff --git a/src/classes/share/javax/media/j3d/PickCylinder.java b/src/classes/share/javax/media/j3d/PickCylinder.java index 9d805eb..1a624f9 100644 --- a/src/classes/share/javax/media/j3d/PickCylinder.java +++ b/src/classes/share/javax/media/j3d/PickCylinder.java @@ -71,7 +71,7 @@ public abstract class PickCylinder extends PickShape { // This is a duplicate of the same method, declared private inside of // BoundingPolytope - // TODO: remove this once the original method is available (public) in + // XXXX: remove this once the original method is available (public) in // BoundingPolytope static boolean pointInPolytope(BoundingPolytope ptope, double x, double y, double z ){ diff --git a/src/classes/share/javax/media/j3d/PickCylinderRay.java b/src/classes/share/javax/media/j3d/PickCylinderRay.java index 2fb33b1..6b5266f 100644 --- a/src/classes/share/javax/media/j3d/PickCylinderRay.java +++ b/src/classes/share/javax/media/j3d/PickCylinderRay.java @@ -185,7 +185,7 @@ public final class PickCylinderRay extends PickCylinder { double distToEdge; for (i=0;i<ptope.nVerts;i++) { for (j=i;i<ptope.nVerts;i++) { - // TODO: make BoundingPolytope.pointInPolytope available to package + // XXXX: make BoundingPolytope.pointInPolytope available to package // scope midpt.x = (ptope.verts[i].x + ptope.verts[j].x) * 0.5; midpt.y = (ptope.verts[i].y + ptope.verts[j].y) * 0.5; diff --git a/src/classes/share/javax/media/j3d/PickCylinderSegment.java b/src/classes/share/javax/media/j3d/PickCylinderSegment.java index 37bb1a7..6f03cd0 100644 --- a/src/classes/share/javax/media/j3d/PickCylinderSegment.java +++ b/src/classes/share/javax/media/j3d/PickCylinderSegment.java @@ -205,7 +205,7 @@ public final class PickCylinderSegment extends PickCylinder { double distToEdge; for (i=0;i<ptope.nVerts;i++) { for (j=i;i<ptope.nVerts;i++) { - // TODO: make BoundingPolytope.pointInPolytope available to package + // XXXX: make BoundingPolytope.pointInPolytope available to package // scope midpt.x = (ptope.verts[i].x + ptope.verts[j].x) * 0.5; midpt.y = (ptope.verts[i].y + ptope.verts[j].y) * 0.5; diff --git a/src/classes/share/javax/media/j3d/PickInfo.java b/src/classes/share/javax/media/j3d/PickInfo.java new file mode 100644 index 0000000..64a6392 --- /dev/null +++ b/src/classes/share/javax/media/j3d/PickInfo.java @@ -0,0 +1,1056 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; +import java.util.*; + +/** + * The PickInfo object contains the computed information about a pick hit. + * The detailed information about each intersection of the PickShape + * with the picked Node can be inquired. The PickInfo object is constructed with + * basic information and more detailed information can be generated by setting the + * appropriate mask to the flag argument in the pick methods of BranchGroup and + * Locale. + * <p> + * + * @see Locale + * @see BranchGroup + * + * @since Java 3D 1.4 + */ + + +public class PickInfo extends Object { + + static final int PICK_ALL = 1; + + static final int PICK_ANY = 2; + + /* The SceneGraphPath of the intersected pickable item */ + private SceneGraphPath sgp; + + /* The intersected pickable node object */ + private Node node; + + /* A copy of LocalToVworld transform of the pickable node */ + private Transform3D l2vw; + + /* The closest intersection point */ + private Point3d closestIntersectionPoint; + + /* Distance between start point of pickShape and closest intersection point */ + private double closestDistance; + + /* An array to store intersection results */ + private IntersectionInfo[] intersectionInfoArr; + + /* The following references are for internal geometry computation use only */ + private ArrayList intersectionInfoList = new ArrayList(); + private boolean intersectionInfoListSorted = false; + private Transform3D l2vwRef; + private Node nodeRef; + + /** + * Specifies a Pick using the bounds of the pickable nodes. + */ + public static final int PICK_BOUNDS = 1; + + /** + * Specifies a Pick using the geometry of the pickable nodes. + */ + public static final int PICK_GEOMETRY = 2; + + /** + * Specifies that this PickInfo returns the computed SceneGraphPath object. + */ + public static final int SCENEGRAPHPATH = 0x01; + + /** + * Specifies that this PickInfo returns the computed intersected Node object. + */ + public static final int NODE = 0x02; + + /** + * Specifies that this PickInfo returns the computed local to vworld transform. + */ + public static final int LOCAL_TO_VWORLD = 0x04; + + /** + * Specifies that this PickInfo returns the closest intersection point. + */ + public static final int CLOSEST_INTERSECTION_POINT = 0x08; + + /** + * Specifies that this PickInfo returns the closest intersection distance. + */ + public static final int CLOSEST_DISTANCE = 0x10; + + /** + * Specifies that this PickInfo returns only the closest intersection + * geometry information. + */ + public static final int CLOSEST_GEOM_INFO = 0x20; + + /** + * Specifies that this PickInfo returns all the closest intersection + * geometry informations. + */ + public static final int ALL_GEOM_INFO = 0x40; + + + /** PickInfo Constructor */ + PickInfo() { + + } + + void setSceneGraphPath(SceneGraphPath sgp) { + this.sgp = sgp; + } + + void setNode(Node node) { + this.node = node; + } + + void setLocalToVWorld(Transform3D l2vw) { + this.l2vw = l2vw; + } + + void setClosestIntersectionPoint(Point3d cIPt) { + this.closestIntersectionPoint = cIPt; + } + + void setClosestDistance(double cDist) { + this.closestDistance = cDist; + } + + void setLocalToVWorldRef(Transform3D l2vwRef) { + this.l2vwRef = l2vwRef; + } + + void setNodeRef(Node nodeRef) { + this.nodeRef = nodeRef; + } + + IntersectionInfo createIntersectionInfo() { + return new IntersectionInfo(); + } + + void insertIntersectionInfo(IntersectionInfo iInfo) { + intersectionInfoList.add(iInfo); + intersectionInfoListSorted = false; + } + + void sortIntersectionInfoArray(IntersectionInfo[] iInfoArr) { + + class Sort { + + IntersectionInfo iInfoArr[]; + + Sort(IntersectionInfo[] iInfoArr) { + // System.out.println("Sort IntersectionInfo ..."); + this.iInfoArr = iInfoArr; + } + + void sorting() { + if (iInfoArr.length < 7) { + // System.out.println(" -- insertSort."); + insertSort(); + } else { + // System.out.println(" -- quicksort."); + quicksort(0, iInfoArr.length-1); + } + } + + // Insertion sort on smallest arrays + final void insertSort() { + for (int i=0; i<iInfoArr.length; i++) { + for (int j=i; j>0 && + (iInfoArr[j-1].distance > iInfoArr[j].distance); j--) { + IntersectionInfo iInfo = iInfoArr[j]; + iInfoArr[j] = iInfoArr[j-1]; + iInfoArr[j-1] = iInfo; + } + } + } + + final void quicksort( int l, int r ) { + int i = l; + int j = r; + double k = iInfoArr[(l+r) / 2].distance; + + do { + while (iInfoArr[i].distance<k) i++; + while (k<iInfoArr[j].distance) j--; + if (i<=j) { + IntersectionInfo iInfo = iInfoArr[i]; + iInfoArr[i] = iInfoArr[j]; + iInfoArr[j] = iInfo; + i++; + j--; + } + } while (i<=j); + + if (l<j) quicksort(l,j); + if (l<r) quicksort(i,r); + } + } + + (new Sort(iInfoArr)).sorting(); + intersectionInfoListSorted = true; + } + + static void sortPickInfoArray(PickInfo[] pickInfoArr) { + + class Sort { + + PickInfo pIArr[]; + + Sort(PickInfo[] pIArr) { + // System.out.println("Sort PickInfo ..."); + this.pIArr = pIArr; + } + + void sorting() { + if (pIArr.length < 7) { + // System.out.println(" -- insertSort."); + insertSort(); + } else { + // System.out.println(" -- quicksort."); + quicksort(0, pIArr.length-1); + } + } + + // Insertion sort on smallest arrays + final void insertSort() { + for (int i=0; i<pIArr.length; i++) { + for (int j=i; j>0 && + (pIArr[j-1].closestDistance > pIArr[j].closestDistance); j--) { + PickInfo pI = pIArr[j]; + pIArr[j] = pIArr[j-1]; + pIArr[j-1] = pI; + } + } + } + + final void quicksort( int l, int r ) { + int i = l; + int j = r; + double k = pIArr[(l+r) / 2].closestDistance; + + do { + while (pIArr[i].closestDistance<k) i++; + while (k<pIArr[j].closestDistance) j--; + if (i<=j) { + PickInfo pI = pIArr[i]; + pIArr[i] = pIArr[j]; + pIArr[j] = pI; + i++; + j--; + } + } while (i<=j); + + if (l<j) quicksort(l,j); + if (l<r) quicksort(i,r); + } + } + + (new Sort(pickInfoArr)).sorting(); + + } + + + /** + * Retrieves the reference to the SceneGraphPath in this PickInfo object. + * @return the SceneGraphPath object, or null if flag is not set with SCENEGRAPHPATH. + * @see Locale + * @see BranchGroup + */ + public SceneGraphPath getSceneGraphPath() { + return sgp; + } + + /** + * Retrieves the reference to the picked node, either a Shape3D or a Morph, in this PickInfo object. + * @return the picked leaf node object, or null if flag is not set with NODE. + * @see Locale + * @see BranchGroup + */ + public Node getNode() { + return node; + } + + /** + * Retrieves the reference to the LocalToVworld transform of the picked node in this PickInfo object. + * @return the local to vworld transform, or null if flag is not set with LOCAL_TO_VWORLD. + * @see Locale + * @see BranchGroup + */ + public Transform3D getLocalToVWorld() { + return l2vw; + } + + /** + * Retrieves the reference to the closest intersection point in this PickInfo object. + * @return the closest intersection point, or null if flag is not set with CLOSEST_INTERSECTION_POINT. + * @see Locale + * @see BranchGroup + */ + public Point3d getClosestIntersectionPoint() { + return closestIntersectionPoint; + } + + /** + * Retrieves the distance between the start point of the pickShape and the closest intersection point. + * @return the closest distance in double, or NaN if flag is not set with CLOSEST_INTERSECTION_POINT. + * Note : If this PickInfo object is returned by either pickClosest or pickAllSorted method, the return + * value is the closest distance in double even if flag is not set with CLOSET_INTERSECTION_POINT. + * @see Locale + * @see BranchGroup + */ + public double getClosestDistance() { + return closestDistance; + } + + Transform3D getLocalToVWorldRef() { + return l2vwRef; + } + + Node getNodeRef() { + return nodeRef; + } + + /** + * Retrieves the reference to the array of intersection results in this PickInfo object. + * @return an array of 1 IntersectionInfo object if flag is to set CLOSEST_GEOM_INFO, + * or an array of <i>N</i> IntersectionInfo objects containing all intersections of + * the picked node in sorted order if flag is to set ALL_GEOM_INFO, or null if neither + * bit is set. + * @see Locale + * @see BranchGroup + */ + public IntersectionInfo[] getIntersectionInfos() { + if (intersectionInfoListSorted == false) { + intersectionInfoArr = new IntersectionInfo[intersectionInfoList.size()]; + intersectionInfoArr = + (IntersectionInfo []) intersectionInfoList.toArray(intersectionInfoArr); + + sortIntersectionInfoArray(intersectionInfoArr); + } + + return intersectionInfoArr; + } + + /** + * Search the path from nodeR up to Locale. + * Return the search path as ArrayList if found. + * Note that the locale will not insert into path. + */ + static ArrayList initSceneGraphPath(NodeRetained nodeR) { + ArrayList path = new ArrayList(5); + + do { + if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)){ + path.add(nodeR); + } + nodeR = nodeR.parent; + } while (nodeR != null); // reach Locale + + return path; + } + + static private Node[] createPath(NodeRetained srcNode, + BranchGroupRetained bgRetained, + GeometryAtom geomAtom, + ArrayList initpath) { + + ArrayList path = retrievePath(srcNode, bgRetained, + geomAtom.source.key); + assert(path != null); + + return mergePath(path, initpath); + + } + + + /** + * Return true if bg is inside cachedBG or bg is null + */ + static private boolean inside(BranchGroupRetained bgArr[], + BranchGroupRetained bg) { + + if ((bg == null) || (bgArr == null)) { + return true; + } + + for (int i=0; i < bgArr.length; i++) { + if (bgArr[i] == bg) { + return true; + } + } + return false; + } + + /** + * search the full path from the bottom of the scene graph - + * startNode, up to the Locale if endNode is null. + * If endNode is not null, the path is found up to, but not + * including, endNode or return null if endNode not hit + * during the search. + */ + static private ArrayList retrievePath(NodeRetained startNode, + NodeRetained endNode, + HashKey key) { + + ArrayList path = new ArrayList(5); + NodeRetained nodeR = startNode; + + if (nodeR.inSharedGroup) { + // getlastNodeId() will destroy this key + key = new HashKey(key); + } + + do { + if (nodeR == endNode) { // we found it ! + return path; + } + + if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)) { + path.add(nodeR); + } + + if (nodeR instanceof SharedGroupRetained) { + // retrieve the last node ID + String nodeId = key.getLastNodeId(); + Vector parents = ((SharedGroupRetained) nodeR).parents; + int sz = parents.size(); + NodeRetained prevNodeR = nodeR; + for(int i=0; i< sz; i++) { + NodeRetained linkR = (NodeRetained) parents.elementAt(i); + if (linkR.nodeId.equals(nodeId)) { + nodeR = linkR; + // Need to add Link to the path report + path.add(nodeR); + // since !(endNode instanceof Link), we + // can skip the check (nodeR == endNode) and + // proceed to parent of link below + break; + } + } + if (nodeR == prevNodeR) { + // branch is already detach + return null; + } + } + nodeR = nodeR.parent; + } while (nodeR != null); // reach Locale + + if (endNode == null) { + // user call pickxxx(Locale locale, PickShape shape) + return path; + } + + // user call pickxxx(BranchGroup endNode, PickShape shape) + // if locale is reached and endNode not hit, this is not + // the path user want to select + return null; + } + + /** + * copy p1, (follow by) p2 into a new array, p2 can be null + * The path is then reverse before return. + */ + static private Node[] mergePath(ArrayList p1, ArrayList p2) { + int s = p1.size(); + int len; + int i; + int l; + if (p2 == null) { + len = s; + } else { + len = s + p2.size(); + } + + Node nodes[] = new Node[len]; + l = len-1; + for (i=0; i < s; i++) { + nodes[l-i] = (Node) ((NodeRetained) p1.get(i)).source; + } + for (int j=0; i< len; i++, j++) { + nodes[l-i] = (Node) ((NodeRetained) p2.get(j)).source; + } + return nodes; + } + + /** + * Sort the GeometryAtoms distance from shape in ascending order + * geomAtoms.length must be >= 1 + */ + static void sortGeomAtoms(GeometryAtom geomAtoms[], + PickShape shape) { + + final double distance[] = new double[geomAtoms.length]; + Point4d pickPos = new Point4d(); + + for (int i=0; i < geomAtoms.length; i++) { + shape.intersect(geomAtoms[i].source.vwcBounds, pickPos); + distance[i] = pickPos.w; + } + + class Sort { + + GeometryAtom atoms[]; + + Sort(GeometryAtom[] atoms) { + this.atoms = atoms; + } + + void sorting() { + if (atoms.length < 7) { + insertSort(); + } else { + quicksort(0, atoms.length-1); + } + } + + // Insertion sort on smallest arrays + final void insertSort() { + for (int i=0; i<atoms.length; i++) { + for (int j=i; j>0 && + (distance[j-1] > distance[j]); j--) { + double t = distance[j]; + distance[j] = distance[j-1]; + distance[j-1] = t; + GeometryAtom p = atoms[j]; + atoms[j] = atoms[j-1]; + atoms[j-1] = p; + } + } + } + + final void quicksort( int l, int r ) { + int i = l; + int j = r; + double k = distance[(l+r) / 2]; + + do { + while (distance[i]<k) i++; + while (k<distance[j]) j--; + if (i<=j) { + double tmp = distance[i]; + distance[i] =distance[j]; + distance[j] = tmp; + + GeometryAtom p=atoms[i]; + atoms[i]=atoms[j]; + atoms[j]=p; + i++; + j--; + } + } while (i<=j); + + if (l<j) quicksort(l,j); + if (l<r) quicksort(i,r); + } + } + + (new Sort(geomAtoms)).sorting(); + } + + + /** + * return all PickInfo[] of the geomAtoms. + * If initpath is null, the path is search from + * geomAtom Shape3D/Morph Node up to Locale + * (assume the same locale). + * Otherwise, the path is search up to node or + * null is return if it is not hit. + */ + static ArrayList getPickInfos(ArrayList initpath, + BranchGroupRetained bgRetained, + GeometryAtom geomAtoms[], + Locale locale, int flags, int pickType) { + + ArrayList pickInfoList = new ArrayList(5); + NodeRetained srcNode; + ArrayList text3dList = null; + + if ((geomAtoms == null) || (geomAtoms.length == 0)) { + return null; + } + + for (int i=0; i < geomAtoms.length; i++) { + assert((geomAtoms[i] != null) && + (geomAtoms[i].source != null)); + + PickInfo pickInfo = null; + Shape3DRetained shape = geomAtoms[i].source; + srcNode = shape.sourceNode; + + if (srcNode == null) { + // The node is just detach from branch so sourceNode = null + continue; + } + + // Special case, for Text3DRetained, it is possible + // for different geomAtoms pointing to the same + // source Text3DRetained. So we need to combine + // those cases and report only once. + if (srcNode instanceof Shape3DRetained) { + Shape3DRetained s3dR = (Shape3DRetained) srcNode; + GeometryRetained geomR = null; + for(int cnt=0; cnt<s3dR.geometryList.size(); cnt++) { + geomR = (GeometryRetained) s3dR.geometryList.get(cnt); + if(geomR != null) + break; + } + + if (geomR == null) + continue; + + if (geomR instanceof Text3DRetained) { + // assume this case is not frequent, we allocate + // ArrayList only when necessary and we use ArrayList + // instead of HashMap since the case of when large + // number of distingish Text3DRetained node hit is + // rare. + if (text3dList == null) { + text3dList = new ArrayList(3); + } else { + int size = text3dList.size(); + boolean found = false; + for (int j=0; j < size; j++) { + if (text3dList.get(j) == srcNode) { + found = true; + break; + } + } + if (found) { + continue; // try next geomAtom + } + } + text3dList.add(srcNode); + } + } + + // If srcNode is instance of compile retained, then loop thru + // the entire source list and add it to the scene graph path + if (srcNode instanceof Shape3DCompileRetained) { + + Shape3DCompileRetained s3dCR = (Shape3DCompileRetained)srcNode; + + Node[] mpath = null; + boolean first = true; + + for (int n = 0; n < s3dCR.srcList.length; n++) { + + pickInfo = null; + + // PickInfo.SCENEGRAPHPATH - request for computed SceneGraphPath. + if (((flags & SCENEGRAPHPATH) != 0) && + (inside(shape.branchGroupPath,bgRetained))){ + + if(first) { + mpath = createPath(srcNode, bgRetained, geomAtoms[i], initpath); + first = false; + } + + if(mpath != null) { + SceneGraphPath sgpath = new SceneGraphPath(locale, + mpath, (Node) s3dCR.srcList[n]); + sgpath.setTransform(shape.getCurrentLocalToVworld(0)); + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setSceneGraphPath(sgpath); + } + } + + // PickInfo.NODE - request for computed intersected Node. + if ((flags & NODE) != 0) { + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setNode((Node) s3dCR.srcList[n]); + } + + // PickInfo.LOCAL_TO_VWORLD + // - request for computed local to virtual world transform. + if ((flags & LOCAL_TO_VWORLD) != 0) { + Transform3D l2vw = geomAtoms[i].source.getCurrentLocalToVworld(); + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setLocalToVWorld( new Transform3D(l2vw)); + } + + // NOTE : Piggy bag for geometry computation by caller. + if (((flags & CLOSEST_DISTANCE) != 0) || + ((flags & CLOSEST_GEOM_INFO) != 0) || + ((flags & CLOSEST_INTERSECTION_POINT) != 0) || + ((flags & ALL_GEOM_INFO) != 0)) { + + pickInfo.setNodeRef((Node) s3dCR.srcList[n]); + Transform3D l2vw = geomAtoms[i].source.getCurrentLocalToVworld(); + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setLocalToVWorldRef(l2vw); + } + + if(pickInfo != null) + pickInfoList.add(pickInfo); + if(pickType == PICK_ANY) { + return pickInfoList; + } + } + } + else { + Node[] mpath = null; + + // PickInfo.SCENEGRAPHPATH - request for computed SceneGraphPath. + if (((flags & SCENEGRAPHPATH) != 0) && + (inside(shape.branchGroupPath,bgRetained))) { + + mpath = createPath(srcNode, bgRetained, geomAtoms[i], initpath); + + if(mpath != null) { + SceneGraphPath sgpath = new SceneGraphPath(locale, mpath, + (Node) srcNode.source); + sgpath.setTransform(shape.getCurrentLocalToVworld(0)); + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setSceneGraphPath(sgpath); + } + } + + // PickInfo.NODE - request for computed intersected Node. + if ((flags & NODE) != 0) { + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setNode((Node) srcNode.source); + } + + // PickInfo.LOCAL_TO_VWORLD + // - request for computed local to virtual world transform. + if ((flags & LOCAL_TO_VWORLD) != 0) { + Transform3D l2vw = geomAtoms[i].source.getCurrentLocalToVworld(); + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setLocalToVWorld( new Transform3D(l2vw)); + } + + // NOTE : Piggy bag for geometry computation by caller. + if (((flags & CLOSEST_DISTANCE) != 0) || + ((flags & CLOSEST_GEOM_INFO) != 0) || + ((flags & CLOSEST_INTERSECTION_POINT) != 0) || + ((flags & ALL_GEOM_INFO) != 0)) { + + pickInfo.setNodeRef((Node) srcNode.source); + Transform3D l2vw = geomAtoms[i].source.getCurrentLocalToVworld(); + if(pickInfo == null) + pickInfo = new PickInfo(); + pickInfo.setLocalToVWorldRef(l2vw); + } + + if(pickInfo != null) + pickInfoList.add(pickInfo); + if(pickType == PICK_ANY) { + return pickInfoList; + } + } + } + + return pickInfoList; + } + + static PickInfo[] pick(Object node, GeometryAtom[] geomAtoms, + int mode, int flags, PickShape pickShape, int pickType) { + + int pickInfoListSize; + PickInfo[] pickInfoArr = null; + Locale locale = null; + BranchGroupRetained bgRetained = null; + ArrayList initPath = null; + ArrayList pickInfoList = null; + + if (node instanceof Locale) { + locale = (Locale) node; + } + else if ( node instanceof BranchGroupRetained) { + bgRetained = (BranchGroupRetained) node; + locale = bgRetained.locale; + } + synchronized (locale.universe.sceneGraphLock) { + if ( bgRetained != null) { + initPath = initSceneGraphPath(bgRetained); + } + pickInfoList = getPickInfos(initPath, bgRetained, geomAtoms, + locale, flags, pickType); + } + + // We're done with PICK_BOUNDS case, but there is still more work for PICK_GEOMETRY case. + if((mode == PICK_GEOMETRY) && ((pickInfoListSize = pickInfoList.size()) > 0)) { + + //System.out.println("PickInfo.pick() - In geometry case : pickInfoList.size() is " + pickInfoListSize); + PickInfo pickInfo = null; + Node pickNode = null; + + // Order is impt. Need to do in reverse order. + for(int i = pickInfoListSize - 1; i >= 0; i--) { + pickInfo = (PickInfo) pickInfoList.get(i); + pickNode = pickInfo.getNode(); + + if (pickNode instanceof Shape3D) { + + /* + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are + * as follows : + * + * By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ + * By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ + * Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above) + * + */ + + if (!pickNode.getCapability(Shape3D.ALLOW_GEOMETRY_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo0")); + } + + for (int j = 0; j < ((Shape3D)pickNode).numGeometries(); j++) { + Geometry geo = ((Shape3D)pickNode).getGeometry(j); + + if(!geo.getCapability(Geometry.ALLOW_INTERSECT)) { + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo1")); + } + + if (geo instanceof GeometryArray) { + if(!geo.getCapability(GeometryArray.ALLOW_COORDINATE_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo2")); + if(!geo.getCapability(GeometryArray.ALLOW_COUNT_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo3")); + if(!geo.getCapability(GeometryArray.ALLOW_FORMAT_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo4")); + if (geo instanceof IndexedGeometryArray) { + if(!geo.getCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo5")); + } + } else if (geo instanceof CompressedGeometry) { + if(!geo.getCapability(CompressedGeometry.ALLOW_GEOMETRY_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo0")); + } + } + + if (((Shape3DRetained)(pickNode.retained)).intersect(pickInfo, pickShape, flags) == false) { + // System.out.println(" ---- geom " + i + " not intersected"); + + pickInfoList.remove(i); + + } + else if(pickType == PICK_ANY) { + pickInfoArr = new PickInfo[1]; + pickInfoArr[0] = pickInfo; + return pickInfoArr; + } + } else if (pickNode instanceof Morph) { + + /* + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are + * as follows : + * + * By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ + * By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ + * Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above) + * + */ + + if (!pickNode.getCapability(Morph.ALLOW_GEOMETRY_ARRAY_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo6")); + } + + int numGeo = ((MorphRetained)(pickNode.retained)).getNumGeometryArrays(); + for (int j = 0; j < numGeo; j++) { + GeometryArray geo = ((Morph)pickNode).getGeometryArray(j); + + if(!geo.getCapability(Geometry.ALLOW_INTERSECT)) { + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo1")); + } + + if(!geo.getCapability(GeometryArray.ALLOW_COORDINATE_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo2")); + if(!geo.getCapability(GeometryArray.ALLOW_COUNT_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo3")); + if(!geo.getCapability(GeometryArray.ALLOW_FORMAT_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo4")); + + if (geo instanceof IndexedGeometryArray) { + if(!geo.getCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("PickInfo5")); + } + } + + if (((MorphRetained)(pickNode.retained)).intersect(pickInfo, pickShape, flags) == false) { + pickInfoList.remove(i); + } + else if(pickType == PICK_ANY) { + pickInfoArr = new PickInfo[1]; + pickInfoArr[0] = pickInfo; + return pickInfoArr; + } + } + } + } + + // System.out.println("PickInfo : pickInfoList " + pickInfoList); + + if ((pickInfoList != null) && (pickInfoList.size() > 0)) { + // System.out.println(" --- : pickInfoList.size() " + pickInfoList.size()); + // System.out.println(" --- : pickInfoList's sgp " + + // ((PickInfo)(pickInfoList.get(0))).getSceneGraphPath()); + pickInfoArr = new PickInfo[pickInfoList.size()]; + return (PickInfo []) pickInfoList.toArray(pickInfoArr); + } + + return null; + + } + + /** + * The IntersectionInfo object holds extra information about an intersection + * of a PickShape with a Node as part of a PickInfo. Information such as + * the intersected geometry, the intersected point, and the vertex indices + * can be inquired. + * The local coordinates, normal, color and texture coordiantes of at the + * intersection can be computed, if they are present and readable, using the + * interpolation weights and vertex indices. + * <p> + * If the Shape3D being picked has multiple geometry arrays, the possible arrays + * of IntersectionInfo are stored in the PickInfo and referred to by a geometry + * index. If the picked geometry is of type, Text3D or CompressGeometry, + * getVertexIndices is invalid. If the picked Node is an Morph + * object, the geometry used in pick computation is alway at index 0. + * <p> + * + * @since Java 3D 1.4 + */ + + public class IntersectionInfo extends Object { + + /* The index to the intersected geometry in the pickable node */ + private int geomIndex; + + /* The reference to the intersected geometry in the pickable object */ + private Geometry geom; + + /* The intersection point */ + private Point3d intersectionPoint; + + /* Distance between start point of pickShape and intersection point */ + private double distance; + + /* The vertex indices of the intersected primitive in the geometry */ + private int[] vertexIndices; + + /* The interpolation weights for each of the verticies of the primitive */ + // private float[] weights; Not supported. Should be done in util. package + + /** IntersectionInfo Constructor */ + IntersectionInfo() { + + } + + void setGeometryIndex(int geomIndex) { + this.geomIndex = geomIndex; + } + + void setGeometry(Geometry geom) { + this.geom = geom; + } + + void setIntersectionPoint(Point3d intersectionPoint) { + this.intersectionPoint = intersectionPoint; + } + + void setDistance(double distance) { + this.distance = distance; + } + + void setVertexIndices(int[] vertexIndices) { + this.vertexIndices = vertexIndices; + } + + + /** + * Retrieves the index to the intersected geometry in the picked node, either a Shape3D or Morph. + * @return the index of the intersected geometry in the pickable node. + */ + public int getGeometryIndex() { + return geomIndex; + } + + /** + * Retrieves the reference to the intersected geometry in the picked object, either a Shape3D or Morph. + * @return the intersected geometry in the pickable node. + */ + public Geometry getGeometry() { + return geom; + } + + /** + * Retrieves the reference to the intersection point in the pickable node. + * @return the intersected point in the pickable node. + */ + public Point3d getIntersectionPoint() { + return intersectionPoint; + } + + /** + * Retrieves the distance between the start point of the pickShape and the + * intersection point. + * @return distance between the start point of the pickShape and the + * intersection point. + */ + public double getDistance() { + return distance; + } + + /** + * Retrieves the vertex indices of the intersected primitive in the geometry. + * @return the vertex indices of the intersected primitive. + */ + public int[] getVertexIndices() { + return vertexIndices; + } + + } +} + + diff --git a/src/classes/share/javax/media/j3d/PickPoint.java b/src/classes/share/javax/media/j3d/PickPoint.java index 3001af1..22ec12b 100644 --- a/src/classes/share/javax/media/j3d/PickPoint.java +++ b/src/classes/share/javax/media/j3d/PickPoint.java @@ -20,6 +20,10 @@ import javax.vecmath.*; * * @see BranchGroup#pickAll * @see Locale#pickAll + * @see PickBounds + * + * @deprecated As of Java 3D version 1.4, use PickBounds with a + * BoundingSphere that has a small radius. */ public final class PickPoint extends PickShape { diff --git a/src/classes/share/javax/media/j3d/Picking.java b/src/classes/share/javax/media/j3d/Picking.java deleted file mode 100644 index 952248d..0000000 --- a/src/classes/share/javax/media/j3d/Picking.java +++ /dev/null @@ -1,660 +0,0 @@ -/* - * $RCSfile$ - * - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * - * Use is subject to license terms. - * - * $Revision$ - * $Date$ - * $State$ - */ - -package javax.media.j3d; - -import javax.vecmath.*; -import java.util.*; - - -/** - * Internal class that implements picking functionality. - */ - -class Picking { - - static SceneGraphPath[] pickAll(Locale locale, PickShape shape) { - if(locale == null) { - return null; - } - - GeometryAtom geomAtoms[] = - locale.universe.geometryStructure.pickAll(locale, shape); - if ((geomAtoms == null) || (geomAtoms.length == 0)) { - // although getSceneGraphPath() also return null, we - // save time for synchronization - return null; - } - synchronized (locale.universe.sceneGraphLock) { - return getSceneGraphPath(null, null, geomAtoms, locale); - } - } - - - - static SceneGraphPath[] pickAll(BranchGroup node, - PickShape shape) { - if (node == null) { - return null; - } - - BranchGroupRetained nodeR = (BranchGroupRetained) node.retained; - - if (nodeR.inSharedGroup) { - throw new RestrictedAccessException(J3dI18N.getString("Picking0")); - } - - Locale locale = nodeR.locale; - - GeometryAtom geomAtoms[] = - locale.universe.geometryStructure.pickAll(locale, shape); - - if ((geomAtoms == null) || (geomAtoms.length == 0)) { - return null; - } - - synchronized (nodeR.universe.sceneGraphLock) { - return getSceneGraphPath(initSceneGraphPath(nodeR), - nodeR, geomAtoms, locale); - } - } - - - static SceneGraphPath[] pickAllSorted(Locale locale, - PickShape shape) { - if(locale == null) { - return null; - } - - GeometryAtom geomAtoms[] = - locale.universe.geometryStructure.pickAll(locale, shape); - - if ((geomAtoms == null) || (geomAtoms.length == 0)) { - return null; - } - - sortGeomAtoms(geomAtoms, shape); - - synchronized (locale.universe.sceneGraphLock) { - return getSceneGraphPath(null, null, geomAtoms, locale); - } - } - - - static SceneGraphPath[] pickAllSorted(BranchGroup node, - PickShape shape) { - if (node == null) { - return null; - } - - BranchGroupRetained nodeR = (BranchGroupRetained) node.retained; - - if (nodeR.inSharedGroup) { - throw new RestrictedAccessException(J3dI18N.getString("Picking0")); - } - - Locale locale = nodeR.locale; - - GeometryAtom geomAtoms[] = - locale.universe.geometryStructure.pickAll(locale, shape); - - if ((geomAtoms == null) || (geomAtoms.length == 0)) { - return null; - } - - // we have to sort first before eliminate duplicate Text3D - // since we want the closest geometry atoms of Text3D - sortGeomAtoms(geomAtoms, shape); - - synchronized (nodeR.universe.sceneGraphLock) { - return getSceneGraphPath(initSceneGraphPath(nodeR), - nodeR, geomAtoms, locale); - } - } - - - static SceneGraphPath pickClosest(Locale locale, - PickShape shape) { - - if(locale == null) { - return null; - } - - GeometryAtom geomAtoms[] = - locale.universe.geometryStructure.pickAll(locale, shape); - - - if ((geomAtoms == null) || (geomAtoms.length == 0)) { - return null; - } - - - GeometryAtom geomAtom = selectClosest(geomAtoms, shape); - - - synchronized (locale.universe.sceneGraphLock) { - return getSceneGraphPath(null, null, geomAtom, locale); - } - } - - - static SceneGraphPath pickClosest(BranchGroup node, - PickShape shape) { - if (node == null) { - return null; - } - - BranchGroupRetained nodeR = (BranchGroupRetained) node.retained; - - if (nodeR.inSharedGroup) { - throw new RestrictedAccessException(J3dI18N.getString("Picking0")); - } - - Locale locale = nodeR.locale; - - GeometryAtom geomAtoms[] = - locale.universe.geometryStructure.pickAll(locale, shape); - - - - if ((geomAtoms == null) || (geomAtoms.length == 0)) { - return null; - } - - - // We must sort all since the closest one in geomAtoms may not - // under the BranchGroup node - sortGeomAtoms(geomAtoms, shape); - - synchronized (nodeR.universe.sceneGraphLock) { - return getFirstSceneGraphPath(initSceneGraphPath(nodeR), - nodeR, geomAtoms, locale); - - } - } - - - static SceneGraphPath pickAny(Locale locale, PickShape shape) { - - if(locale == null) { - return null; - } - - GeometryAtom geomAtom = - locale.universe.geometryStructure.pickAny(locale, shape); - - if (geomAtom == null) { - return null; - } - - - synchronized (locale.universe.sceneGraphLock) { - return getSceneGraphPath(null, null, geomAtom, locale); - } - } - - static SceneGraphPath pickAny(BranchGroup node, PickShape shape) { - - if (node == null) { - return null; - } - - BranchGroupRetained nodeR = (BranchGroupRetained) node.retained; - - if (nodeR.inSharedGroup) { - throw new RestrictedAccessException(J3dI18N.getString("Picking0")); - } - - Locale locale = nodeR.locale; - - // since PickAny return from geometry may not lie under - // BranchGroup node, we have to use pickAll - - GeometryAtom geomAtoms[] = - locale.universe.geometryStructure.pickAll(locale, shape); - - if ((geomAtoms == null) || (geomAtoms.length == 0)) { - return null; - } - - synchronized (nodeR.universe.sceneGraphLock) { - return getFirstSceneGraphPath(initSceneGraphPath(nodeR), - nodeR, geomAtoms, locale); - } - } - - - /** - * Search the path from nodeR up to Locale. - * Return the search path as ArrayList if found. - * Note that the locale will not insert into path. - */ - static private ArrayList initSceneGraphPath(NodeRetained nodeR) { - ArrayList path = new ArrayList(5); - - do { - if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)){ - path.add(nodeR); - } - nodeR = nodeR.parent; - } while (nodeR != null); // reach Locale - - return path; - } - - /** - * return all SceneGraphPath[] of the geomAtoms. - * If initpath is null, the path is search from - * geomAtom Shape3D/Morph Node up to Locale - * (assume the same locale). - * Otherwise, the path is search up to node or - * null is return if it is not hit. - */ - static private SceneGraphPath[] getSceneGraphPath(ArrayList initpath, - BranchGroupRetained node, - GeometryAtom geomAtoms[], - Locale locale) { - - ArrayList paths = new ArrayList(5); - GeometryAtom geomAtom; - NodeRetained target; - ArrayList texts = null; - - if (geomAtoms == null) { - return null; - } - - - for (int i=0; i < geomAtoms.length; i++) { - geomAtom = (GeometryAtom) geomAtoms[i]; - Shape3DRetained shape = geomAtom.source; - - // isPickable and currentSwitchOn has been check in BHTree - - if (!inside(shape.branchGroupPath, node)) { - continue; - } - - target = shape.sourceNode; - - if (target == null) { - // The node is just detach from branch so sourceNode = null - continue; - } - - // Special case, for Text3DRetained, it is possible - // for different geomAtoms pointing to the same - // source Text3DRetained. So we need to combine - // those cases and report only once. - if (target instanceof Shape3DRetained) { - Shape3DRetained s3dR = (Shape3DRetained) target; - GeometryRetained geomR = null; - for(int cnt=0; cnt<s3dR.geometryList.size(); cnt++) { - geomR = (GeometryRetained) s3dR.geometryList.get(cnt); - if(geomR != null) - break; - } - - if (geomR == null) - continue; - - if (geomR instanceof Text3DRetained) { - // assume this case is not frequent, we allocate - // ArrayList only when necessary and we use ArrayList - // instead of HashMap since the case of when large - // number of distingish Text3DRetained node hit is - // rare. - if (texts == null) { - texts = new ArrayList(3); - } else { - int size = texts.size(); - boolean found = false; - for (int j=0; j < size; j++) { - if (texts.get(j) == target) { - found = true; - break; - } - } - if (found) { - continue; // try next geomAtom - } - } - texts.add(target); - } - } - - ArrayList path = retrievePath(target, node, - geomAtom.source.key); - - if (path == null) { - continue; - } - - // If target is instance of compile retained, then loop thru - // the entire source list and add it to the scene graph path - if (target instanceof Shape3DCompileRetained) { - Shape3DCompileRetained s3dCR = (Shape3DCompileRetained)target; - Node[] mpath = mergePath(path, initpath); - for (int n = 0; n < s3dCR.srcList.length; n++) { - SceneGraphPath sgpath = new SceneGraphPath(locale, - mpath, - (Node) s3dCR.srcList[n]); - sgpath.setTransform(shape.getCurrentLocalToVworld(0)); - paths.add(sgpath); - } - - } - else { - SceneGraphPath sgpath = new SceneGraphPath(locale, - mergePath(path, initpath), - (Node) target.source); - sgpath.setTransform(shape.getCurrentLocalToVworld(0)); - paths.add(sgpath); - } - - - } - SceneGraphPath pathArray[] = new SceneGraphPath[paths.size()]; - return (SceneGraphPath []) paths.toArray(pathArray); - } - - /** - * return the SceneGraphPath of the geomAtom. - * If initpath is null, the path is search from - * geomAtom Shape3D/Morph Node up to Locale - * (assume the same locale). - * Otherwise, the path is search up to node or - * null is return if it is not hit. - */ - static private SceneGraphPath getSceneGraphPath(ArrayList initpath, - BranchGroupRetained node, - GeometryAtom geomAtom, - Locale locale) { - if (geomAtom == null) { - return null; - } - - Shape3DRetained shape = geomAtom.source; - NodeRetained target = shape.sourceNode; - - if (target == null) { - // The node is just detach from branch so sourceNode = null - return null; - } - - if (!inside(shape.branchGroupPath, node)) { - return null; - } - - ArrayList path = retrievePath(target, node, shape.key); - - if (path == null) { - return null; - } - - SceneGraphPath sgpath = new SceneGraphPath(locale, - mergePath(path, initpath), - (Node) - target.source); - sgpath.setTransform(shape.getCurrentLocalToVworld(0)); - return sgpath; - } - - /** - * Return true if bg is inside cachedBG or bg is null - */ - static private boolean inside(BranchGroupRetained bgArr[], - BranchGroupRetained bg) { - - if ((bg == null) || (bgArr == null)) { - return true; - } - - for (int i=0; i < bgArr.length; i++) { - if (bgArr[i] == bg) { - return true; - } - } - return false; - } - - - /** - * return the first SceneGraphPath of the geomAtom. - * If initpath is null, the path is search from - * geomAtom Shape3D/Morph Node up to Locale - * (assume the same locale). - * Otherwise, the path is search up to node or - * null is return if it is not hit. - */ - static private SceneGraphPath getFirstSceneGraphPath(ArrayList initpath, - BranchGroupRetained node, - GeometryAtom geomAtoms[], - Locale locale) { - if (geomAtoms == null) { - return null; - } - - for (int i=0; i < geomAtoms.length; i++) { - Shape3DRetained shape = geomAtoms[i].source; - NodeRetained target = shape.sourceNode; - - if (target == null) { - // The node is just detach from branch so sourceNode = null - continue; - } - if (!inside(shape.branchGroupPath, node)) { - continue; - } - ArrayList path = retrievePath(target, node, geomAtoms[i].source.key); - - if (path == null) { - continue; - } - SceneGraphPath sgpath = new SceneGraphPath(locale, - mergePath(path, initpath), - (Node) target.source); - sgpath.setTransform(shape.getCurrentLocalToVworld(0)); - return sgpath; - } - return null; - } - - - /** - * search the full path from the botton of the scene graph - - * startNode, up to the Locale if endNode is null. - * If endNode is not null, the path is found up to, but not - * including, endNode or return null if endNode not hit - * during the search. - */ - static private ArrayList retrievePath(NodeRetained startNode, - NodeRetained endNode, - HashKey key) { - - ArrayList path = new ArrayList(5); - NodeRetained nodeR = startNode; - - if (nodeR.inSharedGroup) { - // getlastNodeId() will destroy this key - key = new HashKey(key); - } - - do { - if (nodeR == endNode) { // we found it ! - return path; - } - - if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)) { - path.add(nodeR); - } - - if (nodeR instanceof SharedGroupRetained) { - // retrieve the last node ID - String nodeId = key.getLastNodeId(); - Vector parents = ((SharedGroupRetained) nodeR).parents; - int sz = parents.size(); - NodeRetained prevNodeR = nodeR; - for(int i=0; i< sz; i++) { - NodeRetained linkR = (NodeRetained) parents.elementAt(i); - if (linkR.nodeId.equals(nodeId)) { - nodeR = linkR; - // Need to add Link to the path report - path.add(nodeR); - // since !(endNode instanceof Link), we - // can skip the check (nodeR == endNode) and - // proceed to parent of link below - break; - } - } - if (nodeR == prevNodeR) { - // branch is already detach - return null; - } - } - nodeR = nodeR.parent; - } while (nodeR != null); // reach Locale - - if (endNode == null) { - // user call pickxxx(Locale locale, PickShape shape) - return path; - } - - // user call pickxxx(BranchGroup endNode, PickShape shape) - // if locale is reached and endNode not hit, this is not - // the path user want to select - return null; - } - - /** - * copy p1, (follow by) p2 into a new array, p2 can be null - * The path is then reverse before return. - */ - static private Node[] mergePath(ArrayList p1, ArrayList p2) { - int s = p1.size(); - int len; - int i; - int l; - if (p2 == null) { - len = s; - } else { - len = s + p2.size(); - } - - Node nodes[] = new Node[len]; - l = len-1; - for (i=0; i < s; i++) { - nodes[l-i] = (Node) ((NodeRetained) p1.get(i)).source; - } - for (int j=0; i< len; i++, j++) { - nodes[l-i] = (Node) ((NodeRetained) p2.get(j)).source; - } - return nodes; - } - - /** - * Select the closest geomAtoms from shape - * geomAtoms.length must be >= 1 - */ - static private GeometryAtom selectClosest(GeometryAtom geomAtoms[], - PickShape shape) { - Point4d pickPos = new Point4d(); - GeometryAtom closestAtom = geomAtoms[0]; - shape.intersect(closestAtom.source.vwcBounds, pickPos); - double distance = pickPos.w; - - for (int i=1; i < geomAtoms.length; i++) { - shape.intersect(geomAtoms[i].source.vwcBounds, pickPos); - if (pickPos.w < distance) { - distance = pickPos.w; - closestAtom = geomAtoms[i]; - } - } - return closestAtom; - } - - /** - * Sort the GeometryAtoms distance from shape in ascending order - * geomAtoms.length must be >= 1 - */ - static private void sortGeomAtoms(GeometryAtom geomAtoms[], - PickShape shape) { - - final double distance[] = new double[geomAtoms.length]; - Point4d pickPos = new Point4d(); - - for (int i=0; i < geomAtoms.length; i++) { - shape.intersect(geomAtoms[i].source.vwcBounds, pickPos); - distance[i] = pickPos.w; - } - - class Sort { - - GeometryAtom atoms[]; - - Sort(GeometryAtom[] atoms) { - this.atoms = atoms; - } - - void sorting() { - if (atoms.length < 7) { - insertSort(); - } else { - quicksort(0, atoms.length-1); - } - } - - // Insertion sort on smallest arrays - final void insertSort() { - for (int i=0; i<atoms.length; i++) { - for (int j=i; j>0 && - (distance[j-1] > distance[j]); j--) { - double t = distance[j]; - distance[j] = distance[j-1]; - distance[j-1] = t; - GeometryAtom p = atoms[j]; - atoms[j] = atoms[j-1]; - atoms[j-1] = p; - } - } - } - - final void quicksort( int l, int r ) { - int i = l; - int j = r; - double k = distance[(l+r) / 2]; - - do { - while (distance[i]<k) i++; - while (k<distance[j]) j--; - if (i<=j) { - double tmp = distance[i]; - distance[i] =distance[j]; - distance[j] = tmp; - - GeometryAtom p=atoms[i]; - atoms[i]=atoms[j]; - atoms[j]=p; - i++; - j--; - } - } while (i<=j); - - if (l<j) quicksort(l,j); - if (l<r) quicksort(i,r); - } - } - - (new Sort(geomAtoms)).sorting(); - } - -} diff --git a/src/classes/share/javax/media/j3d/PointArray.java b/src/classes/share/javax/media/j3d/PointArray.java index 412f4d5..421960d 100644 --- a/src/classes/share/javax/media/j3d/PointArray.java +++ b/src/classes/share/javax/media/j3d/PointArray.java @@ -23,22 +23,21 @@ public class PointArray extends GeometryArray { PointArray() {} /** - * Constructs an empty PointArray object with the specified - * number of vertices, and vertex format. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. + * Constructs an empty PointArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 1 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public PointArray(int vertexCount, int vertexFormat) { super(vertexCount,vertexFormat); @@ -48,59 +47,29 @@ public class PointArray extends GeometryArray { } /** - * Constructs an empty PointArray object with the specified - * number of vertices, and vertex format, number of texture coordinate - * sets, and texture coordinate mapping array. - * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used. + * Constructs an empty PointArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 1 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -117,6 +86,52 @@ public class PointArray extends GeometryArray { } /** + * Constructs an empty PointArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 1 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public PointArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); + + if (vertexCount < 1 ) + throw new IllegalArgumentException(J3dI18N.getString("PointArray0")); + } + + /** * Creates the retained mode PointArrayRetained object that this * PointArray object will point to. */ @@ -130,21 +145,26 @@ public class PointArray extends GeometryArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - PointArrayRetained rt = (PointArrayRetained) retained; - int texSetCount = rt.getTexCoordSetCount(); - PointArray p; - if (texSetCount == 0) { - p = new PointArray(rt.getVertexCount(), - rt.getVertexFormat()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - p = new PointArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap); - } - p.duplicateNodeComponent(this); + PointArrayRetained rt = (PointArrayRetained) retained; + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + PointArray p = new PointArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes); + p.duplicateNodeComponent(this); return p; } } diff --git a/src/classes/share/javax/media/j3d/PointArrayRetained.java b/src/classes/share/javax/media/j3d/PointArrayRetained.java index b06e410..319a643 100644 --- a/src/classes/share/javax/media/j3d/PointArrayRetained.java +++ b/src/classes/share/javax/media/j3d/PointArrayRetained.java @@ -25,13 +25,15 @@ class PointArrayRetained extends GeometryArrayRetained { this.geoType = GEO_TYPE_POINT_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; - Point3d pnt = new Point3d(); + int count = 0; + int minICount = 0; int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); + Point3d pnt = new Point3d(); switch (pickShape.getPickType()) { case PickShape.PICKRAY: @@ -39,13 +41,15 @@ class PointArrayRetained extends GeometryArrayRetained { while (i < validVertexCount) { getVertexData(i++, pnt); - if (intersectPntAndRay(pnt, pickRay.origin, + count++; + if (intersectPntAndRay(pnt, pickRay.origin, pickRay.direction, sdist)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -61,14 +65,16 @@ class PointArrayRetained extends GeometryArrayRetained { pickSegment.end.z - pickSegment.start.z); while (i < validVertexCount) { getVertexData(i++, pnt); + count++; if (intersectPntAndRay(pnt, pickSegment.start, dir, sdist) && (sdist[0] <= 1.0)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -84,13 +90,15 @@ class PointArrayRetained extends GeometryArrayRetained { while (i < validVertexCount) { getVertexData(i++, pnt); + count++; if (bounds.intersect(pnt)) { - if (dist == null) { + if (flags == 0) { return true; } sdist[0] = pickShape.distance(pnt); if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -104,13 +112,14 @@ class PointArrayRetained extends GeometryArrayRetained { while (i < validVertexCount) { getVertexData(i++, pnt); - + count++; if (intersectCylinder(pnt, pickCylinder, sdist)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -123,13 +132,14 @@ class PointArrayRetained extends GeometryArrayRetained { while (i < validVertexCount) { getVertexData(i++, pnt); - + count++; if (intersectCone(pnt, pickCone, sdist)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = pnt.x; y = pnt.y; z = pnt.z; @@ -145,14 +155,19 @@ class PointArrayRetained extends GeometryArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=1); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[1]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; return true; } return false; - } boolean intersect(Point3d[] pnts) { diff --git a/src/classes/share/javax/media/j3d/PointAttributes.java b/src/classes/share/javax/media/j3d/PointAttributes.java index 29b9e92..66c4e39 100644 --- a/src/classes/share/javax/media/j3d/PointAttributes.java +++ b/src/classes/share/javax/media/j3d/PointAttributes.java @@ -65,6 +65,12 @@ public class PointAttributes extends NodeComponent { public static final int ALLOW_ANTIALIASING_WRITE = CapabilityBits.POINT_ATTRIBUTES_ALLOW_ANTIALIASING_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SIZE_READ, + ALLOW_ANTIALIASING_READ + }; + /** * Constructs a PointAttributes object with default parameters. * The default values are as follows: @@ -74,6 +80,8 @@ public class PointAttributes extends NodeComponent { * </ul> */ public PointAttributes(){ + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -82,8 +90,10 @@ public class PointAttributes extends NodeComponent { * @param pointAntialiasing flag to set point antialising ON or OFF */ public PointAttributes(float pointSize, boolean pointAntialiasing){ + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); - ((PointAttributesRetained)this.retained).initPointSize(pointSize); + ((PointAttributesRetained)this.retained).initPointSize(pointSize); ((PointAttributesRetained)this.retained).initPointAntialiasingEnable(pointAntialiasing); } diff --git a/src/classes/share/javax/media/j3d/PointLight.java b/src/classes/share/javax/media/j3d/PointLight.java index 3e87f84..147c186 100644 --- a/src/classes/share/javax/media/j3d/PointLight.java +++ b/src/classes/share/javax/media/j3d/PointLight.java @@ -80,6 +80,12 @@ public class PointLight extends Light { public static final int ALLOW_ATTENUATION_WRITE = CapabilityBits.POINT_LIGHT_ALLOW_ATTENUATION_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_POSITION_READ, + ALLOW_ATTENUATION_READ + }; + /** * Constructs a PointLight node with default parameters. * The default values are as follows: @@ -89,6 +95,8 @@ public class PointLight extends Light { * </ul> */ public PointLight() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -101,6 +109,10 @@ public class PointLight extends Light { Point3f position, Point3f attenuation) { super(color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointLightRetained)this.retained).initPosition(position); ((PointLightRetained)this.retained).initAttenuation(attenuation); } @@ -117,6 +129,10 @@ public class PointLight extends Light { Point3f position, Point3f attenuation) { super(lightOn, color); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointLightRetained)this.retained).initPosition(position); ((PointLightRetained)this.retained).initAttenuation(attenuation); } diff --git a/src/classes/share/javax/media/j3d/PointSound.java b/src/classes/share/javax/media/j3d/PointSound.java index 1f005eb..4af92dd 100644 --- a/src/classes/share/javax/media/j3d/PointSound.java +++ b/src/classes/share/javax/media/j3d/PointSound.java @@ -99,6 +99,13 @@ public class PointSound extends Sound { public static final int ALLOW_DISTANCE_GAIN_WRITE = CapabilityBits.POINT_SOUND_ALLOW_DISTANCE_GAIN_WRITE; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_POSITION_READ, + ALLOW_DISTANCE_GAIN_READ + }; + /** * Constructs and initializes a new PointSound node using default * parameters. The following default values are used: @@ -111,6 +118,9 @@ public class PointSound extends Sound { public PointSound() { // Uses default values defined for Sound and PointSound nodes super(); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } /** @@ -126,6 +136,10 @@ public class PointSound extends Sound { float initialGain, Point3f position) { super(soundData, initialGain); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointSoundRetained)this.retained).setPosition(position); } @@ -144,6 +158,10 @@ public class PointSound extends Sound { float initialGain, float posX, float posY, float posZ ) { super(soundData, initialGain); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointSoundRetained)this.retained).setPosition(posX,posY,posZ); } @@ -180,6 +198,10 @@ public class PointSound extends Sound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointSoundRetained)this.retained).setPosition(position); ((PointSoundRetained)this.retained).setDistanceGain(distanceGain); } @@ -215,6 +237,10 @@ public class PointSound extends Sound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointSoundRetained)this.retained).setPosition(posX,posY,posZ); ((PointSoundRetained)this.retained).setDistanceGain(distanceGain); } @@ -249,6 +275,10 @@ public class PointSound extends Sound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointSoundRetained)this.retained).setPosition(position); ((PointSoundRetained)this.retained).setDistanceGain( attenuationDistance, attenuationGain); @@ -286,6 +316,10 @@ public class PointSound extends Sound { super(soundData, initialGain, loopCount, release, continuous, enable, region, priority ); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PointSoundRetained)this.retained).setPosition(posX,posY,posZ); ((PointSoundRetained)this.retained).setDistanceGain( attenuationDistance, attenuationGain); diff --git a/src/classes/share/javax/media/j3d/PolygonAttributes.java b/src/classes/share/javax/media/j3d/PolygonAttributes.java index 25b1269..ec676e2 100644 --- a/src/classes/share/javax/media/j3d/PolygonAttributes.java +++ b/src/classes/share/javax/media/j3d/PolygonAttributes.java @@ -146,6 +146,14 @@ public class PolygonAttributes extends NodeComponent { */ public static final int CULL_FRONT = 2; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_CULL_FACE_READ, + ALLOW_MODE_READ, + ALLOW_NORMAL_FLIP_READ, + ALLOW_OFFSET_READ + }; + /** * Constructs a PolygonAttributes object with default parameters. * The default values are as follows: @@ -159,6 +167,8 @@ public class PolygonAttributes extends NodeComponent { */ public PolygonAttributes() { // Just use defaults for all attributes + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -216,6 +226,9 @@ public class PolygonAttributes extends NodeComponent { if (cullFace < CULL_NONE || cullFace > CULL_FRONT) throw new IllegalArgumentException(J3dI18N.getString("PolygonAttributes12")); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((PolygonAttributesRetained)this.retained).initPolygonMode(polygonMode); ((PolygonAttributesRetained)this.retained).initCullFace(cullFace); ((PolygonAttributesRetained)this.retained).initPolygonOffset(polygonOffset); diff --git a/src/classes/share/javax/media/j3d/QuadArray.java b/src/classes/share/javax/media/j3d/QuadArray.java index 79818d3..ee7ab2f 100644 --- a/src/classes/share/javax/media/j3d/QuadArray.java +++ b/src/classes/share/javax/media/j3d/QuadArray.java @@ -25,23 +25,22 @@ public class QuadArray extends GeometryArray { QuadArray() {} /** - * Constructs an empty QuadArray object with the specified - * number of vertices, and vertex format. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. + * Constructs an empty QuadArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 4 * or vertexCount is <i>not</i> a multiple of 4 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public QuadArray(int vertexCount, int vertexFormat) { super(vertexCount,vertexFormat); @@ -51,60 +50,30 @@ public class QuadArray extends GeometryArray { } /** - * Constructs an empty QuadArray object with the specified - * number of vertices, and vertex format, number of texture coordinate - * sets, and texture coordinate mapping array. - * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3 or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used. + * Constructs an empty QuadArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 4 * or vertexCount is <i>not</i> a multiple of 4 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -121,6 +90,53 @@ public class QuadArray extends GeometryArray { } /** + * Constructs an empty QuadArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 4 + * or vertexCount is <i>not</i> a multiple of 4 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public QuadArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); + + if (vertexCount < 4 || ((vertexCount%4) != 0)) + throw new IllegalArgumentException(J3dI18N.getString("QuadArray0")); + } + + /** * Creates the retained mode QuadArrayRetained object that this * QuadArray object will point to. */ @@ -134,21 +150,26 @@ public class QuadArray extends GeometryArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - QuadArrayRetained rt = (QuadArrayRetained) retained; - int texSetCount = rt.getTexCoordSetCount(); - QuadArray q; - if (texSetCount == 0) { - q = new QuadArray(rt.getVertexCount(), - rt.getVertexFormat()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - q = new QuadArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap); - } - q.duplicateNodeComponent(this); + QuadArrayRetained rt = (QuadArrayRetained) retained; + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + QuadArray q = new QuadArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes); + q.duplicateNodeComponent(this); return q; } diff --git a/src/classes/share/javax/media/j3d/QuadArrayRetained.java b/src/classes/share/javax/media/j3d/QuadArrayRetained.java index b33f605..5e95b76 100644 --- a/src/classes/share/javax/media/j3d/QuadArrayRetained.java +++ b/src/classes/share/javax/media/j3d/QuadArrayRetained.java @@ -27,14 +27,15 @@ class QuadArrayRetained extends GeometryArrayRetained { this.geoType = GEO_TYPE_QUAD_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[4]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; + int count = 0; + int minICount = 0; int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); - pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); @@ -49,12 +50,14 @@ class QuadArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); getVertexData(i++, pnts[3]); + count += 4; if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -70,18 +73,19 @@ class QuadArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); getVertexData(i++, pnts[3]); + count += 4; if (intersectSegment(pnts, pickSegment.start, pickSegment.end, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; } - } } break; @@ -93,20 +97,20 @@ class QuadArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); getVertexData(i++, pnts[3]); - + count += 4; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; } } } - break; case PickShape.PICKBOUNDINGSPHERE: BoundingSphere bsphere = (BoundingSphere) @@ -117,13 +121,14 @@ class QuadArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); getVertexData(i++, pnts[3]); - + count += 4; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -141,13 +146,14 @@ class QuadArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); getVertexData(i++, pnts[3]); - + count += 4; if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -163,13 +169,14 @@ class QuadArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); getVertexData(i++, pnts[3]); - + count += 4; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -185,12 +192,14 @@ class QuadArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); getVertexData(i++, pnts[3]); + count += 4; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -206,7 +215,16 @@ class QuadArrayRetained extends GeometryArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >= 4); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[4]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 4; + vertexIndices[1] = minICount - 3; + vertexIndices[2] = minICount - 2; + vertexIndices[3] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; @@ -215,7 +233,7 @@ class QuadArrayRetained extends GeometryArrayRetained { return false; } - + // intersect pnts[] with every quad in this object boolean intersect(Point3d[] pnts) { Point3d[] points = new Point3d[4]; diff --git a/src/classes/share/javax/media/j3d/Raster.java b/src/classes/share/javax/media/j3d/Raster.java index d14eaf7..d95fee7 100644 --- a/src/classes/share/javax/media/j3d/Raster.java +++ b/src/classes/share/javax/media/j3d/Raster.java @@ -180,6 +180,17 @@ public class Raster extends Geometry { ALLOW_CLIP_MODE_WRITE = CapabilityBits.RASTER_ALLOW_CLIP_MODE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_POSITION_READ, + ALLOW_OFFSET_READ, + ALLOW_IMAGE_READ, + ALLOW_DEPTH_COMPONENT_READ, + ALLOW_SIZE_READ, + ALLOW_TYPE_READ, + ALLOW_CLIP_MODE_READ + }; + /** * Constructs a Raster object with default parameters. * The default values are as follows: @@ -195,6 +206,8 @@ public class Raster extends Geometry { * </ul> */ public Raster() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -223,6 +236,9 @@ public class Raster extends Geometry { ImageComponent2D image, DepthComponent depthComponent) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((RasterRetained)this.retained).setPosition(pos); ((RasterRetained)this.retained).setType(type); ((RasterRetained)this.retained).setSrcOffset(xSrcOffset, ySrcOffset); @@ -252,6 +268,9 @@ public class Raster extends Geometry { ImageComponent2D image, DepthComponent depthComponent) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((RasterRetained)this.retained).setPosition(pos); ((RasterRetained)this.retained).setType(type); ((RasterRetained)this.retained).setSrcOffset(srcOffset.x, srcOffset.y); @@ -289,6 +308,9 @@ public class Raster extends Geometry { ImageComponent2D image, DepthComponent depthComponent) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((RasterRetained)this.retained).setPosition(pos); ((RasterRetained)this.retained).setType(type); ((RasterRetained)this.retained).setClipMode(clipMode); diff --git a/src/classes/share/javax/media/j3d/RasterRetained.java b/src/classes/share/javax/media/j3d/RasterRetained.java index d580cd7..bd591b9 100644 --- a/src/classes/share/javax/media/j3d/RasterRetained.java +++ b/src/classes/share/javax/media/j3d/RasterRetained.java @@ -687,9 +687,10 @@ class RasterRetained extends GeometryRetained { ImageComponentUpdateInfo value) { } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { return false; } + boolean intersect(Bounds targetBound) { return false; } diff --git a/src/classes/share/javax/media/j3d/RenderBin.java b/src/classes/share/javax/media/j3d/RenderBin.java index e252bef..23ba119 100644 --- a/src/classes/share/javax/media/j3d/RenderBin.java +++ b/src/classes/share/javax/media/j3d/RenderBin.java @@ -46,6 +46,12 @@ class RenderBin extends J3dStructure implements ObjectUpdate { ArrayList aBinUpdateList = new ArrayList(); /** + * List of ShaderBin that are soleUser that + * needs to have its components updated @updateObject time + */ + ArrayList sBinUpdateList = new ArrayList(); + + /** * List of TextureBin that are soleUser that * needs to have its components updated @updateObject time */ @@ -95,6 +101,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { ArrayList lightBinFreelist = new ArrayList(5); ArrayList envSetFreelist = new ArrayList(5); ArrayList attrBinFreelist = new ArrayList(5); + ArrayList shaderBinFreelist = new ArrayList(5); ArrayList textureBinFreelist = new ArrayList(5); ArrayList renderMoleculeFreelist = new ArrayList(5); ArrayList transparentInfoFreeList = new ArrayList(5); @@ -167,6 +174,8 @@ class RenderBin extends J3dStructure implements ObjectUpdate { */ View view = null; + private Comparator transparencySortComparator = null; + ArrayList toBeAddedTextureResourceFreeList = new ArrayList(5); ArrayList displayListResourceFreeList = new ArrayList(5); boolean resourceToFree = false; @@ -526,10 +535,15 @@ class RenderBin extends J3dStructure implements ObjectUpdate { for (i = 0; i < size; i++) { AttributeBin abin = (AttributeBin)aBinUpdateList.get(i); abin.updateNodeComponent(); - } } + if ((size = sBinUpdateList.size()) > 0) { + for (i = 0; i < size; i++) { + ShaderBin sbin = (ShaderBin)sBinUpdateList.get(i); + sbin.updateNodeComponent(); + } + } // Update the sole user TextureBins. if (tbUpdateList.size() > 0) { @@ -544,12 +558,12 @@ class RenderBin extends J3dStructure implements ObjectUpdate { // texture in the first texture unit state for (i = 0; i < size; i++) { tb = (TextureBin) tbUpdateList.get(i); - // Bug Id : 4701430 - Have to be sure tb.attributeBin is + // Bug Id : 4701430 - Have to be sure tb.shaderBin is // not equal to null. This is a temporary fix for j3d1.3. if (((tb.tbFlag & TextureBin.RESORT) != 0) && - (tb.attributeBin != null)) { + (tb.shaderBin != null)) { - tb.attributeBin.reInsertTextureBin(tb); + tb.shaderBin.reInsertTextureBin(tb); tb.tbFlag &= ~TextureBin.RESORT; } } @@ -823,7 +837,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { continue; zVal = renderAtom.geometryAtom.centroid[k].distanceSquared(eyeInVworld); renderAtom.parentTInfo[k].zVal = zVal; - + renderAtom.parentTInfo[k].geometryAtom = renderAtom.geometryAtom; } } @@ -923,7 +937,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { } // lock list of dlist - // TODO: Instead of copying could we keep 2 arrays + // XXXX: Instead of copying could we keep 2 arrays // and just toggle? size = dirtyRenderMoleculeList.size(); for (i = 0; i < size; i++) { @@ -964,7 +978,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { RenderAtomListInfo arr[]; RenderAtomListInfo ra; - // TODO: there is a possible problem in the case of multiple + // XXXX: there is a possible problem in the case of multiple // renderers (i.e., multiple screens). Unless the // MasterControl sends us a separate message for each // renderer, we won't create a new display list for renderers @@ -1125,6 +1139,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { rmUpdateList.clear(); ogCIOList.clear(); aBinUpdateList.clear(); + sBinUpdateList.clear(); tbUpdateList.clear(); removeRenderAtomInRMList.clear(); addOpaqueBin = null; @@ -1334,6 +1349,10 @@ class RenderBin extends J3dStructure implements ObjectUpdate { } } texIdObj = new Integer(id); + // XXXX: The following code seems wrong -- why add it to + // the list if it is already there? Maybe one is for the + // texture and the other (idential value) is for the + // detail texture? if (cv.textureIdResourceFreeList.contains(texIdObj)) { cv.textureIdResourceFreeList.add(texIdObj); dtex.resourceCreationMask[tex.format] &= ~cv.canvasBit; @@ -1616,8 +1635,13 @@ class RenderBin extends J3dStructure implements ObjectUpdate { // Texture is always in a sole user position processTextureChanged((NodeComponentRetained) m.args[0], (GeometryAtom[])m.args[3], - m.args); - + m.args); + m.decRefcount(); + break; + case J3dMessage.SHADER_APPEARANCE_CHANGED: + case J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED: + case J3dMessage.SHADER_ATTRIBUTE_CHANGED: + processShaderComponentChanged(m.args); m.decRefcount(); break; case J3dMessage.RENDERINGATTRIBUTES_CHANGED: @@ -1695,7 +1719,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { updateViewPlatform((ViewPlatformRetained)vp.retained, ((Float)m.args[1]).floatValue()); visQuery = true; - // TODO : Handle view.visibilityPolicy changed. + // XXXX : Handle view.visibilityPolicy changed. if(((View.VISIBILITY_POLICY_DIRTY != 0) && (View.VISIBILITY_DRAW_ALL != view.viewCache.visibilityPolicy)) || locale != ((ViewPlatformRetained) (vp.retained)).locale) { @@ -2050,7 +2074,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { RenderAtom ra = null; TextureBin tb; - AttributeBin ab; + ShaderBin sb; boolean reInsertNeeded = false; if (nc.mirror.changedFrequent == 0) { @@ -2101,9 +2125,9 @@ class RenderBin extends J3dStructure implements ObjectUpdate { tb.soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TA; } else { - ab= ra.renderMolecule.textureBin.attributeBin; + sb= ra.renderMolecule.textureBin.shaderBin; ra.renderMolecule.removeRenderAtom(ra); - reInsertTextureBin(ab, ra); + reInsertTextureBin(sb, ra); } } } @@ -2113,7 +2137,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { RenderAtom ra = null; TextureBin tb; - AttributeBin ab; + ShaderBin sb; boolean reInsertNeeded = false; if (nc.mirror.changedFrequent == 0) { @@ -2164,9 +2188,9 @@ class RenderBin extends J3dStructure implements ObjectUpdate { tb.soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TC; } else { - ab= ra.renderMolecule.textureBin.attributeBin; + sb= ra.renderMolecule.textureBin.shaderBin; ra.renderMolecule.removeRenderAtom(ra); - reInsertTextureBin(ab, ra); + reInsertTextureBin(sb, ra); } } } @@ -2178,7 +2202,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { RenderAtom ra = null; TextureBin tb; - AttributeBin ab; + ShaderBin sb; boolean reInsertNeeded = false; int command = ((Integer)args[1]).intValue(); @@ -2275,7 +2299,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { GeometryAtom[] gaArr) { RenderAtom ra = null; TextureBin tb; - AttributeBin ab; + ShaderBin sb; boolean mirrorSet = false; boolean firstTextureBin = true; @@ -2313,9 +2337,9 @@ class RenderBin extends J3dStructure implements ObjectUpdate { tb.soleUserCompDirty |= TextureBin.SOLE_USER_DIRTY_TUS; } else { - ab= ra.renderMolecule.textureBin.attributeBin; + sb = ra.renderMolecule.textureBin.shaderBin; ra.renderMolecule.removeRenderAtom(ra); - reInsertTextureBin(ab, ra); + reInsertTextureBin(sb, ra); } } } @@ -2359,7 +2383,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { if (ra== null || !ra.inRenderBin()) continue; if (restructure && !ra.renderMolecule.textureBin.attributeBin.soleUser) { - EnvironmentSet e= ra.renderMolecule.textureBin.attributeBin.environmentSet; + EnvironmentSet e= ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); /* @@ -2400,6 +2424,131 @@ class RenderBin extends J3dStructure implements ObjectUpdate { } } + /** + * This processes a shader component change. + */ + void processShaderComponentChanged(Object[] args) { + + // System.out.println("RenderBin : processShaderComponentChanged"); + + int component = ((Integer)args[1]).intValue(); + int i; + GeometryAtom[] gaArr = (GeometryAtom[] )args[3]; + GeometryAtom ga; + RenderAtom ra = null; + /* TODO : JADA - Sole user logic is incomplete. Will disable for JavaOne */ + // Note : args[0] may be a ShaderAppearanceRetained or ShaderAttributeSetRetained + //ShaderAppearanceRetained sApp = (ShaderAppearanceRetained) args[0]; + int start = -1; + + + // Get the first ra that is visible + for (i = 0; (i < gaArr.length && (start < 0)); i++) { + ra = gaArr[i].getRenderAtom(view); + if (ra== null || !ra.inRenderBin()) { + continue; + } + else { + start = i; + } + } + if (start >= 0) { + + + + boolean spUpdate = + ((component & ShaderAppearanceRetained.SHADER_PROGRAM) != 0); + boolean sasUpdate = + (((component & ShaderAppearanceRetained.SHADER_ATTRIBUTE_SET) != 0) || + ((component & ShaderAttributeSetRetained.ATTRIBUTE_SET_PUT) != 0) || + ((component & ShaderAttributeSetRetained.ATTRIBUTE_SET_REMOVE) != 0) || + ((component & ShaderAttributeSetRetained.ATTRIBUTE_SET_CLEAR) != 0) || + ((component & ShaderAttributeRetained.SHADER_ATTRIBUTE_VALUE_UPDATE) != 0)); + + if (spUpdate) { + /* TODO : JADA - Sole user logic is incomplete. Will disable for JavaOne */ + //if (false && (sApp.mirror.changedFrequent & component) != 0) { + if(false) { + /* + System.out.println("RenderBin : Shader sole user (SHADER_PROGRAM)" + + ra.renderMolecule.textureBin.shaderBin); + */ + + ShaderBin sBin; + + for (i = start; i < gaArr.length; i++) { + ra = gaArr[i].getRenderAtom(view); + if (ra== null || !ra.inRenderBin()) + continue; + + sBin = ra.renderMolecule.textureBin.shaderBin; + + if (sBin.componentDirty == 0) { + sBinUpdateList.add(sBin); + sBin.componentDirty |= ShaderBin.SHADER_PROGRAM_DIRTY; + } + } + } else { + /* + System.out.println("RenderBin : not soleUser (SHADER_PROGRAM)" + + ra.renderMolecule.textureBin.shaderBin); + */ + + for (i = 0; i < gaArr.length; i++) { + ra = gaArr[i].getRenderAtom(view); + if (ra== null || !ra.inRenderBin()) + continue; + + AttributeBin attrBin = ra.renderMolecule.textureBin.attributeBin; + ra.renderMolecule.removeRenderAtom(ra); + reInsertShaderBin(attrBin, ra); + } + } + } else if (sasUpdate) { + /* TODO : JADA - Sole user logic is incomplete. Will disable for JavaOne */ + //if (false && (sApp.mirror.changedFrequent & component) != 0) { + if(false) { + /* + System.out.println("RenderBin : sole user (SHADER_ATTRIBUTE_SET)" + + ra.renderMolecule.textureBin.shaderBin); + */ + + ShaderBin sBin; + + for (i = 0; i < gaArr.length; i++) { + ra = gaArr[i].getRenderAtom(view); + if (ra== null || !ra.inRenderBin()) + continue; + + + sBin = ra.renderMolecule.textureBin.shaderBin; + + if (sBin.componentDirty == 0) { + sBinUpdateList.add(sBin); + sBin.componentDirty |= ShaderBin.SHADER_ATTRIBUTE_SET_DIRTY; + } + } + } else { + /* + System.out.println("RenderBin :not soleUser (SHADER_ATTRIBUTE_SET) " + + ra.renderMolecule.textureBin.shaderBin); + */ + + for (i = 0; i < gaArr.length; i++) { + ra = gaArr[i].getRenderAtom(view); + if (ra== null || !ra.inRenderBin()) + continue; + + AttributeBin attrBin = ra.renderMolecule.textureBin.attributeBin; + ra.renderMolecule.removeRenderAtom(ra); + reInsertShaderBin(attrBin, ra); + } + } + } + } + + } + void processFogChanged(Object[] args) { FogRetained fog = (FogRetained)args[0]; @@ -2464,7 +2613,7 @@ class RenderBin extends J3dStructure implements ObjectUpdate { if ((component & TEXTURE_STATE_CHANGED) != 0) { - if (((app.changedFrequent & TEXTURE_STATE_CHANGED) != 0) && + if (((app.mirror.changedFrequent & TEXTURE_STATE_CHANGED) != 0) && ((ra.renderMolecule.textureBin.tbFlag & TextureBin.SOLE_USER) != 0)) { @@ -2501,8 +2650,8 @@ System.out.println("renderbin. texture state changed tb not sole user " + System.out.println("......tb.soleUser= " + ((ra.renderMolecule.textureBin.tbFlag & TextureBin.SOLE_USER) != 0) + - " app.changedFrequent= " + - ((app.changedFrequent & TEXTURE_STATE_CHANGED) != 0)); + " app.mirror.changedFrequent= " + + ((app.mirror.changedFrequent & TEXTURE_STATE_CHANGED) != 0)); */ @@ -2510,9 +2659,9 @@ System.out.println("......tb.soleUser= " + ra = gaArr[i].getRenderAtom(view); if (ra== null || !ra.inRenderBin()) continue; - AttributeBin ab = ra.renderMolecule.textureBin.attributeBin; + ShaderBin sb = ra.renderMolecule.textureBin.shaderBin; ra.renderMolecule.removeRenderAtom(ra); - reInsertTextureBin(ab, ra); + reInsertTextureBin(sb, ra); } } } else if ((component & AppearanceRetained.RENDERING) != 0) { @@ -2551,7 +2700,7 @@ System.out.println("......tb.soleUser= " + ra = gaArr[i].getRenderAtom(view); if (ra== null || !ra.inRenderBin()) continue; - EnvironmentSet e = ra.renderMolecule.textureBin.attributeBin.environmentSet; + EnvironmentSet e = ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } @@ -2656,7 +2805,7 @@ System.out.println("......tb.soleUser= " + Object[] users = (Object[])(args[3]); int i; - // TODO: Handle other object affected by bounding leaf changes + // XXXX: Handle other object affected by bounding leaf changes for (i = 0; i < users.length; i++) { LeafRetained leaf = (LeafRetained)users[i]; switch(leaf.nodeType) { @@ -2725,7 +2874,7 @@ System.out.println("......tb.soleUser= " + continue; } ra.app = ra.geometryAtom.source.appearance; - e = ra.renderMolecule.textureBin.attributeBin.environmentSet; + e = ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } @@ -2740,7 +2889,7 @@ System.out.println("......tb.soleUser= " + if (ra.app == ra.geometryAtom.source.otherAppearance) continue; ra.app = ra.geometryAtom.source.appearance; - e = ra.renderMolecule.textureBin.attributeBin.environmentSet; + e = ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } @@ -2793,7 +2942,7 @@ System.out.println("......tb.soleUser= " + app = saveApp; } ra.app = app; - e = ra.renderMolecule.textureBin.attributeBin.environmentSet; + e = ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } @@ -2860,7 +3009,7 @@ System.out.println("......tb.soleUser= " + continue; } ra.app = ra.geometryAtom.source.appearance; - e = ra.renderMolecule.textureBin.attributeBin.environmentSet; + e = ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } @@ -2875,7 +3024,7 @@ System.out.println("......tb.soleUser= " + if (ra.app == ra.geometryAtom.source.otherAppearance) continue; ra.app = ra.geometryAtom.source.appearance; - e = ra.renderMolecule.textureBin.attributeBin.environmentSet; + e = ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } @@ -2926,7 +3075,7 @@ System.out.println("......tb.soleUser= " + app = saveApp; } ra.app = app; - e = ra.renderMolecule.textureBin.attributeBin.environmentSet; + e = ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } @@ -3243,7 +3392,7 @@ System.out.println("......tb.soleUser= " + } } - void processText3DTransformChanged(Object[] list, + private void processText3DTransformChanged(Object[] list, Object[] transforms, long referenceTime) { int i, j, numShapes; @@ -3290,7 +3439,7 @@ System.out.println("......tb.soleUser= " + } - void processOrderedGroupRemoved(J3dMessage m) { + private void processOrderedGroupRemoved(J3dMessage m) { int i, n; Object[] ogList = (Object[])m.args[0]; Object[] ogChildIdList = (Object[])m.args[1]; @@ -3329,7 +3478,7 @@ System.out.println("......tb.soleUser= " + } - void processOrderedGroupInserted(J3dMessage m) { + private void processOrderedGroupInserted(J3dMessage m) { Object[] ogList = (Object[])m.args[0]; Object[] ogChildIdList = (Object[])m.args[1]; Object[] ogOrderedIdList = (Object[])m.args[2]; @@ -3368,7 +3517,7 @@ System.out.println("......tb.soleUser= " + } } - void processTransformChanged(long referenceTime) { + private void processTransformChanged(long referenceTime) { int i, j, k, numRenderMolecules, n; Shape3DRetained s; RenderMolecule rm; @@ -3435,8 +3584,7 @@ System.out.println("......tb.soleUser= " + else { app = ra.geometryAtom.source.appearance; } - // TODO: Should we do a more extensive equals - // app? + // XXXX: Should we do a more extensive equals app? if (ra.envSet.equals(ra, lights, fog, modelClip) && app == ra.app) { @@ -3614,7 +3762,7 @@ System.out.println("......tb.soleUser= " + /** * This processes a LIGHT change. */ - void processLightChanged() { + private void processLightChanged() { int i, j, k, l, n; LightRetained lt; EnvironmentSet e; @@ -3785,7 +3933,7 @@ System.out.println("......tb.soleUser= " + - void processBgGeometryAtoms(GeometryAtom[] nodes, long referenceTime) { + private void processBgGeometryAtoms(GeometryAtom[] nodes, long referenceTime) { int i; GeometryAtom ga; RenderAtom renderAtom; @@ -3826,7 +3974,7 @@ System.out.println("......tb.soleUser= " + * This method looks through the list of RenderAtoms to see if * compaction is needed. */ - void checkForCompaction() { + private void checkForCompaction() { int i, numRas; int numDead = 0; int numAlive = 0; @@ -3879,7 +4027,7 @@ System.out.println("......tb.soleUser= " + } - void reEvaluateAlternateAppearance() { + private void reEvaluateAlternateAppearance() { AppearanceRetained app; EnvironmentSet e; Object[] retVal; @@ -3924,7 +4072,7 @@ System.out.println("......tb.soleUser= " + } - void reEvaluateAllRenderAtoms(boolean altAppDirty) { + private void reEvaluateAllRenderAtoms(boolean altAppDirty) { int sz = renderAtoms.size(); @@ -3966,7 +4114,7 @@ System.out.println("......tb.soleUser= " + // If the lights/fog/model_clip of the render atom is the same // as the old set of lights/fog/model_clip, then move on to the // next renderAtom - // TODO: Should app test for equivalent? + // XXXX: Should app test for equivalent? if (ra.envSet.equals(ra, lights, newfog, newModelClip) && app == ra.app) continue; @@ -3996,7 +4144,7 @@ System.out.println("......tb.soleUser= " + - void getNewEnvironment(RenderAtom ra, LightRetained[] lights, + private void getNewEnvironment(RenderAtom ra, LightRetained[] lights, FogRetained fog, ModelClipRetained modelClip, AppearanceRetained app) { @@ -4176,28 +4324,36 @@ System.out.println("......tb.soleUser= " + reInsertAttributeBin(eNew, ra); } - void reInsertAttributeBin(EnvironmentSet e, RenderAtom ra) { + + private void reInsertAttributeBin(EnvironmentSet e, RenderAtom ra) { AttributeBin ab; // Just go up to the environment and re-insert ab = findAttributeBin(e, ra); - reInsertTextureBin(ab, ra); + reInsertShaderBin(ab, ra); } + private void reInsertShaderBin(AttributeBin ab, RenderAtom ra) { + ShaderBin sb; + + // System.out.println("RenderBin.reInsertShaderBin() ra= " + ra); + sb = findShaderBin(ab, ra); + reInsertTextureBin(sb, ra); + } - void reInsertTextureBin(AttributeBin ab, RenderAtom ra) { + private void reInsertTextureBin(ShaderBin sb, RenderAtom ra) { TextureBin tb; - tb = findTextureBin(ab, ra); + tb = findTextureBin(sb, ra); reInsertRenderAtom(tb, ra); } - void reInsertRenderAtom(TextureBin tb, RenderAtom ra) { + private void reInsertRenderAtom(TextureBin tb, RenderAtom ra) { RenderMolecule newRm; // Just go up to the texture bin and re-insert newRm = findRenderMolecule(tb, ra); } - void computeViewFrustumBBox(BoundingBox viewFrustumBBox) { + private void computeViewFrustumBBox(BoundingBox viewFrustumBBox) { //Initial view frustumBBox BBox viewFrustumBBox.lower.x = Float.POSITIVE_INFINITY; viewFrustumBBox.lower.y = Float.POSITIVE_INFINITY; @@ -4241,10 +4397,11 @@ System.out.println("......tb.soleUser= " + /** * This inserts a RenderAtom into the appropriate bin. */ - RenderMolecule insertRenderAtom(RenderAtom ra) { + private RenderMolecule insertRenderAtom(RenderAtom ra) { LightBin lightBin; EnvironmentSet environmentSet; AttributeBin attributeBin; + ShaderBin shaderBin; TextureBin textureBin; RenderMolecule renderMolecule; OrderedCollection oc; @@ -4301,7 +4458,11 @@ System.out.println("......tb.soleUser= " + // determined environmentSet = findEnvironmentSet(ra); attributeBin = findAttributeBin(environmentSet, ra); - textureBin = findTextureBin(attributeBin, ra); + + // System.out.println("RenderBin : findShaderBin()"); + shaderBin = findShaderBin(attributeBin, ra); + + textureBin = findTextureBin(shaderBin, ra); renderMolecule = findRenderMolecule(textureBin, ra); ra.setRenderBin(true); renderAtoms.add(ra); @@ -4347,7 +4508,7 @@ System.out.println("......tb.soleUser= " + return (renderMolecule); } - OrderedCollection findOrderedCollection(GeometryAtom ga, + private OrderedCollection findOrderedCollection(GeometryAtom ga, boolean doBackground) { int i, n; int oi; // an id which identifies a children of the orderedGroup @@ -4509,7 +4670,7 @@ System.out.println("......tb.soleUser= " + return (oc); } - void removeOrderedHeadLightBin(LightBin lightBin) { + private void removeOrderedHeadLightBin(LightBin lightBin) { int i, k; int oi; // an id which identifies a children of the orderedGroup int ci; // child index of the ordered group @@ -4541,7 +4702,7 @@ System.out.println("......tb.soleUser= " + * This gets a new EnviornmentSet. It creates one if there are none * on the freelist. */ - EnvironmentSet getEnvironmentSet(RenderAtom ra, LightRetained[] lights, + private EnvironmentSet getEnvironmentSet(RenderAtom ra, LightRetained[] lights, FogRetained fog, ModelClipRetained modelClip) { EnvironmentSet envSet; @@ -4554,10 +4715,11 @@ System.out.println("......tb.soleUser= " + } return (envSet); } + /** * This finds or creates an AttributeBin for a given RenderAtom. */ - AttributeBin findAttributeBin(EnvironmentSet envSet, RenderAtom ra) { + private AttributeBin findAttributeBin(EnvironmentSet envSet, RenderAtom ra) { int i; AttributeBin currentBin; RenderingAttributesRetained renderingAttributes; @@ -4566,7 +4728,6 @@ System.out.println("......tb.soleUser= " + } else { renderingAttributes = ra.app.renderingAttributes; } - currentBin = envSet.attributeBinList; while (currentBin != null) { @@ -4575,7 +4736,6 @@ System.out.println("......tb.soleUser= " + } currentBin = currentBin.next; } - // Check the "to-be-added" list of attributeBins for a match for (i = 0; i < envSet.addAttributeBins.size(); i++) { currentBin = (AttributeBin)envSet.addAttributeBins.get(i); @@ -4583,59 +4743,88 @@ System.out.println("......tb.soleUser= " + return(currentBin); } } - currentBin = getAttributeBin(ra.app, renderingAttributes); envSet.addAttributeBin(currentBin, this); return(currentBin); } /** - * This finds or creates a TextureBin for a given RenderAtom. + * This finds or creates an ShaderBin for a given RenderAtom. */ - TextureBin findTextureBin(AttributeBin attributeBin, RenderAtom ra) { + private ShaderBin findShaderBin(AttributeBin attributeBin, RenderAtom ra) { + int i, size; + ShaderBin currentBin; + ShaderAppearanceRetained sApp; + if((ra != null) && (ra.app instanceof ShaderAppearanceRetained)) + sApp = (ShaderAppearanceRetained)ra.app; + else + sApp = null; - int i; + currentBin = attributeBin.shaderBinList; + while (currentBin != null) { + if (currentBin.equals(sApp)) { + return currentBin; + } + currentBin = currentBin.next; + } + + // Check the "to-be-added" list of shaderBins for a match + size = attributeBin.addShaderBins.size(); + for (i = 0; i < size; i++) { + currentBin = (ShaderBin)attributeBin.addShaderBins.get(i); + if (currentBin.equals(sApp)) { + return currentBin; + } + } + + currentBin = getShaderBin(sApp); + attributeBin.addShaderBin(currentBin, this, sApp); + return currentBin; + } + + /** + * This finds or creates a TextureBin for a given RenderAtom. + */ + private TextureBin findTextureBin(ShaderBin shaderBin, RenderAtom ra) { + int i, size; TextureBin currentBin; TextureRetained texture; TextureUnitStateRetained texUnitState[]; - RenderingAttributesRetained rAttrs = - (ra.geometryAtom.source.appearance == null)? null: - ra.geometryAtom.source.appearance.renderingAttributes; - if (ra.app == null) { texUnitState = null; } else { texUnitState = ra.app.texUnitState; } - currentBin = attributeBin.textureBinList; + currentBin = shaderBin.textureBinList; while (currentBin != null) { if (currentBin.equals(texUnitState, ra)) { - //System.out.println("1: Equal"); + //System.out.println("1: Equal"); return(currentBin); } currentBin = currentBin.next; } // Check the "to-be-added" list of TextureBins for a match - for (i = 0; i < attributeBin.addTBs.size(); i++) { - currentBin = (TextureBin)attributeBin.addTBs.get(i); + size = shaderBin.addTextureBins.size(); + for (i = 0; i < size; i++) { + currentBin = (TextureBin)shaderBin.addTextureBins.get(i); if (currentBin.equals(texUnitState, ra)) { - //System.out.println("2: Equal"); + //System.out.println("2: Equal"); return(currentBin); } } // get a new texture bin for this texture unit state currentBin = getTextureBin(texUnitState, ra.app); - attributeBin.addTextureBin(currentBin, this, ra); + shaderBin.addTextureBin(currentBin, this, ra); return(currentBin); } /** * This finds or creates a RenderMolecule for a given RenderAtom. */ - RenderMolecule findRenderMolecule(TextureBin textureBin, + private RenderMolecule findRenderMolecule(TextureBin textureBin, RenderAtom ra) { RenderMolecule currentBin; @@ -4691,7 +4880,7 @@ System.out.println("......tb.soleUser= " + ra.geometryAtom.source.localToVworld[0])) { currentBin.addRenderAtom(ra, this); - ra.envSet = ra.renderMolecule.textureBin.attributeBin.environmentSet; + ra.envSet = ra.renderMolecule.textureBin.environmentSet; // If the locale has changed for an existing renderMolecule // handle the RmlocaleToVworld return(currentBin); @@ -4731,12 +4920,26 @@ System.out.println("......tb.soleUser= " + return(currentBin); } + /** + * This gets a new ShaderBin. It creates one if there are none + * on the freelist. + */ + private ShaderBin getShaderBin(ShaderAppearanceRetained sApp) { + ShaderBin shaderBin; + if (shaderBinFreelist.size() > 0) { + shaderBin = (ShaderBin)shaderBinFreelist.remove(shaderBinFreelist.size()-1); + shaderBin.reset(sApp, this); + } else { + shaderBin = new ShaderBin( sApp, this); + } + return (shaderBin); + } /** * This gets a new AttributeBin. It creates one if there are none * on the freelist. */ - AttributeBin getAttributeBin(AppearanceRetained app, RenderingAttributesRetained ra) { + private AttributeBin getAttributeBin(AppearanceRetained app, RenderingAttributesRetained ra) { AttributeBin attrBin; if (attrBinFreelist.size() > 0) { attrBin = (AttributeBin)attrBinFreelist.remove( @@ -4754,7 +4957,7 @@ System.out.println("......tb.soleUser= " + * This gets a new LightBin. It creates one if there are none * on the freelist. */ - LightBin getLightBin(int maxLights, BackgroundRetained bg, boolean inOpaque) { + private LightBin getLightBin(int maxLights, BackgroundRetained bg, boolean inOpaque) { LightBin lightBin; if (lightBinFreelist.size() > 0) { @@ -4772,7 +4975,7 @@ System.out.println("......tb.soleUser= " + * This gets a new TextureBin. It creates one if there are none * on the freelist. */ - TextureBin getTextureBin(TextureUnitStateRetained texUnitState[], + private TextureBin getTextureBin(TextureUnitStateRetained texUnitState[], AppearanceRetained app) { TextureBin textureBin; @@ -4791,7 +4994,7 @@ System.out.println("......tb.soleUser= " + * This gets a new RenderMolecule. It creates one if there are none * on the freelist. */ - RenderMolecule getRenderMolecule(GeometryAtom ga, + private RenderMolecule getRenderMolecule(GeometryAtom ga, PolygonAttributesRetained polya, LineAttributesRetained linea, PointAttributesRetained pointa, @@ -4823,7 +5026,7 @@ System.out.println("......tb.soleUser= " + * This finds or creates an EnviornmentSet for a given RenderAtom. * This also deals with empty LightBin lists. */ - EnvironmentSet findEnvironmentSet(RenderAtom ra) { + private EnvironmentSet findEnvironmentSet(RenderAtom ra) { LightBin currentBin, lightBin ; EnvironmentSet currentEnvSet, newBin; int i; @@ -5040,9 +5243,9 @@ System.out.println("......tb.soleUser= " + */ void renderOpaque(Canvas3D cv) { LightBin currentBin = opaqueBin; - // System.out.println("========> renderOpaque"); + //System.out.println("========> renderOpaque"); while (currentBin != null) { - // System.out.println("====> rendering Opaque Bin "); + //System.out.println("====> rendering Opaque Bin "); currentBin.render(cv); currentBin = currentBin.next; } @@ -5055,9 +5258,10 @@ System.out.println("......tb.soleUser= " + void renderTransparent(Canvas3D cv) { boolean savedDepthBufferWriteEnable = true; + //System.out.println("====> renderTransparent"); TransparentRenderingInfo tinfo = transparentInfo; if (tinfo != null) { - // System.out.println("====> rendering transparent Bin"); + //System.out.println("====> rendering transparent Bin"); if (cv.view.depthBufferFreezeTransparent) { cv.setDepthBufferWriteEnableOverride(true); @@ -5110,9 +5314,7 @@ System.out.println("......tb.soleUser= " + OrderedCollection oc; boolean depthBufferEnable = true; OrderedGroupRetained og = orderedBin.source; - boolean isDecal = (og instanceof DecalGroupRetained) && - ((cv.extensionsSupported & Canvas3D.STENCIL_BUFFER) != 0); - + boolean isDecal = (og instanceof DecalGroupRetained) && cv.systemStencilAvailable; int size = orderedBin.orderedCollections.size(); // System.out.println("RB : orderedBin.orderedCollections.size() " + size); @@ -5198,9 +5400,14 @@ System.out.println("......tb.soleUser= " + Canvas3D canvases[] = view.getCanvases(); for (int i=0; i< canvases.length; i++) { Canvas3D canvas = canvases[i]; - if(cvDirty) - canvas.cvDirtyMask |= Canvas3D.BACKGROUND_DIRTY; - canvas.cvDirtyMask |= Canvas3D.BACKGROUND_IMAGE_DIRTY; + synchronized (canvas.dirtyMaskLock) { + if(cvDirty) { + canvas.cvDirtyMask[0] |= Canvas3D.BACKGROUND_DIRTY; + canvas.cvDirtyMask[1] |= Canvas3D.BACKGROUND_DIRTY; + } + canvas.cvDirtyMask[0] |= Canvas3D.BACKGROUND_IMAGE_DIRTY; + canvas.cvDirtyMask[1] |= Canvas3D.BACKGROUND_IMAGE_DIRTY; + } } } @@ -5801,6 +6008,7 @@ System.out.println("......tb.soleUser= " + lightBinFreelist.clear(); envSetFreelist.clear(); attrBinFreelist.clear(); + shaderBinFreelist.clear(); textureBinFreelist.clear(); renderMoleculeFreelist.clear(); @@ -5848,22 +6056,26 @@ System.out.println("......tb.soleUser= " + AttributeBin abin = envSet.attributeBinList; while (abin != null) { System.out.println(" ABin = "+abin); - TextureBin tbin = abin.textureBinList; - while (tbin != null) { - System.out.println(" Tbin = "+tbin); - RenderMolecule rm = tbin.opaqueRMList; - System.out.println("===> Begin Dumping OpaqueBin"); - dumpRM(rm); - System.out.println("===> End Dumping OpaqueBin"); - rm = tbin.transparentRMList; - System.out.println("===> Begin Dumping transparentBin"); - dumpRM(rm); - System.out.println("===> End Dumping transparentBin"); - tbin = tbin.next; + ShaderBin sbin = abin.shaderBinList; + while (sbin != null) { + System.out.println(" SBin = "+sbin); + TextureBin tbin = sbin.textureBinList; + while (tbin != null) { + System.out.println(" Tbin = "+tbin); + RenderMolecule rm = tbin.opaqueRMList; + System.out.println("===> Begin Dumping OpaqueBin"); + dumpRM(rm); + System.out.println("===> End Dumping OpaqueBin"); + rm = tbin.transparentRMList; + System.out.println("===> Begin Dumping transparentBin"); + dumpRM(rm); + System.out.println("===> End Dumping transparentBin"); + tbin = tbin.next; + } + sbin = sbin.next; } abin = abin.next; } - envSet = envSet.next; } obin = obin.next; @@ -5914,7 +6126,7 @@ System.out.println("......tb.soleUser= " + // System.out.println("&&&&&&&&&&&&removeTransparentObject r = "+obj); if (obj instanceof TextureBin) { TextureBin tb = (TextureBin) obj; - if (tb.attributeBin.environmentSet.lightBin.geometryBackground != null) { + if (tb.environmentSet.lightBin.geometryBackground != null) { TransparentRenderingInfo t = tb.parentTInfo; // Remove the element from the transparentInfo struct @@ -6018,7 +6230,7 @@ System.out.println("......tb.soleUser= " + if (obj instanceof TextureBin) { TextureBin tb = (TextureBin) obj; // Background geometry - if (tb.attributeBin.environmentSet.lightBin.geometryBackground != null) { + if (tb.environmentSet.lightBin.geometryBackground != null) { bgTransparentInfo = computeDirtyAcrossTransparentBins(tb, bgTransparentInfo); } else { @@ -6063,8 +6275,8 @@ System.out.println("......tb.soleUser= " + TransparentRenderingInfo computeDirtyAcrossTransparentBins(TextureBin tb, TransparentRenderingInfo startinfo) { TransparentRenderingInfo tinfo = getTransparentInfo(); /* - tinfo.lightBin = tb.attributeBin.environmentSet.lightBin; - tinfo.envSet = tb.attributeBin.environmentSet; + tinfo.lightBin = tb.environmentSet.lightBin; + tinfo.envSet = tb.environmentSet; tinfo.aBin = tb.attributeBin; */ tinfo.rm = tb.transparentRMList; @@ -6257,7 +6469,16 @@ System.out.println("......tb.soleUser= " + zval1 = input1.zVal; zval2 = input2.zVal; // Put the newList before the current one - if (zval2 > zval1) { + +// System.out.print("Code path 1 "); +// if (transparencySortComparator!=null) +// if (zval2 > zval1 && (transparencySortComparator.compare(input2, input1)>0)) +// System.out.println("PASS"); +// else +// System.out.println("FAIL"); + + if ((transparencySortComparator==null && zval2 > zval1) || + (transparencySortComparator!=null && (transparencySortComparator.compare(input2, input1)>0))){ // System.out.println("===> path1"); if (input1.prev == null) { input1.prev = input2; @@ -6293,38 +6514,48 @@ System.out.println("......tb.soleUser= " + return oldList; } - void insertDepthSort(RenderAtom r) { - TransparentRenderingInfo tinfo = null; - // System.out.println("&&&&&&&&insertDepthSort"); - for (int i = 0; i < r.rListInfo.length; i++) { - if (r.parentTInfo[i] == null) - continue; - - if (transparentInfo == null) { - transparentInfo = r.parentTInfo[i]; - transparentInfo.prev = null; - transparentInfo.next = null; - } - else { - tinfo = transparentInfo; - TransparentRenderingInfo prevInfo = transparentInfo; - while (tinfo != null&& r.parentTInfo[i].zVal < tinfo.zVal) { - prevInfo = tinfo; - tinfo = tinfo.next; - } - r.parentTInfo[i].prev = prevInfo; - if (prevInfo.next != null) { - prevInfo.next.prev = r.parentTInfo[i]; - } - r.parentTInfo[i].next = prevInfo.next; - prevInfo.next = r.parentTInfo[i]; - - } - - } - } - - +// void insertDepthSort(RenderAtom r) { +// TransparentRenderingInfo tinfo = null; +// // System.out.println("&&&&&&&&insertDepthSort"); +// for (int i = 0; i < r.rListInfo.length; i++) { +// if (r.parentTInfo[i] == null) +// continue; +// +// if (transparentInfo == null) { +// transparentInfo = r.parentTInfo[i]; +// transparentInfo.prev = null; +// transparentInfo.next = null; +// } +// else { +// tinfo = transparentInfo; +// TransparentRenderingInfo prevInfo = transparentInfo; +// if (transparencySortComparator==null) +// while (tinfo != null && r.parentTInfo[i].zVal < tinfo.zVal) { +// prevInfo = tinfo; +// tinfo = tinfo.next; +// } +// else { +// System.out.println("Code Path 2 "); +// if (tinfo!=null && (transparencySortComparator.compare(r.parentTInfo[i], tinfo)<0)==r.parentTInfo[i].zVal < tinfo.zVal) +// System.out.println("PASS"); +// else +// System.out.println("FAIL"); +// while (tinfo != null && transparencySortComparator.compare(r.parentTInfo[i], tinfo)<0) { +// prevInfo = tinfo; +// tinfo = tinfo.next; +// } +// } +// r.parentTInfo[i].prev = prevInfo; +// if (prevInfo.next != null) { +// prevInfo.next.prev = r.parentTInfo[i]; +// } +// r.parentTInfo[i].next = prevInfo.next; +// prevInfo.next = r.parentTInfo[i]; +// +// } +// +// } +// } TransparentRenderingInfo collectDirtyTRInfo( TransparentRenderingInfo dirtyList, RenderAtom r) { @@ -6371,6 +6602,7 @@ System.out.println("......tb.soleUser= " + TransparentRenderingInfo depthSortAll(TransparentRenderingInfo startinfo) { + transparencySortComparator = com.sun.j3d.utils.scenegraph.transparency.TransparencySortController.getComparator(view); TransparentRenderingInfo tinfo, previnfo, nextinfo; double curZ; // System.out.println("&&&&&&&&&&&depthSortAll"); @@ -6390,10 +6622,21 @@ System.out.println("......tb.soleUser= " + previnfo = tinfo.prev; // Find the correct location for tinfo - while (previnfo != null && previnfo.zVal < curZ) { - previnfo = previnfo.prev; - - } + if (transparencySortComparator==null) { + while (previnfo != null && previnfo.zVal < curZ) { + previnfo = previnfo.prev; + } + } else { +// System.out.println("Code Path 3 "); +// if (tinfo!=null && (transparencySortComparator.compare(previnfo, tinfo)<0)==previnfo.zVal < curZ) +// System.out.println("PASS"); +// else +// System.out.println("FAIL"); + while (previnfo != null && transparencySortComparator.compare(previnfo,tinfo)<0) { + previnfo = previnfo.prev; + } + } + if (tinfo.prev != previnfo) { if (previnfo == null) { if (tinfo.next != null) { @@ -6764,7 +7007,7 @@ System.out.println("......tb.soleUser= " + // context creation bits for this canvas, but don't do anything // with the geo's user list. if (geo.dlistId > 0) { - // TODO: for the shared ctx case, we really should + // XXXX: for the shared ctx case, we really should // only free the display lists if this is the last // Canvas in the renderer. However, since the // display lists will be recreated, it doesn't @@ -6936,14 +7179,14 @@ System.out.println("......tb.soleUser= " + if (ra== null || !ra.inRenderBin()) continue; - EnvironmentSet e= ra.renderMolecule.textureBin.attributeBin.environmentSet; + EnvironmentSet e= ra.renderMolecule.textureBin.environmentSet; ra.renderMolecule.removeRenderAtom(ra); reInsertAttributeBin(e, ra); } } else { - // TODO: handle texture + // XXXX: handle texture } diff --git a/src/classes/share/javax/media/j3d/RenderMolecule.java b/src/classes/share/javax/media/j3d/RenderMolecule.java index d52cd93..61672cf 100644 --- a/src/classes/share/javax/media/j3d/RenderMolecule.java +++ b/src/classes/share/javax/media/j3d/RenderMolecule.java @@ -45,7 +45,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen AppearanceRetained.TRANSPARENCY| AppearanceRetained.COLOR); - // TODO: use definingMaterial etc. instead of these + // XXXX: use definingMaterial etc. instead of these // when sole user is completely implement PolygonAttributesRetained polygonAttributes = null; LineAttributesRetained lineAttributes = null; @@ -740,7 +740,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen k++; } - // TODO: Add tags + // XXXX: Add tags switch (ga.geoType) { case GeometryRetained.GEO_TYPE_POINT_SET: case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET: @@ -788,7 +788,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen return (false); } /* - // TODO : Check this + // XXXX : Check this if (useDisplayList && (ga.geometry.isEditable || ga.geometry.refCount > 1 || @@ -811,7 +811,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen return (false); } - // TODO: Its is necessary to have same vformat for dl, + // XXXX: Its is necessary to have same vformat for dl, // Howabout iteration, should we have 2 vformats in rm? if (geo instanceof GeometryArrayRetained) { GeometryArrayRetained gr = (GeometryArrayRetained)geo; @@ -845,7 +845,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen return (false); } } else { - //TODO: compare isEditable + //XXXX: compare isEditable if (this.vertexFormat != -1) { return (false); } @@ -1143,7 +1143,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen renderBin.orientedRAs.remove(renderBin.orientedRAs.indexOf(r)); } - if ((textureBin.attributeBin.environmentSet.lightBin.geometryBackground == null) && + if ((textureBin.environmentSet.lightBin.geometryBackground == null) && !isOpaqueOrInOG && renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) { renderBin.removeTransparentObject(r); } @@ -1318,7 +1318,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } // If transparent and not in bg geometry and is depth sorted transparency - if (!isOpaqueOrInOG && (textureBin.attributeBin.environmentSet.lightBin.geometryBackground == null)&& + if (!isOpaqueOrInOG && (textureBin.environmentSet.lightBin.geometryBackground == null)&& (renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY)) { GeometryRetained geo = null; int k = 0; @@ -1401,36 +1401,11 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } boolean canBeInDisplayList(GeometryRetained geo, GeometryAtom ga) { - boolean inDL = false; - inDL = geo.canBeInDisplayList(ga.alphaEditable); - // If can not in DL, then check if all the attrs affecting - // it are infrequently changing, if yes then put it - // Exclude Morph and indexed-by-ref-use-index-coord only for now - // in displayList if OptimizeForSpace if false - - // System.out.println("inDL = "+inDL); - // System.out.println("geo.cachedChangedFrequent = "+geo.cachedChangedFrequent); - // System.out.println("inDL = "+inDL); - // System.out.println("COLOR = "+((((GeometryArrayRetained)geo).vertexFormat& - // GeometryArray.COLOR) != 0)); - // System.out.println("Before: inDL = "+inDL); - // System.out.println("VirtualUniverse.mc.buildDisplayListIfPossible = "+VirtualUniverse.mc.buildDisplayListIfPossible); - if (VirtualUniverse.mc.buildDisplayListIfPossible && - !inDL && - !(ga.source.sourceNode instanceof MorphRetained || - (geo instanceof GeometryArrayRetained && - ((((GeometryArrayRetained)geo).vertexFormat & (GeometryArray.USE_NIO_BUFFER|GeometryArray.INTERLEAVED)) ==(GeometryArray.USE_NIO_BUFFER|GeometryArray.INTERLEAVED))) || - (geo instanceof IndexedGeometryArrayRetained && - ((((IndexedGeometryArrayRetained)geo).vertexFormat & (GeometryArray.BY_REFERENCE|GeometryArray.USE_COORD_INDEX_ONLY)) == (GeometryArray.BY_REFERENCE|GeometryArray.USE_COORD_INDEX_ONLY))))) { - // Check if geometry is frequentlyEditable - boolean alphaFreqEditable = ga.source.isAlphaFrequentlyEditable(geo); - inDL = !((geo.cachedChangedFrequent != 0) || - ((!(geo instanceof GeometryArrayRetained) && alphaFreqEditable)|| - (alphaFreqEditable && ((((GeometryArrayRetained)geo).vertexFormat& - GeometryArray.COLOR) != 0)))); - } - // System.out.println("After: inDL = "+inDL); - return inDL; + if (ga.source.sourceNode instanceof MorphRetained) { + return false; + } + + return geo.canBeInDisplayList(ga.alphaEditable); } // If dlist will be altered due to alpha or ignoreVertexColors, then don't @@ -1498,7 +1473,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen RenderAtomListInfo r; int index; - renderAtom.envSet = textureBin.attributeBin.environmentSet; + renderAtom.envSet = textureBin.environmentSet; renderAtom.renderMolecule = this; renderAtom.dirtyMask &= ~RenderAtom.NEED_SEPARATE_LOCALE_VWC_BOUNDS; @@ -1732,8 +1707,6 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen void evalAlphaUsage(RenderingAttributesRetained renderAttrs, TextureUnitStateRetained[] texUnits) { - RenderingAttributesRetained ra; - TextureAttributesRetained ta; boolean alphaBlend, alphaTest, textureBlend = false; alphaBlend = @@ -1847,7 +1820,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen // we'll have to punt to vertex array as well. if ((pass != TextureBin.USE_DISPLAYLIST) || - (texCoordSetMapLen > cv.numTexCoordSupported) || + (texCoordSetMapLen > cv.maxTexCoordSets) || (VirtualUniverse.mc.isD3D() && (((definingPolygonAttributes != null) && ((isQuadGeometryArray && @@ -1862,7 +1835,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen /* System.out.println("texCoord " + texCoordSetMapLen + " " + - cv.numTexCoordSupported + " " + modeSupportDL); + cv.maxTexCoordSets + " " + modeSupportDL); System.out.println("primaryMoleculeType = "+primaryMoleculeType+" primaryRenderAtomList ="+primaryRenderAtomList+" separateDlistRenderAtomList ="+separateDlistRenderAtomList+" vertexArrayRenderAtomList ="+vertexArrayRenderAtomList); */ @@ -1934,7 +1907,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } - // TODO: In the case of independent primitives such as quads, + // XXXX: In the case of independent primitives such as quads, // it would still be better to call multi draw arrays if (vertexArrayRenderAtomList != null) { if (pass == TextureBin.USE_DISPLAYLIST) { @@ -2171,7 +2144,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen // instead. if ((pass != TextureBin.USE_DISPLAYLIST) || - (texCoordSetMapLen > cv.numTexCoordSupported) || + (texCoordSetMapLen > cv.maxTexCoordSets) || (VirtualUniverse.mc.isD3D() && (((definingPolygonAttributes != null) && ((isQuadGeometryArray && @@ -2188,7 +2161,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen // System.out.println("r.isOpaque = "+isOpaque+" rinfo = "+tinfo.rInfo+" groupType = "+tinfo.rInfo.groupType); // Only support individual dlist or varray // If this rInfo is a part of a bigger dlist, render as VA - // TODO: What to do with Text3D, Raster, CG? + // XXXX: What to do with Text3D, Raster, CG? if ((tinfo.rInfo.groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0) { RenderAtomListInfo save= tinfo.rInfo.next; // Render only one geometry @@ -2353,7 +2326,7 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen void checkEquivalenceWithLeftNeighbor(RenderMolecule rm, int dirtyBits) { boolean reload_color = reloadColor(rm); - // TODO : For now ignore the dirtyBits being sent in + // XXXX : For now ignore the dirtyBits being sent in dirtyAttrsAcrossRms = ALL_DIRTY_BITS ; @@ -2703,6 +2676,30 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } + // Issue 129: method to add or remove all rendering atoms in this + // RenderMolecule to or from the transparent info list when we are + // in depth sorted transparency mode and the RenderMolecule + // changes from opaque to transparent or vice versa. + void addRemoveTransparentObject(RenderBin renderBin, boolean add) { + addRemoveTransparentObject(renderBin, add, primaryRenderAtomList); + addRemoveTransparentObject(renderBin, add, separateDlistRenderAtomList); + addRemoveTransparentObject(renderBin, add, vertexArrayRenderAtomList); + } + + private void addRemoveTransparentObject(RenderBin renderBin, + boolean add, + RenderAtomListInfo rinfo) { + while (rinfo != null) { + if (add) { + renderBin.addTransparentObject(rinfo.renderAtom); + } + else { + renderBin.removeTransparentObject(rinfo.renderAtom); + } + rinfo = rinfo.next; + } + } + void evalMaterialCachedState() { if (definingMaterial == null) { enableLighting = false;; @@ -3118,7 +3115,3 @@ class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponen } } } - - - - diff --git a/src/classes/share/javax/media/j3d/Renderer.java b/src/classes/share/javax/media/j3d/Renderer.java index 4f52a06..bb61822 100644 --- a/src/classes/share/javax/media/j3d/Renderer.java +++ b/src/classes/share/javax/media/j3d/Renderer.java @@ -96,6 +96,8 @@ class Renderer extends J3dThread { // an unique bit to identify this renderer int rendererBit = 0; + // an unique number to identify this renderer : ( rendererBit = 1 << rendererId) + int rendererId = 0; // List of renderMolecules that are dirty due to additions // or removal of renderAtoms from their display list set @@ -117,10 +119,6 @@ class Renderer extends J3dThread { ArrayList textureReloadList = new ArrayList(); - // This is a local copy of canvas view cache. It is used as a data storage for the - // renderer. Note: This isn't the "real" canvasViewCache references by the Canvas. - CanvasViewCache copyOfCvCache = new CanvasViewCache(null, null, null); - J3dMessage[] renderMessage; // The screen for this Renderer. Note that this renderer may share @@ -178,7 +176,8 @@ class Renderer extends J3dThread { setName("J3D-Renderer-" + getInstanceNum()); type = J3dThread.RENDER_THREAD; - rendererBit = VirtualUniverse.mc.getRendererBit(); + rendererId = VirtualUniverse.mc.getRendererId(); + rendererBit = (1 << rendererId); renderMessage = new J3dMessage[1]; } @@ -391,7 +390,25 @@ class Renderer extends J3dThread { c.doubleBufferAvailable = nct.hasDoubleBuffer(c); c.stereoAvailable = nct.hasStereo(c); } - c.sceneAntialiasingMultiSamplesAvailable = + + // Setup stencil related variables. + c.actualStencilSize = nct.getStencilSize(c); + boolean userOwnsStencil = c.requestedStencilSize > 0; + + c.userStencilAvailable = + (userOwnsStencil && (c.actualStencilSize > 0)); + c.systemStencilAvailable = + (!userOwnsStencil && (c.actualStencilSize > 0)); + + /* + System.out.println("Renderer :check for nct configuration"); + System.out.println("-- userStencilAvailable " + + c.userStencilAvailable); + System.out.println("-- systemStencilAvailable " + + c.systemStencilAvailable); + */ + + c.sceneAntialiasingMultiSamplesAvailable = nct.hasSceneAntialiasingMultisample(c); if (c.sceneAntialiasingMultiSamplesAvailable) { @@ -667,13 +684,7 @@ class Renderer extends J3dThread { } synchronized (VirtualUniverse.mc.contextCreationLock) { - sharedCtx = - canvas.createNewContext(canvas.screen.display, - canvas.window, - canvas.vid, - canvas.fbConfig, - 0, true, - canvas.offScreen); + sharedCtx = canvas.createNewContext(0, true); if (sharedCtx == 0) { canvas.drawingSurfaceObject.unLock(); if ((offBufRetained != null) && @@ -706,15 +717,9 @@ class Renderer extends J3dThread { } synchronized (VirtualUniverse.mc.contextCreationLock) { - canvas.ctx = - canvas.createNewContext(canvas.screen.display, - canvas.window, canvas.vid, - canvas.fbConfig, sharedCtx, - false, canvas.offScreen); - - + canvas.ctx = canvas.createNewContext(sharedCtx, false); - if (canvas.ctx == 0) { + if (canvas.ctx == 0) { canvas.drawingSurfaceObject.unLock(); if ((offBufRetained != null) && offBufRetained.isByReference()) { @@ -737,56 +742,29 @@ class Renderer extends J3dThread { NodeComponentRetained nc = (NodeComponentRetained)renderBin.nodeComponentList.get(i); nc.evaluateExtensions(canvas.extensionsSupported); } - } - - - // query for the number of texture units supported - if (canvas.multiTexAccelerated) { - canvas.numTexUnitSupported = - canvas.getTextureUnitCount(canvas.ctx); - if (VirtualUniverse.mc.textureUnitMax < canvas.numTexUnitSupported) { - canvas.numTexUnitSupported = VirtualUniverse.mc.textureUnitMax; - } - } + } - // enable separate specular color + // enable separate specular color canvas.enableSeparateSpecularColor(); - } + // create the cache texture state in canvas + // for state download checking purpose + if (canvas.texUnitState == null) { + canvas.createTexUnitState(); + } - // create the cache texture state in canvas - // for state download checking purpose - - if (canvas.texUnitState == null) { - canvas.texUnitState = - new TextureUnitStateRetained[ - canvas.numTexCoordSupported]; - for (int t = 0; t < canvas.numTexCoordSupported; - t++) { - canvas.texUnitState[t] = - new TextureUnitStateRetained(); - canvas.texUnitState[t].texture = null; - canvas.texUnitState[t].mirror = null; - } - } - + // Create the texture unit state map + if (canvas.texUnitStateMap == null) { + canvas.createTexUnitStateMap(); + } - // also create the texture unit state map - // which is a mapping from texture unit state to - // the actual underlying texture unit + canvas.resetImmediateRendering(Canvas3D.NOCHANGE); + canvas.drawingSurfaceObject.contextValidated(); - if (canvas.texUnitStateMap == null) { - canvas.texUnitStateMap = - new int[canvas.numTexCoordSupported]; - } - - canvas.resetImmediateRendering(Canvas3D.NOCHANGE); - canvas.drawingSurfaceObject.contextValidated(); - - if (!canvas.useSharedCtx) { - canvas.needToRebuildDisplayList = true; - } + if (!canvas.useSharedCtx) { + canvas.needToRebuildDisplayList = true; + } canvas.drawingSurfaceObject.unLock(); } else { @@ -819,30 +797,22 @@ class Renderer extends J3dThread { // save the BACKGROUND_IMAGE_DIRTY before canvas.updateViewCache // clean it - background_image_update = - ((canvas.cvDirtyMask & Canvas3D.BACKGROUND_IMAGE_DIRTY) != 0); - - // copyOfcvCache is a copy of canvas view - // cache. It is used as a data storage for the - // renderer. Note: This isn't the "real" - // canvasViewCache references by the Canvas. - // - // Note : For performance reason, copyOfcvCache - // doesn't contain are valid canvasViewCache info., - // only data needed by the renderer are stored. - // - // The valid data are : useStereo, canvasWidth, - // canvasHeight, leftProjection, rightProjection, - // leftVpcToEc, rightVpcToEc, leftFrustumPlanes, - // rightFrustumPlanes, vpcToVworld and vworldToVpc. + synchronized (canvas.dirtyMaskLock) { + background_image_update = + ((canvas.cvDirtyMask[Canvas3D.RENDERER_DIRTY_IDX] & Canvas3D.BACKGROUND_IMAGE_DIRTY) != 0); + } if (VirtualUniverse.mc.doDsiRenderLock) { canvas.drawingSurfaceObject.unLock(); } + // Issue 109 : removed copyOfCvCache now that we have + // a separate canvasViewCache for computing view frustum + CanvasViewCache cvCache = canvas.canvasViewCache; + // Deadlock if we include updateViewCache in // drawingSurfaceObject sync. - canvas.updateViewCache(false, copyOfCvCache, null, + canvas.updateViewCache(false, null, null, renderBin.geometryBackground != null); if ((VirtualUniverse.mc.doDsiRenderLock) && @@ -856,8 +826,8 @@ class Renderer extends J3dThread { // setup viewport canvas.setViewport(canvas.ctx, 0, 0, - copyOfCvCache.getCanvasWidth(), - copyOfCvCache.getCanvasHeight()); + cvCache.getCanvasWidth(), + cvCache.getCanvasHeight()); @@ -915,7 +885,7 @@ class Renderer extends J3dThread { // stereo setup - boolean useStereo = copyOfCvCache.getUseStereo(); + boolean useStereo = cvCache.getUseStereo(); if (useStereo) { num_stereo_passes = 2; stereo_mode = Canvas3D.FIELD_LEFT; @@ -942,7 +912,7 @@ class Renderer extends J3dThread { num_accum_passes = NUM_ACCUMULATION_SAMPLES; System.arraycopy( - copyOfCvCache.getLeftProjection().mat, + cvCache.getLeftProjection().mat, 0, accumLeftProjMat, 0, 16); @@ -960,7 +930,7 @@ class Renderer extends J3dThread { if (useStereo) { System.arraycopy( - copyOfCvCache.getRightProjection().mat, + cvCache.getRightProjection().mat, 0, accumRightProjMat, 0, 16); accumRightX = accumRightProjMat[3]; accumRightY = accumRightProjMat[7]; @@ -968,13 +938,13 @@ class Renderer extends J3dThread { if (renderBin.geometryBackground != null) { System.arraycopy( - copyOfCvCache.getInfLeftProjection().mat, + cvCache.getInfLeftProjection().mat, 0, accumInfLeftProjMat, 0, 16); accumInfLeftX = accumInfLeftProjMat[3]; accumInfLeftY = accumInfLeftProjMat[7]; if (useStereo) { System.arraycopy( - copyOfCvCache.getInfRightProjection().mat, + cvCache.getInfRightProjection().mat, 0, accumInfRightProjMat, 0, 16); accumInfRightX = accumInfRightProjMat[3]; accumInfRightY = accumInfRightProjMat[7]; @@ -1044,8 +1014,8 @@ class Renderer extends J3dThread { canvas.beginScene(); // this is if the background image resizes with the canvas - int winWidth = copyOfCvCache.getCanvasWidth(); - int winHeight = copyOfCvCache.getCanvasHeight(); + int winWidth = cvCache.getCanvasWidth(); + int winHeight = cvCache.getCanvasHeight(); // clear background if not full screen antialiasing @@ -1217,7 +1187,7 @@ class Renderer extends J3dThread { // setup rendering matrices if (pass == 0) { canvas.vpcToEc = - copyOfCvCache.getInfLeftVpcToEc(); + cvCache.getInfLeftVpcToEc(); if (doAccum) { canvas.setProjectionMatrix( canvas.ctx, @@ -1225,11 +1195,11 @@ class Renderer extends J3dThread { } else { canvas.setProjectionMatrix( canvas.ctx, - copyOfCvCache.getInfLeftProjection().mat); + cvCache.getInfLeftProjection().mat); } } else { canvas.vpcToEc = - copyOfCvCache.getInfRightVpcToEc(); + cvCache.getInfRightVpcToEc(); if (doAccum) { canvas.setProjectionMatrix( canvas.ctx, @@ -1237,11 +1207,11 @@ class Renderer extends J3dThread { } else { canvas.setProjectionMatrix( canvas.ctx, - copyOfCvCache.getInfRightProjection().mat); + cvCache.getInfRightProjection().mat); } } canvas.vworldToEc.mul(canvas.vpcToEc, - copyOfCvCache.getInfVworldToVpc()); + cvCache.getInfVworldToVpc()); // render background geometry renderBin.renderBackground(canvas); @@ -1249,33 +1219,33 @@ class Renderer extends J3dThread { // setup rendering matrices if (pass == 0) { - canvas.vpcToEc = copyOfCvCache.getLeftVpcToEc(); + canvas.vpcToEc = cvCache.getLeftVpcToEc(); if (doAccum) { canvas.setProjectionMatrix( canvas.ctx, accumLeftProjMat); } else { canvas.setProjectionMatrix(canvas.ctx, - copyOfCvCache.getLeftProjection().mat); + cvCache.getLeftProjection().mat); } } else { - canvas.vpcToEc = copyOfCvCache.getRightVpcToEc(); + canvas.vpcToEc = cvCache.getRightVpcToEc(); if (doAccum) { canvas.setProjectionMatrix( canvas.ctx, accumRightProjMat); } else { canvas.setProjectionMatrix(canvas.ctx, - copyOfCvCache.getRightProjection().mat); + cvCache.getRightProjection().mat); } } canvas.vworldToEc.mul(canvas.vpcToEc, - copyOfCvCache.getVworldToVpc()); + cvCache.getVworldToVpc()); - synchronized (copyOfCvCache) { + synchronized (cvCache) { if (pass == 0) { - canvas.setFrustumPlanes(copyOfCvCache.getLeftFrustumPlanesInVworld()); + canvas.setFrustumPlanes(cvCache.getLeftFrustumPlanesInVworld()); } else { - canvas.setFrustumPlanes(copyOfCvCache.getRightFrustumPlanesInVworld()); + canvas.setFrustumPlanes(cvCache.getRightFrustumPlanesInVworld()); } } @@ -1464,7 +1434,6 @@ class Renderer extends J3dThread { dirtyDlistPerRinfoList.clear(); textureIdResourceFreeList.clear(); displayListResourceFreeList.clear(); - copyOfCvCache = new CanvasViewCache(null, null, null); onScreen = null; offScreen = null; m = null; @@ -1630,12 +1599,15 @@ class Renderer extends J3dThread { // restore current context currentCanvas.makeCtxCurrent(); } - if (texture.equals("2D")){ - VirtualUniverse.mc.freeTexture2DId(texId); - } - else if(texture.equals("3D")){ - VirtualUniverse.mc.freeTexture3DId(texId); - } + // Issue 162: TEMPORARY FIX -- don't free the texture ID, since it will + // be freed once per canvas / screen and will subsequently cause the ID + // to be used for multiple textures. +// if (texture.equals("2D")){ +// VirtualUniverse.mc.freeTexture2DId(texId); +// } +// else if(texture.equals("3D")){ +// VirtualUniverse.mc.freeTexture3DId(texId); +// } } diff --git a/src/classes/share/javax/media/j3d/RenderingAttributes.java b/src/classes/share/javax/media/j3d/RenderingAttributes.java index d3cb2be..d4c444a 100644 --- a/src/classes/share/javax/media/j3d/RenderingAttributes.java +++ b/src/classes/share/javax/media/j3d/RenderingAttributes.java @@ -16,38 +16,72 @@ package javax.media.j3d; * The RenderingAttributes object defines common rendering attributes * for all primitive types. The rendering attributes are:<p> * <ul> - * <li>Alpha test function - used to compare the alpha test value with - * each per-pixel alpha value. If the test passes, the pixel is + * <li>Depth test function - used to compare the incoming (source) depth of + * each pixel with depth of the pixel stored in frame buffer. If the test + * passes, the pixel is written, otherwise the pixel is not written. The depth test + * function is set with the <code>setDepthTestFunction</code> + * method. By default, LESS_OR_EQUAL is the function used. The depth test + * function is one of the following:</li><p> + * <ul> + * <li>ALWAYS - pixels are always drawn, irrespective of the depth + * value. This effectively disables depth testing.</li><p> + * + * <li>NEVER - pixels are never drawn, irrespective of the depth + * value.</li><p> + * + * <li>EQUAL - pixels are drawn if the incoming pixel depth is equal + * to the stored pixel depth in the frame buffer.</li><p> + * + * <li>NOT_EQUAL - pixels are drawn if the incoming pixel depth is + * not equal to the stored pixel depth in the frame buffer.</li><p> + * + * <li>LESS - pixels are drawn if the incoming pixel depth is less + * than the stored pixel depth in the frame buffer.</li><p> + * + * <li>LESS_OR_EQUAL - pixels are drawn if the incoming pixel depth + * is less than or equal to the stored pixel depth in the frame buffer. + * This is the default setting.</li><p> + * + * <li>GREATER - pixels are drawn if the incoming pixel depth is greater + * than the stored pixel depth in the frame buffer.</li><p> + * + * <li>GREATER_OR_EQUAL - pixels are drawn if the incoming pixel depth + * is greater than or equal to the stored pixel depth in the frame buffer.</li><p> + * </ul> + * + * <li>Alpha test function - used to compare the incoming (source) alpha value + * of each pixel with the alpha test value. If the test passes, the pixel is * written, otherwise the pixel is not written. The alpha test * function is set with the <code>setAlphaTestFunction</code> * method. The alpha test * function is one of the following:</li><p> * <ul> * <li>ALWAYS - pixels are always drawn, irrespective of the alpha - * value. This effectively disables alpha testing. This is - * the default setting.</li><p> + * value. This effectively disables alpha testing. + * This is the default setting.</li><p> * * <li>NEVER - pixels are never drawn, irrespective of the alpha * value.</li><p> * - * <li>EQUAL - pixels are drawn if the pixel alpha value is equal + * <li>EQUAL - pixels are drawn if the incoming pixel alpha value is equal * to the alpha test value.</li><p> * - * <li>NOT_EQUAL - pixels are drawn if the pixel alpha value is + * <li>NOT_EQUAL - pixels are drawn if the incoming pixel alpha value is * not equal to the alpha test value.</li><p> * - * <li>LESS - pixels are drawn if the pixel alpha value is less + * <li>LESS - pixels are drawn if the incoming pixel alpha value is less * than the alpha test value.</li><p> * - * <li>LESS_OR_EQUAL - pixels are drawn if the pixel alpha value + * <li>LESS_OR_EQUAL - pixels are drawn if the incoming pixel alpha value * is less than or equal to the alpha test value.</li><p> * - * <li>GREATER - pixels are drawn if the pixel alpha value is greater + * <li>GREATER - pixels are drawn if the incoming pixel alpha value is greater * than the alpha test value.</li><p> * - * <li>GREATER_OR_EQUAL - pixels are drawn if the pixel alpha + * <li>GREATER_OR_EQUAL - pixels are drawn if the incoming pixel alpha * value is greater than or equal to the alpha test value.</li><p> * </ul> + * * <li>Alpha test value - the test value used by the alpha test function. * This value is compared to the alpha value of each rendered pixel. * The alpha test value is set with the <code>setAlphaTestValue</code> @@ -59,8 +93,22 @@ package javax.media.j3d; * is enabled or disabled with the <code>setRasterOpEnable</code> * method. The raster operation is one of the following:</li><p> * <ul> + * <li>ROP_CLEAR - DST = 0.</li> + * <li>ROP_AND DST = SRC & DST.</li> + * <li>ROP_AND_REVERSE DST = SRC & ~DST.</li> * <li>ROP_COPY - DST = SRC. This is the default operation.</li> - * <li>ROP_XOR - DST = SRC ^ DST.</li><p> + * <li>ROP_AND_INVERTED - DST = ~SRC & DST.</li> + * <li>ROP_NOOP - DST = DST.</li> + * <li>ROP_XOR - DST = SRC ^ DST.</li> + * <li>ROP_OR - DST = DST | SRC.</li> + * <li>ROP_NOR - DST = ~( DST | SRC .)</li> + * <li>ROP_EQUIV - DST = ~( DST ^ SRC .)</li> + * <li>ROP_INVERT - DST = ~DST.</li> + * <li>ROP_OR_REVERSE - DST = src | ~DST.</li> + * <li>ROP_COPY_INVERTED - DST = ~SRC.</li> + * <li>ROP_OR_INVERTED - DST = ~SRC | DST.</li> + * <li>ROP_NAND - DST = ~(SRC & DST.)</li> + * <li>ROP_SET - DST = 1.</li><p> * </ul> * <li>Vertex colors - vertex colors can be ignored for this * RenderingAttributes object. This capability is set with the @@ -93,12 +141,79 @@ package javax.media.j3d; * include opaque objects or primitives rendered with * SCREEN_DOOR transparency. By default, the depth buffer * is enabled and the depth buffer write is enabled.</li><p> + * + * <li>Stencil buffer - can be enabled or disabled for this RenderingAttributes + * component object using the <code>setStencilEnable</code> method. If the + * stencil buffer is disabled, the stencil operation and function are ignored. + * If a scene graph is rendered on a Canvas3D that does not have a stencil + * buffer, the stencil buffer will be implicitly disabled for that + * canvas.</li><p> + * + * <li>Stencil write mask - mask that controls which bits of the stencil + * buffer are written when the stencil buffer is enabled. The default value is + * <code>~0</code> (all ones).</li><p> + * + * <li>Stencil operation - a set of three stencil operations performed + * when: 1) the stencil test fails; 2) the stencil test passes, but + * the depth test fails; or 3) both the stencil test and depth test pass. + * The stencil operations are set with the <code>setStencilOp</code> + * method. The stencil operation is one of the following:</li><p> + * <ul> + * <li>STENCIL_KEEP - keeps the current value (no operation performed). + * This is the default setting.</li> + * <li>STENCIL_ZERO - Sets the stencil buffer value to 0.</li> + * <li>STENCIL_REPLACE - Sets the stencil buffer value to + * <code>refValue</code>, as specified by <code>setStencilFunction</code>.</li> + * <li>STENCIL_INCR - Increments the current stencil buffer value.</li> + * <li>STENCIL_DECR - Decrements the current stencil buffer value.</li> + * <li>STENCIL_INVERT - Bitwise inverts the current stencil buffer value.</li><p> * </ul> * - * @see Appearance + * <li>Stencil test function - used to compare the stencil reference value with + * the per-pixel stencil value stored in the frame buffer. If the test passes, + * the pixel is written, otherwise the pixel is not written. The stencil + * test function, reference value, and comparison mask are set with the + * <code>setStencilFunction</code> method. The stencil comparison mask is + * bitwise-ANDed with both the stencil reference value and the stored stencil + * value prior to doing the comparison. The default value for the reference value + * is 0. The default value for the comparison mask is <code>~0</code> (all ones). + * The stencil test function is one of the following:</li><p> + * <ul> + * <li>ALWAYS - pixels are always drawn, irrespective of the stencil + * value. This effectively disables stencil testing. + * This is the default setting.</li><p> + * + * <li>NEVER - pixels are never drawn, irrespective of the stencil + * value.</li><p> + * + * <li>EQUAL - pixels are drawn if the stencil reference value is equal + * to the stored stencil value in the frame buffer.</li><p> + * + * <li>NOT_EQUAL - pixels are drawn if the stencil reference value is + * not equal to the stored stencil value in the frame buffer.</li><p> + * + * <li>LESS - pixels are drawn if the stencil reference value is less + * than the stored stencil value in the frame buffer.</li><p> * + * <li>LESS_OR_EQUAL - pixels are drawn if the stencil reference value + * is less than or equal to the stored stencil value in the frame buffer.</li><p> + * + * <li>GREATER - pixels are drawn if the stencil reference value is greater + * than the stored stencil value in the frame buffer.</li><p> + * + * <li>GREATER_OR_EQUAL - pixels are drawn if the stencil reference value + * is greater than or equal to the stored stencil value in the frame buffer.</li><p> + * </ul> + * + * </ul> + * + * <p>Note: the alpha test, depth test, and stencil functions all use + * the same enums.</p> + * + * @see Appearance */ public class RenderingAttributes extends NodeComponent { + /** * Specifies that this RenderingAttributes object * allows reading its alpha test value component information. @@ -127,6 +242,24 @@ public class RenderingAttributes extends NodeComponent { public static final int ALLOW_ALPHA_TEST_FUNCTION_WRITE = CapabilityBits.RENDERING_ATTRIBUTES_ALLOW_ALPHA_TEST_FUNCTION_WRITE; + /** + * Specifies that this RenderingAttributes object + * allows reading its depth test function component information. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_DEPTH_TEST_FUNCTION_READ = CapabilityBits.RENDERING_ATTRIBUTES_ALLOW_DEPTH_TEST_FUNCTION_READ; + + /** + * Specifies that this RenderingAttributes object + * allows writing its depth test function component information. + * + * @since Java 3D 1.4 + */ + public static final int + ALLOW_DEPTH_TEST_FUNCTION_WRITE = CapabilityBits.RENDERING_ATTRIBUTES_ALLOW_DEPTH_TEST_FUNCTION_WRITE; + /** * Specifies that this RenderingAttributes object * allows reading its depth buffer enable and depth buffer write enable @@ -200,84 +333,322 @@ public class RenderingAttributes extends NodeComponent { CapabilityBits.RENDERING_ATTRIBUTES_ALLOW_RASTER_OP_WRITE; /** - * Indicates pixels are always drawn irrespective of alpha value. - * This effectively disables alpha testing. + * Specifies that this RenderingAttributes object allows reading + * its stencil enable, stencil op, stencil function, and + * stencil write mask information. + * + * @since Java 3D 1.4 + */ + public static final int ALLOW_STENCIL_ATTRIBUTES_READ = + CapabilityBits.RENDERING_ATTRIBUTES_ALLOW_STENCIL_ATTRIBUTES_READ; + + /** + * Specifies that this RenderingAttributes object allows writing + * its stencil enable, stencil op, stencil function, and + * stencil write mask information. + * + * @since Java 3D 1.4 + */ + public static final int ALLOW_STENCIL_ATTRIBUTES_WRITE = + CapabilityBits.RENDERING_ATTRIBUTES_ALLOW_STENCIL_ATTRIBUTES_WRITE; + + + // + // Enums for alpha test, depth test, and stencil test + // + + /** + * Specifies that pixels are always drawn irrespective of the + * values being tested. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * This setting effectively disables alpha, depth, or stencil testing. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int ALWAYS = 0; /** - * Indicates pixels are never drawn irrespective of alpha value. + * Specifies that pixels are never drawn irrespective of the + * values being tested. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int NEVER = 1; /** - * Indicates pixels are drawn if pixel alpha value is equal - * to alpha test value. + * Specifies that pixels are drawn if the two values being tested are equal. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int EQUAL = 2; /** - * Indicates pixels are drawn if pixel alpha value is not equal - * to alpha test value. + * Specifies that pixels are drawn if the two values being tested are not equal. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int NOT_EQUAL = 3; /** - * Indicates pixels are drawn if pixel alpha value is less - * than alpha test value. + * Specifies that pixels are drawn if the source/reference value is less + * than the destination/test value. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int LESS = 4; /** - * Indicates pixels are drawn if pixel alpha value is less - * than or equal to alpha test value. + * Specifies that pixels are drawn if the source/reference value is less + * than or equal to the destination/test value. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int LESS_OR_EQUAL = 5; /** - * Indicates pixels are drawn if pixel alpha value is greater - * than alpha test value. + * Specifies that pixels are drawn if the source/reference value is greater + * than the destination/test value. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int GREATER = 6; /** - * Indicates pixels are drawn if pixel alpha value is greater - * than or equal to alpha test value. + * Specifies that pixels are drawn if the source/reference value is greater + * than or equal to the destination/test value. + * Can be used to specify the alpha test function, the depth test function, + * or the stencil function. + * + * @see #setAlphaTestFunction + * @see #setDepthTestFunction + * @see #setStencilFunction(int,int,int) */ public static final int GREATER_OR_EQUAL = 7; -// public static final int ROP_CLEAR = 0x0; -// public static final int ROP_AND = 0x1; -// public static final int ROP_AND_REVERSE = 0x2; + // + // Raster op enums + // + + /** + * Raster operation: <code>DST = 0</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_CLEAR = 0x0; + + /** + * Raster operation: <code>DST = SRC & DST</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_AND = 0x1; + + /** + * Raster operation: <code>DST = SRC & ~DST</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_AND_REVERSE = 0x2; /** * Raster operation: <code>DST = SRC</code>. * @see #setRasterOp + * * @since Java 3D 1.2 */ public static final int ROP_COPY = 0x3; -// public static final int ROP_AND_INVERTED = 0x4; -// public static final int ROP_NOOP = 0x5; + /** + * Raster operation: <code>DST = ~SRC & DST</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_AND_INVERTED = 0x4; + + /** + * Raster operation: <code>DST = DST</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_NOOP = 0x5; /** * Raster operation: <code>DST = SRC ^ DST</code>. * @see #setRasterOp + * * @since Java 3D 1.2 */ public static final int ROP_XOR = 0x6; -// public static final int ROP_OR = 0x7; -// public static final int ROP_NOR = 0x8; -// public static final int ROP_EQUIV = 0x9; -// public static final int ROP_INVERT = 0xA; -// public static final int ROP_OR_REVERSE = 0xB; -// public static final int ROP_COPY_INVERTED = 0xC; -// public static final int ROP_OR_INVERTED = 0xD; -// public static final int ROP_NAND = 0xE; -// public static final int ROP_SET = 0xF; + /** + * Raster operation: <code>DST = DST | SRC</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_OR = 0x7; + + /** + * Raster operation: <code>DST = ~( DST | SRC )</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_NOR = 0x8; + + /** + * Raster operation: <code>DST = ~( DST ^ SRC )</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_EQUIV = 0x9; + + /** + * Raster operation: <code>DST = ~DST</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_INVERT = 0xA; + + /** + * Raster operation: <code>DST = src | ~DST</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_OR_REVERSE = 0xB; + /** + * Raster operation: <code>DST = ~SRC</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_COPY_INVERTED = 0xC; + + /** + * Raster operation: <code>DST = ~SRC | DST</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_OR_INVERTED = 0xD; + + /** + * Raster operation: <code>DST = ~(SRC & DST)</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_NAND = 0xE; + + /** + * Raster operation: <code>DST = 1</code>. + * @see #setRasterOp + * + * @since Java 3D 1.4 + */ + public static final int ROP_SET = 0xF; + + + // + // Stencil op enums + // + + /** + * Stencil operation: <code>DST = DST</code> + * @see #setStencilOp(int,int,int) + * + * @since Java 3D 1.4 + */ + public static final int STENCIL_KEEP = 1; + + /** + * Stencil operation: <code>DST = 0</code> + * @see #setStencilOp(int,int,int) + * + * @since Java 3D 1.4 + */ + public static final int STENCIL_ZERO = 2; + + /** + * Stencil operation: <code>DST = REF</code> + * @see #setStencilOp(int,int,int) + * + * @since Java 3D 1.4 + */ + public static final int STENCIL_REPLACE = 3; + + /** + * Stencil operation: <code>DST = DST + 1</code> + * @see #setStencilOp(int,int,int) + * + * @since Java 3D 1.4 + */ + public static final int STENCIL_INCR = 4; + + /** + * Stencil operation: <code>DST = DST - 1</code> + * @see #setStencilOp(int,int,int) + * + * @since Java 3D 1.4 + */ + public static final int STENCIL_DECR = 5; + + /** + * Stencil operation: <code>DST = ~DST</code> + * @see #setStencilOp(int,int,int) + * + * @since Java 3D 1.4 + */ + public static final int STENCIL_INVERT = 6; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_ALPHA_TEST_FUNCTION_READ, + ALLOW_ALPHA_TEST_VALUE_READ, + ALLOW_DEPTH_ENABLE_READ, + ALLOW_DEPTH_TEST_FUNCTION_READ, + ALLOW_IGNORE_VERTEX_COLORS_READ, + ALLOW_RASTER_OP_READ, + ALLOW_STENCIL_ATTRIBUTES_READ, + ALLOW_VISIBLE_READ + }; /** * Constructs a RenderingAttributes object with default parameters. @@ -286,15 +657,26 @@ public class RenderingAttributes extends NodeComponent { * depth buffer enable : true<br> * depth buffer write enable : true<br> * alpha test function : ALWAYS<br> - * alpha test value : 0.0<br> + * alpha test value : 0.0f<br> * visible : true<br> * ignore vertex colors : false<br> * raster operation enable : false<br> * raster operation : ROP_COPY<br> + * depth test: LESS_OR_EQUAL<br> + * stencil enable : false<br> + * stencil write mask : ~0 (all ones)<br> + * stencil op - failOp : STENCIL_KEEP<br> + * stencil op - zFailOp : STENCIL_KEEP<br> + * stencil op - zPassOp : STENCIL_KEEP<br> + * stencil function : ALWAYS<br> + * stencil reference value : 0<br> + * stencil comparison mask : ~0 (all ones) * </ul> */ public RenderingAttributes() { // Just use default attributes + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -327,8 +709,10 @@ public class RenderingAttributes extends NodeComponent { * @param rasterOpEnable a flag that specifies whether logical * raster operations are enabled for this RenderingAttributes object. * This disables all alpha blending operations. - * @param rasterOp the logical raster operation, one of ROP_COPY or - * ROP_XOR. + * @param rasterOp the logical raster operation, one of: + * ROP_CLEAR, ROP_AND, ROP_AND_REVERSE, ROP_COPY, ROP_AND_INVERTED, + * ROP_NOOP, ROP_XOR, ROP_OR, ROP_NOR, ROP_EQUIV, ROP_INVERT, + * ROP_OR_REVERSE, ROP_COPY_INVERTED, ROP_OR_INVERTED, ROP_NAND or ROP_SET * * @since Java 3D 1.2 */ @@ -340,6 +724,8 @@ public class RenderingAttributes extends NodeComponent { boolean ignoreVertexColors, boolean rasterOpEnable, int rasterOp) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); ((RenderingAttributesRetained)this.retained).initDepthBufferEnable(depthBufferEnable); ((RenderingAttributesRetained)this.retained).initDepthBufferWriteEnable(depthBufferWriteEnable); @@ -356,9 +742,13 @@ public class RenderingAttributes extends NodeComponent { /** * Enables or disables depth buffer mode for this RenderingAttributes * component object. + * * @param state true or false to enable or disable depth buffer mode + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph + * + * @see GraphicsConfigTemplate3D#setDepthSize */ public void setDepthBufferEnable(boolean state){ if (isLiveOrCompiled()) @@ -401,7 +791,6 @@ public class RenderingAttributes extends NodeComponent { if (isLiveOrCompiled()) if (!this.getCapability(ALLOW_DEPTH_ENABLE_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes2")); - if (isLive()) ((RenderingAttributesRetained)this.retained).setDepthBufferWriteEnable(state); else @@ -456,9 +845,9 @@ public class RenderingAttributes extends NodeComponent { } /** - * Set alpha test function. This function is used to compare the - * alpha test value with each per-pixel alpha value. If the test - * passes, the pixel is written otherwise the pixel is not + * Set alpha test function. This function is used to compare + * each incoming (source) per-pixel alpha value with the alpha test value. + * If the test passes, the pixel is written otherwise the pixel is not * written. * @param function the new alpha test function. One of * ALWAYS, NEVER, EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, @@ -639,8 +1028,10 @@ public class RenderingAttributes extends NodeComponent { * Sets the raster operation function for this RenderingAttributes * component object. * - * @param rasterOp the logical raster operation, one of ROP_COPY or - * ROP_XOR + * @param rasterOp the logical raster operation, one of: + * ROP_CLEAR, ROP_AND, ROP_AND_REVERSE, ROP_COPY, ROP_AND_INVERTED, + * ROP_NOOP, ROP_XOR, ROP_OR, ROP_NOR, ROP_EQUIV, ROP_INVERT, + * ROP_OR_REVERSE, ROP_COPY_INVERTED, ROP_OR_INVERTED, ROP_NAND or ROP_SET. * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * @@ -660,7 +1051,10 @@ public class RenderingAttributes extends NodeComponent { /** * Retrieves the current raster operation for this RenderingAttributes * object. - * @return one of ROP_COPY or ROP_XOR. + * @return one of: + * ROP_CLEAR, ROP_AND, ROP_AND_REVERSE, ROP_COPY, ROP_AND_INVERTED, + * ROP_NOOP, ROP_XOR, ROP_OR, ROP_NOR, ROP_EQUIV, ROP_INVERT, + * ROP_OR_REVERSE, ROP_COPY_INVERTED, ROP_OR_INVERTED, ROP_NAND or ROP_SET * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * @@ -723,13 +1117,368 @@ public class RenderingAttributes extends NodeComponent { rt.initDepthBufferEnable(attr.getDepthBufferEnable()); rt.initDepthBufferWriteEnable(attr.getDepthBufferWriteEnable()); + rt.initDepthTestFunction(attr.getDepthTestFunction()); rt.initAlphaTestValue(attr.getAlphaTestValue()); rt.initAlphaTestFunction(attr.getAlphaTestFunction()); rt.initVisible(attr.getVisible()); rt.initIgnoreVertexColors(attr.getIgnoreVertexColors()); rt.initRasterOpEnable(attr.getRasterOpEnable()); rt.initRasterOp(attr.getRasterOp()); + rt.initStencilEnable(attr.getStencilEnable()); + int[] ops = new int[3]; + attr.getStencilOp(ops); + rt.initStencilOp(ops[0], ops[1], ops[2]); + attr.getStencilFunction(ops); + rt.initStencilFunction(ops[0], ops[1], ops[2]); + rt.initStencilWriteMask(attr.getStencilWriteMask()); + + } + + /** + * Set depth test function. This function is used to compare each + * incoming (source) per-pixel depth test value with the stored per-pixel + * depth value in the frame buffer. If the test + * passes, the pixel is written, otherwise the pixel is not + * written. + * @param function the new depth test function. One of + * ALWAYS, NEVER, EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, + * or GREATER_OR_EQUAL. + * The default value is LESS_OR_EQUAL. + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public void setDepthTestFunction(int function){ + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_DEPTH_TEST_FUNCTION_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes14")); + if (isLive()) + ((RenderingAttributesRetained)this.retained).setDepthTestFunction(function); + else + ((RenderingAttributesRetained)this.retained).initDepthTestFunction(function); + } + + /** + * Retrieves current depth test function. + * @return the current depth test function + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public int getDepthTestFunction(){ + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_DEPTH_TEST_FUNCTION_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes15")); + + return ((RenderingAttributesRetained)this.retained).getDepthTestFunction(); + } + + /** + * Enables or disables the stencil buffer for this RenderingAttributes + * component object. If the stencil buffer is disabled, the + * stencil operation and function are ignored. If a scene graph + * is rendered on a Canvas3D that does not have a stencil buffer, + * the stencil buffer will be implicitly disabled for that canvas. + * + * @param state true or false to enable or disable stencil buffer + * operations. + * If this is set to false, the stencilOp and stencilFunction parameters + * are not used. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @see GraphicsConfigTemplate3D#setStencilSize + * + * @since Java 3D 1.4 + */ + public void setStencilEnable(boolean state) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes16")); + } + } + + if (isLive()) + ((RenderingAttributesRetained)this.retained).setStencilEnable(state); + else + ((RenderingAttributesRetained)this.retained).initStencilEnable(state); + + } + + /** + * Retrieves the stencil buffer enable flag for this RenderingAttributes + * object. + * + * @return true if stencil buffer operations are enabled; false + * if stencil buffer operations are disabled. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public boolean getStencilEnable() { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes17")); + } + } + + return ((RenderingAttributesRetained)this.retained).getStencilEnable(); + } + + /** + * Sets the stencil operations for this RenderingAttributes object to the + * specified parameters. + * + * @param failOp operation performed when the stencil test fails, one of: + * STENCIL_KEEP, STENCIL_ZERO, STENCIL_REPLACE, STENCIL_INCR, STENCIL_DECR, + * or STENCIL_INVERT. + * + * @param zFailOp operation performed when the stencil test passes and the + * depth test fails, one of: + * STENCIL_KEEP, STENCIL_ZERO, STENCIL_REPLACE, STENCIL_INCR, STENCIL_DECR, + * or STENCIL_INVERT. + * + * @param zPassOp operation performed when both the stencil test and the + * depth test pass, one of: + * STENCIL_KEEP, STENCIL_ZERO, STENCIL_REPLACE, STENCIL_INCR, STENCIL_DECR, + * or STENCIL_INVERT. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public void setStencilOp(int failOp, int zFailOp, int zPassOp) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes16")); + } + } + + if (isLive()) + ((RenderingAttributesRetained)this.retained).setStencilOp(failOp, + zFailOp, + zPassOp); + else + ((RenderingAttributesRetained)this.retained).initStencilOp(failOp, + zFailOp, + zPassOp); + + } + + /** + * Sets the stencil operations for this RenderingAttributes object to the + * specified parameters. + * + * @param stencilOps an array of three integers that specifies the new + * set of stencil operations. Element 0 of the array specifies the + * <code>failOp</code> parameter, element 1 specifies the + * <code>zFailOp</code> parameter, and element 2 specifies the + * <code>zPassOp</code> parameter. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @see #setStencilOp(int,int,int) + * + * @since Java 3D 1.4 + */ + public void setStencilOp(int[] stencilOps) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes16")); + } + } + + if (isLive()) + ((RenderingAttributesRetained)this.retained).setStencilOp(stencilOps[0], + stencilOps[1], + stencilOps[2]); + else + ((RenderingAttributesRetained)this.retained).initStencilOp(stencilOps[0], + stencilOps[1], + stencilOps[2]); + } + + /** + * Retrieves the current set of stencil operations, and copies them + * into the specified array. The caller must ensure that this array + * has been allocated with enough space to hold the results. + * + * @param stencilOps array that will receive the current set of + * three stencil operations. The <code>failOp</code> parameter is copied + * into element 0 of the array, the <code>zFailOp</code> parameter is copied + * into element 1, and the <code>zPassOp</code> parameter is copied + * into element 2. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public void getStencilOp(int[] stencilOps) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes17")); + } + } + + ((RenderingAttributesRetained)this.retained).getStencilOp(stencilOps); + } + + /** + * Sets the stencil function, reference value, and comparison mask + * for this RenderingAttributes object to the specified parameters. + * + * @param function the stencil test function, used to compare the + * stencil reference value with the stored per-pixel + * stencil value in the frame buffer. If the test + * passes, the pixel is written, otherwise the pixel is not + * written. The stencil function is one of: + * ALWAYS, NEVER, EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, + * or GREATER_OR_EQUAL. + * + * @param refValue the stencil reference value that is tested against + * the stored per-pixel stencil value + * + * @param compareMask a mask that limits which bits are compared; it is + * bitwise-ANDed with both the stencil reference value and the stored + * per-pixel stencil value before doing the comparison. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public void setStencilFunction(int function, int refValue, int compareMask) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes16")); + } + } + if (isLive()) + ((RenderingAttributesRetained)this.retained).setStencilFunction(function, + refValue, + compareMask); + else + ((RenderingAttributesRetained)this.retained).initStencilFunction(function, + refValue, + compareMask); + } + + /** + * Sets the stencil function, reference value, and comparison mask + * for this RenderingAttributes object to the specified parameters. + * + * @param params an array of three integers that specifies the new + * stencil function, reference value, and comparison mask. + * Element 0 of the array specifies the + * stencil function, element 1 specifies the + * reference value, and element 2 specifies the + * comparison mask. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @see #setStencilFunction(int,int,int) + * + * @since Java 3D 1.4 + */ + public void setStencilFunction(int[] params) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes16")); + } + } + + if (isLive()) + ((RenderingAttributesRetained)this.retained).setStencilFunction(params[0], + params[1], + params[2]); + else + ((RenderingAttributesRetained)this.retained).initStencilFunction(params[0], + params[1], + params[2]); + + } + + /** + * Retrieves the stencil function, reference value, and comparison mask, + * and copies them into the specified array. The caller must ensure + * that this array has been allocated with enough space to hold the results. + * + * @param params array that will receive the current stencil function, + * reference value, and comparison mask. The stencil function is copied + * into element 0 of the array, the reference value is copied + * into element 1, and the comparison mask is copied + * into element 2. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public void getStencilFunction(int[] params) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes17")); + } + } + + ((RenderingAttributesRetained)this.retained).getStencilFunction(params); + } + + /** + * Sets the stencil write mask for this RenderingAttributes + * object. This mask controls which bits of the + * stencil buffer are written. + * The default value is <code>~0</code> (all ones). + * + * @param mask the new stencil write mask. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public void setStencilWriteMask(int mask) { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_WRITE)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes16")); + } + } + + if (isLive()) + ((RenderingAttributesRetained)this.retained).setStencilWriteMask(mask); + else + ((RenderingAttributesRetained)this.retained).initStencilWriteMask(mask); + } + + /** + * Retrieves the current stencil write mask for this RenderingAttributes + * object. + * + * @return the stencil write mask. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @since Java 3D 1.4 + */ + public int getStencilWriteMask() { + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_STENCIL_ATTRIBUTES_READ)) { + throw new CapabilityNotSetException(J3dI18N.getString("RenderingAttributes17")); + } + } + + return ((RenderingAttributesRetained)this.retained).getStencilWriteMask(); } } diff --git a/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java b/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java index 1847fdf..44afe88 100644 --- a/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/RenderingAttributesRetained.java @@ -37,6 +37,15 @@ class RenderingAttributesRetained extends NodeComponentRetained { static final int RASTER_OP_VALUE = 0x80; + static final int DEPTH_TEST_FUNC = 0x100; + + static final int STENCIL_ENABLE = 0x200; + + static final int STENCIL_OP_VALUES = 0x400; + + static final int STENCIL_FUNC = 0x800; + + static final int STENCIL_WRITE_MASK = 0x1000; // depth buffer Enable for hidden surface removal boolean depthBufferEnable = true; @@ -47,6 +56,8 @@ class RenderingAttributesRetained extends NodeComponentRetained { int alphaTestFunction = RenderingAttributes.ALWAYS; + int depthTestFunction = RenderingAttributes.LESS_OR_EQUAL; + boolean visible = true; boolean ignoreVertexColors = false; @@ -54,8 +65,19 @@ class RenderingAttributesRetained extends NodeComponentRetained { // raster operation boolean rasterOpEnable = false; int rasterOp = RenderingAttributes.ROP_COPY; - + + // stencil operation + boolean stencilEnable = false; + int stencilFailOp = RenderingAttributes.STENCIL_KEEP; + int stencilZFailOp = RenderingAttributes.STENCIL_KEEP; + int stencilZPassOp = RenderingAttributes.STENCIL_KEEP; + int stencilFunction = RenderingAttributes.ALWAYS; + int stencilReferenceValue = 0; + int stencilCompareMask = ~0; + int stencilWriteMask = ~0; + // depth buffer comparison function. Used by multi-texturing only + //[PEPE] NOTE: they are both unused. Candidates for removal. static final int LESS = 0; static final int LEQUAL = 1; @@ -113,16 +135,33 @@ class RenderingAttributesRetained extends NodeComponentRetained { return visible; } - final void initIgnoreVertexColors(boolean state) { + + /** + * Enables or disables vertex colors for this RenderAttributes + * component object. + * @param state true or false to enable or disable vertex colors + */ + final void initIgnoreVertexColors(boolean state) { ignoreVertexColors = state; } + /** + * Enables or disables vertex colors for this RenderAttributes + * component object and sends a + * message notifying the interested structures of the change. + * @param state true or false to enable or disable depth vertex colors + */ final void setIgnoreVertexColors(boolean state) { initIgnoreVertexColors(state); sendMessage(IGNORE_VCOLOR, (state ? Boolean.TRUE: Boolean.FALSE)); } + /** + * Retrieves the state of vertex color Enable flag + * @return true if vertex colors are enabled, false + * if vertex colors are disabled + */ final boolean getIgnoreVertexColors() { return ignoreVertexColors; } @@ -260,6 +299,47 @@ class RenderingAttributesRetained extends NodeComponentRetained { return alphaTestFunction; } + /** + * Set depth test function. This function is used to compare the + * depth test value with each per-pixel alpha value. If the test + * passes, then the pixel is written otherwise the pixel is not + * written. + * @param function the new depth test function. One of: + * ALWAYS, NEVER, EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, + * GREATER_OR_EQUAL. + * Default value is LESS_OR_EQUAL + * @since Java 3D 1.4 + */ + final void initDepthTestFunction(int function){ + depthTestFunction = function; + } + + /** + * Set depth test function. This function is used to compare the + * depth test value with each per-pixel depth value. If the test + * passes, the pixel is written otherwise the pixel is not + * written. + * @param function the new depth test function. One of + * ALWAYS, NEVER, EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, + * GREATER_OR_EQUAL + * Default value is LESS_OR_EQUAL + * @since Java 3D 1.4 + */ + final void setDepthTestFunction(int function){ + initDepthTestFunction(function); + sendMessage(DEPTH_TEST_FUNC, new Integer(function)); + } + + /** + * Retrieves current depth test function. + * @return the current depth test function + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * @since Java 3D 1.4 + */ + final int getDepthTestFunction(){ + return depthTestFunction; + } /** * Initialize the raster op enable flag @@ -306,30 +386,149 @@ class RenderingAttributesRetained extends NodeComponentRetained { } + // Stencil operations + /** + * Initialize the stencil enable state + */ + final void initStencilEnable(boolean state) { + stencilEnable = state; + } + + /** + * Set the stencil enable state + */ + final void setStencilEnable(boolean state) { + initStencilEnable(state); + sendMessage(STENCIL_ENABLE, new Boolean(state)); + } + + /** + * Retrieves the current stencil enable state. + */ + final boolean getStencilEnable() { + return stencilEnable; + } + + /** + * Initialize the stencil op. value + */ + final void initStencilOp(int failOp, int zFailOp, int zPassOp) { + stencilFailOp = failOp; + stencilZFailOp = zFailOp; + stencilZPassOp = zPassOp; + } + + /** + * Set the stencil op. value + */ + final void setStencilOp(int failOp, int zFailOp, int zPassOp) { + initStencilOp(failOp, zFailOp, zPassOp); + + ArrayList arrList = new ArrayList(3); + arrList.add(new Integer(failOp)); + arrList.add(new Integer(zFailOp)); + arrList.add(new Integer(zPassOp)); + sendMessage(STENCIL_OP_VALUES, arrList); + } + + /** + * Retrieves the current stencil op. value + */ + final void getStencilOp(int[] stencilOps) { + stencilOps[0] = stencilFailOp; + stencilOps[1] = stencilZFailOp; + stencilOps[2] = stencilZPassOp; + } + + + /** + * Initialize the stencil function value + */ + final void initStencilFunction(int function, int refValue, int compareMask) { + stencilFunction = function; + stencilReferenceValue = refValue; + stencilCompareMask = compareMask; + } + + /** + * Set the stencil function value + */ + final void setStencilFunction(int function, int refValue, int compareMask) { + initStencilOp(function, refValue, compareMask); + + ArrayList arrList = new ArrayList(3); + arrList.add(new Integer(function)); + arrList.add(new Integer(refValue)); + arrList.add(new Integer(compareMask)); + sendMessage(STENCIL_FUNC, arrList); + } + + /** + * Retrieves the current stencil op. value + */ + final void getStencilFunction(int[] params) { + params[0] = stencilFunction; + params[1] = stencilReferenceValue; + params[2] = stencilCompareMask; + } + + + /** + * Initialize the stencil write mask + */ + final void initStencilWriteMask(int mask) { + stencilWriteMask = mask; + } + + /** + * Set the stencil write mask + */ + final void setStencilWriteMask(int mask) { + initStencilWriteMask(mask); + sendMessage(STENCIL_WRITE_MASK, new Integer(mask)); + } + + /** + * Retrieves the current stencil write mask + */ + final int getStencilWriteMask() { + return stencilWriteMask; + } + /** * Updates the native context. */ + + // TODO : Need to handle stencil operation on the native side -- Chien native void updateNative(long ctx, boolean depthBufferWriteEnableOverride, boolean depthBufferEnableOverride, boolean depthBufferEnable, boolean depthBufferWriteEnable, + int depthTestFunction, float alphaTestValue, int alphaTestFunction, boolean ignoreVertexColors, - boolean rasterOpEnable, int rasterOp); + boolean rasterOpEnable, int rasterOp, + boolean userStencilAvailable, boolean stencilEnable, + int stencilFailOp, int stencilZFailOp, int stencilZPassOp, + int stencilFunction, int stencilReferenceValue, + int stencilCompareMask, int stencilWriteMask ); /** * Updates the native context. */ - void updateNative(long ctx, + void updateNative(Canvas3D c3d, boolean depthBufferWriteEnableOverride, boolean depthBufferEnableOverride) { - updateNative(ctx, + updateNative(c3d.ctx, depthBufferWriteEnableOverride, depthBufferEnableOverride, - depthBufferEnable, depthBufferWriteEnable, alphaTestValue, - alphaTestFunction, ignoreVertexColors, - rasterOpEnable, rasterOp); + depthBufferEnable, depthBufferWriteEnable, depthTestFunction, + alphaTestValue, alphaTestFunction, ignoreVertexColors, + rasterOpEnable, rasterOp, c3d.userStencilAvailable, stencilEnable, + stencilFailOp, stencilZFailOp, stencilZPassOp, + stencilFunction, stencilReferenceValue, stencilCompareMask, + stencilWriteMask ); } /** @@ -368,14 +567,17 @@ class RenderingAttributesRetained extends NodeComponentRetained { * given "value" */ synchronized void updateMirrorObject(int component, Object value) { - RenderingAttributesRetained mirrorRa = (RenderingAttributesRetained)mirror; - + RenderingAttributesRetained mirrorRa = (RenderingAttributesRetained)mirror; + if ((component & DEPTH_ENABLE) != 0) { mirrorRa.depthBufferEnable = ((Boolean)value).booleanValue(); } else if ((component & DEPTH_WRITE_ENABLE) != 0) { mirrorRa.depthBufferWriteEnable = ((Boolean)value).booleanValue(); } + else if ((component & DEPTH_TEST_FUNC) != 0) { + mirrorRa.depthTestFunction = ((Integer)value).intValue(); + } else if ((component & ALPHA_TEST_VALUE) != 0) { mirrorRa.alphaTestValue = ((Float)value).floatValue(); } @@ -393,7 +595,25 @@ class RenderingAttributesRetained extends NodeComponentRetained { } else if ((component & RASTER_OP_VALUE) != 0) { mirrorRa.rasterOp = (((Integer)value).intValue()); - } + } + else if ((component & STENCIL_ENABLE) != 0) { + mirrorRa.stencilEnable = (((Boolean)value).booleanValue()); + } + else if ((component & STENCIL_OP_VALUES) != 0) { + ArrayList arrlist = (ArrayList) value; + mirrorRa.stencilFailOp = (((Integer)arrlist.get(0)).intValue()); + mirrorRa.stencilZFailOp = (((Integer)arrlist.get(1)).intValue()); + mirrorRa.stencilZPassOp = (((Integer)arrlist.get(2)).intValue()); + } + else if ((component & STENCIL_FUNC) != 0) { + ArrayList arrlist = (ArrayList) value; + mirrorRa.stencilFunction = (((Integer)arrlist.get(0)).intValue()); + mirrorRa.stencilReferenceValue = (((Integer)arrlist.get(1)).intValue()); + mirrorRa.stencilCompareMask = (((Integer)arrlist.get(2)).intValue()); + } + else if ((component & STENCIL_WRITE_MASK) != 0) { + mirrorRa.stencilWriteMask = (((Integer)value).intValue()); + } } boolean equivalent(RenderingAttributesRetained rr) { @@ -406,7 +626,16 @@ class RenderingAttributesRetained extends NodeComponentRetained { (rr.visible == visible) && (rr.ignoreVertexColors == ignoreVertexColors) && (rr.rasterOpEnable == rasterOpEnable) && - (rr.rasterOp == rasterOp)); + (rr.rasterOp == rasterOp) && + (rr.depthTestFunction == depthTestFunction) && + (rr.stencilEnable == stencilEnable) && + (rr.stencilFailOp == stencilFailOp) && + (rr.stencilZFailOp == stencilZFailOp) && + (rr.stencilZPassOp == stencilZPassOp) && + (rr.stencilFunction == stencilFunction) && + (rr.stencilReferenceValue == stencilReferenceValue) && + (rr.stencilCompareMask == stencilCompareMask) && + (rr.stencilWriteMask == stencilWriteMask)); } protected void set(RenderingAttributesRetained ra) { @@ -415,10 +644,20 @@ class RenderingAttributesRetained extends NodeComponentRetained { depthBufferWriteEnable = ra.depthBufferWriteEnable; alphaTestValue = ra.alphaTestValue; alphaTestFunction = ra.alphaTestFunction; + depthTestFunction = ra.depthTestFunction; visible = ra.visible; ignoreVertexColors = ra.ignoreVertexColors; rasterOpEnable = ra.rasterOpEnable; rasterOp = ra.rasterOp; + stencilEnable = ra.stencilEnable; + stencilFailOp = ra.stencilFailOp; + stencilZFailOp = ra.stencilZFailOp; + stencilZPassOp = ra.stencilZPassOp; + stencilFunction = ra.stencilFunction; + stencilReferenceValue = ra.stencilReferenceValue; + stencilCompareMask = ra.stencilCompareMask; + stencilWriteMask = ra.stencilWriteMask; + } final void sendMessage(int attrMask, Object attr) { @@ -462,7 +701,7 @@ class RenderingAttributesRetained extends NodeComponentRetained { } - + // TODO : Need to handle stencil operation -- Chien void handleFrequencyChange(int bit) { int mask = 0; @@ -478,6 +717,16 @@ class RenderingAttributesRetained extends NodeComponentRetained { mask = RASTER_OP_ENABLE; if(bit == RenderingAttributes.ALLOW_DEPTH_ENABLE_WRITE) mask = DEPTH_WRITE_ENABLE; + if( bit == RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_WRITE) + mask = DEPTH_TEST_FUNC; + + if( bit == RenderingAttributes.ALLOW_STENCIL_ATTRIBUTES_WRITE) + mask = DEPTH_TEST_FUNC; + + if( bit == RenderingAttributes.ALLOW_DEPTH_TEST_FUNCTION_WRITE) + mask = STENCIL_ENABLE | STENCIL_OP_VALUES | STENCIL_FUNC | + STENCIL_WRITE_MASK; + if (mask != 0) setFrequencyChangeMask(bit, mask); // System.out.println("changedFreqent2 = "+changedFrequent); diff --git a/src/classes/share/javax/media/j3d/RenderingAttributesStructure.java b/src/classes/share/javax/media/j3d/RenderingAttributesStructure.java index d81a58a..abe2180 100644 --- a/src/classes/share/javax/media/j3d/RenderingAttributesStructure.java +++ b/src/classes/share/javax/media/j3d/RenderingAttributesStructure.java @@ -42,11 +42,13 @@ class RenderingAttributesStructure extends J3dStructure implements ObjectUpdate for (int i=0; i < nMsg; i++) { m = messages[i]; switch (m.type) { - // Apperance is always updated immediately, since rBin needs + // Appearance is always updated immediately, since rBin needs // the most up-to-date values for restructuring case J3dMessage.APPEARANCE_CHANGED: - case J3dMessage.TEXTURE_UNIT_STATE_CHANGED: // TODO: Is this correct? + case J3dMessage.SHADER_APPEARANCE_CHANGED: + case J3dMessage.TEXTURE_UNIT_STATE_CHANGED: { + // System.out.println("1 RAS : J3dMessage type : " + m.type); int component = ((Integer)m.args[1]).intValue(); NodeComponentRetained nc = (NodeComponentRetained)m.args[0]; nc.mirror.changedFrequent = ((Integer)m.args[3]).intValue(); @@ -69,7 +71,11 @@ class RenderingAttributesStructure extends J3dStructure implements ObjectUpdate case J3dMessage.TRANSPARENCYATTRIBUTES_CHANGED: case J3dMessage.MATERIAL_CHANGED: case J3dMessage.TEXCOORDGENERATION_CHANGED: + case J3dMessage.SHADER_ATTRIBUTE_CHANGED: + case J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED: { + // System.out.println("2 RAS : J3dMessage type : " + m.type); + NodeComponentRetained nc = (NodeComponentRetained)m.args[0]; nc.mirror.changedFrequent = ((Integer)m.args[3]).intValue(); if (nc.mirror.changedFrequent != 0) { @@ -105,8 +111,6 @@ class RenderingAttributesStructure extends J3dStructure implements ObjectUpdate NodeComponentRetained nc = (NodeComponentRetained)m.args[0]; nc.mirror.changedFrequent = ((Integer)m.args[4]).intValue(); - - if (nc.mirror.changedFrequent != 0) { objList.add(m); addMirrorObj = true; @@ -118,11 +122,9 @@ class RenderingAttributesStructure extends J3dStructure implements ObjectUpdate } } break; - case J3dMessage.TEXTURE_CHANGED: { NodeComponentRetained nc = (NodeComponentRetained)m.args[0]; - int attrMask = ((Integer)m.args[1]).intValue(); nc.mirror.changedFrequent = ((Integer)m.args[3]).intValue(); objList.add(m); @@ -190,6 +192,7 @@ class RenderingAttributesStructure extends J3dStructure implements ObjectUpdate updateTextureAttributes((Object[])m.args); } else if (m.type == J3dMessage.APPEARANCE_CHANGED || + m.type == J3dMessage.SHADER_APPEARANCE_CHANGED || m.type == J3dMessage.TEXTURE_UNIT_STATE_CHANGED){ NodeComponentRetained nc = (NodeComponentRetained)m.args[0]; nc.mirror.compChanged = 0; @@ -206,12 +209,13 @@ class RenderingAttributesStructure extends J3dStructure implements ObjectUpdate } - void updateNodeComponent(Object[] args) { - NodeComponentRetained n = (NodeComponentRetained)args[0]; - n.updateMirrorObject(((Integer)args[1]).intValue(), args[2]); + private void updateNodeComponent(Object[] args) { + // System.out.println("RAS : updateNodeComponent : " + this); + NodeComponentRetained n = (NodeComponentRetained)args[0]; + n.updateMirrorObject(((Integer)args[1]).intValue(), args[2]); } - void updateTextureAttributes(Object[] args) { + private void updateTextureAttributes(Object[] args) { TextureAttributesRetained n = (TextureAttributesRetained)args[0]; n.updateMirrorObject(((Integer)args[1]).intValue(), args[2], args[3]); } diff --git a/src/classes/share/javax/media/j3d/SceneGraphObject.java b/src/classes/share/javax/media/j3d/SceneGraphObject.java index bfae7f3..32c52b8 100644 --- a/src/classes/share/javax/media/j3d/SceneGraphObject.java +++ b/src/classes/share/javax/media/j3d/SceneGraphObject.java @@ -15,9 +15,37 @@ package javax.media.j3d; import java.util.Hashtable; /** - * SceneGraphObject is a common superclass for - * all scene graph component objects. This includes Node, - * Geometry, Appearance, etc. + * SceneGraphObject is the common superclass for all scene graph + * objects. Scene graph objects are classified into two main types: + * nodes and node components. The Node object is the common superclass + * of all nodes, which includes TransformGroup, Shape3D, etc. + * The NodeComponent object is the common superclass of all node + * components, which includes Geometry, Appearance, etc. + * + * <p> + * All scene graph objects have a name, a user data object, a set of + * capability bits, and a set of capabilityIsFrequent bits. + * + * <p> + * Capability bits control whether a particular attribute in a node or + * node component is readable or writable. For live or compiled scene + * graphs, only those attributes whose capabilities are set before the + * scene graph is compiled or made live may be read or written. The + * default value for all <i>read</i> capability bits is true, meaning + * that all attributes may be read by default. The default value for + * all <i>write</i> capability bits is false, meaning that no + * attributes may be written by default. Read capability bits are + * defined as those capability bits of the form <code>ALLOW_*_READ</code>, + * plus the <code>ALLOW_INTERSECT</code> capability bit. Write + * capability bits are defined as those capability bits of the form + * <code>ALLOW_*_WRITE</code>, plus the <code>ALLOW_CHILDREN_EXTEND</code> + * and <code>ALLOW_DETACH</code> capability bits. + * + * <p> + * NOTE that the <code>ENABLE_COLLISION_REPORTING</code> and + * <code>ENABLE_PICK_REPORTING</code> bits are not really capability bits, + * although they are set with the setCapability method. The default value + * for each of the <code>ENABLE_*_REPORTING bits</code> is false. */ public abstract class SceneGraphObject extends Object { // Any global flags? (e.g., execution cullable, collideable) @@ -43,6 +71,9 @@ public abstract class SceneGraphObject extends Object { // A reference to user data private Object userData = null; + // Optional name for object. + private String objectName = null; + // use for cloneTree/cloneNode only, set to null after the operation Hashtable nodeHashtable = null; @@ -52,10 +83,13 @@ public abstract class SceneGraphObject extends Object { * Constructs a SceneGraphObject with default parameters. The default * values are as follows: * <ul> - * capability bits : clear (all bits)<br> + * all <i>read</i> capability bits : set (true)<br> + * all <i>write</i> capability bits : clear (false)<br> + * all capabilityIsFrequent bits : set (true)<br> * isLive : false<br> * isCompiled : false<br> * user data : null<br> + * name : null<br> * </ul> */ public SceneGraphObject() { @@ -76,7 +110,18 @@ public abstract class SceneGraphObject extends Object { // this.retained = new <ClassName>Retained(); // this.retained.setSource(this); } - + + /** + * Method to set default read capability bits to true + */ + void setDefaultReadCapabilities(int[] bits) { + if (true /*VirtualUniverse.mc.defaultReadCapability*/) { + for (int i=0; i < bits.length; i++) { + setCapability(bits[i]); + } + } + } + /** * Retrieves the specified capability bit. Note that only one capability * bit may be retrieved per method invocation--capability bits cannot @@ -331,6 +376,28 @@ public abstract class SceneGraphObject extends Object { public void updateNodeReferences(NodeReferenceTable referenceTable) { } + /** + * Sets the name of this object. Object names are for information + * only. + * + * @param name the new name of this object + * + * @since Java 3D 1.4 + */ + public void setName( String name ) { + objectName = name; + } + + /** + * Returns the name of this object. + * + * @return the name of this object + * + * @since Java 3D 1.4 + */ + public String getName() { + return objectName; + } /** * Copies all SceneGraphObject information from @@ -353,6 +420,7 @@ public abstract class SceneGraphObject extends Object { // Duplicate any class specific data here. capabilityBits = originalNode.capabilityBits; userData = originalNode.userData; + objectName = originalNode.objectName; } @@ -402,4 +470,25 @@ public abstract class SceneGraphObject extends Object { return originalNodeComponent; } } + + // Internal method to make a prefix out of the name of this object + String getNamePrefix() { + String name = getName(); + + if (name != null) { + return "[" + name + "] "; + } + + return ""; + } + + /** + * Returns a String representation of this SceneGraphObject. + * If its name is non-null, then it is concatenated with + * super.toString(). + */ + public String toString() { + return getNamePrefix() + super.toString(); + } + } diff --git a/src/classes/share/javax/media/j3d/ScreenViewCache.java b/src/classes/share/javax/media/j3d/ScreenViewCache.java index a3802d4..397367a 100644 --- a/src/classes/share/javax/media/j3d/ScreenViewCache.java +++ b/src/classes/share/javax/media/j3d/ScreenViewCache.java @@ -37,7 +37,12 @@ class ScreenViewCache extends Object { // Mask that indicates Screen3D view dependence info. has changed, // and CanvasViewCache may need to recompute the final view matries. - int scrvcDirtyMask = 0; + // Issue 163: Array of dirty bits is used because the Renderer and + // RenderBin run asynchronously. Now that they each have a separate + // instance of CanvasViewCache (due to the fix for Issue 109), they + // need separate dirty bits. Array element 0 is used for the Renderer and + // element 1 is used for the RenderBin. + int[] scrvcDirtyMask = new int[2]; // // Tracker-base coordinate system to image-plate coordinate @@ -72,17 +77,20 @@ class ScreenViewCache extends Object { * Take snapshot of all per-screen API parameters. */ synchronized void snapshot() { - - // accumulate the dirty bits for offscreen because - // the dirty bits will not be processed until renderOffScreen - // or triggered by RenderBin at some little time - if (screen.offScreen) - scrvcDirtyMask |= screen.scrDirtyMask; - else - scrvcDirtyMask = screen.scrDirtyMask; - - screen.scrDirtyMask = 0; - physicalScreenWidth = screen.physicalScreenWidth; + + // accumulate the dirty bits for offscreen because + // the dirty bits will not be processed until renderOffScreen + // or triggered by RenderBin at some little time + if (screen.offScreen) { + scrvcDirtyMask[0] |= screen.scrDirtyMask; + scrvcDirtyMask[1] |= screen.scrDirtyMask; + } else { + scrvcDirtyMask[0] = screen.scrDirtyMask; + scrvcDirtyMask[1] = screen.scrDirtyMask; + } + screen.scrDirtyMask = 0; + + physicalScreenWidth = screen.physicalScreenWidth; physicalScreenHeight = screen.physicalScreenHeight; screenWidth = screen.screenSize.width; screenHeight = screen.screenSize.height; diff --git a/src/classes/share/javax/media/j3d/Sensor.java b/src/classes/share/javax/media/j3d/Sensor.java index ef44ac6..05df43a 100644 --- a/src/classes/share/javax/media/j3d/Sensor.java +++ b/src/classes/share/javax/media/j3d/Sensor.java @@ -59,29 +59,35 @@ public class Sensor { /** * Set predictor type to do no prediction; this is the default. + * + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public static final int PREDICT_NONE = 1; /** - * Set predictor type to generate the SensorRead to correspond with - * the next frame time. + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public static final int PREDICT_NEXT_FRAME_TIME = 2; /** * Use no prediction policy; this is the default. + * + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public static final int NO_PREDICTOR = 16; /** - * Set the predictor policy to assume the sensor is predicting head - * position/orientation. + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public static final int HEAD_PREDICTOR = 32; /** - * Set the predictor policy to assume the sensor is predicting hand - * position/orientation. + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public static final int HAND_PREDICTOR = 64; @@ -110,11 +116,11 @@ public class Sensor { // size of the sensor read buffer int sensorReadCount; - // Default prediction policy: don't predict - int predictionPolicy = NO_PREDICTOR; + // Prediction policy -- unused + private int predictionPolicy = NO_PREDICTOR; - // Default Predictor none - int predictorType = PREDICT_NONE; + // Predictor type -- unused + private int predictorType = PREDICT_NONE; // This sensor's associated device InputDevice device; @@ -135,12 +141,6 @@ public class Sensor { Matrix3d temp_rot = new Matrix3d(); Matrix3d local_svd = new Matrix3d(); - // Prediction workspace -- these may go away when the readings array - // is used. - static int MAX_PREDICTION_LENGTH = 20; - Transform3D[] previousReads = new Transform3D[MAX_PREDICTION_LENGTH]; - long[] times = new long[MAX_PREDICTION_LENGTH]; - /** * Constructs a Sensor object for the specified input device using @@ -149,8 +149,8 @@ public class Sensor { * sensor read count : 30<br> * sensor button count : 0<br> * hot spot : (0,0,0)<br> - * predictor : PREDICT_NONE<br> - * prediction policy : NO_PREDICTOR<br> + * predictor : PREDICT_NONE — <i>this attribute is unused</i><br> + * prediction policy : NO_PREDICTOR — <i>this attribute is unused</i><br> * </ul> * @param device the Sensor's associated device. */ @@ -237,11 +237,6 @@ public class Sensor { } currentIndex = 0; this.hotspot = new Point3d(hotspot); - - // prediction initialization - for(int i=0 ; i<MAX_PREDICTION_LENGTH ; i++) { - previousReads[i] = new Transform3D(); - } } // argument of 0 is last reading (ie, currentIndex), argument @@ -252,11 +247,16 @@ public class Sensor { } /** - * This function sets the type of predictor to use with this sensor. + * Sets the type of predictor to use with this sensor. + * Since prediction is not implemented (and never has been), this + * attribute has no effect. * @param predictor predictor type one of PREDICT_NONE or * PREDICT_NEXT_FRAME_TIME * @exception IllegalArgumentException if an invalid predictor type * is specified. + * + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public void setPredictor(int predictor){ if (predictor != PREDICT_NONE && predictor != PREDICT_NEXT_FRAME_TIME) { @@ -267,20 +267,27 @@ public class Sensor { } /** - * This function returns the type of predictor used by this sensor. - * @return returns the predictor type. One of PREDICT_NONE or - * PREDICT_NEXT_FRAME_TIME. + * Returns the type of predictor used by this sensor. + * @return the predictor type. + * + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public int getPredictor(){ return predictorType; } /** - * This function sets the prediction policy use by this sensor. + * Sets the prediction policy use by this sensor. + * Since prediction is not implemented (and never has been), this + * attribute has no effect. * @param policy prediction policy one of NO_PREDICTOR, HEAD_PREDICTOR, * or HAND_PREDICTOR * @exception IllegalArgumentException if an invalid prediction policy * is specified. + * + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public void setPredictionPolicy(int policy){ if (policy != NO_PREDICTOR && policy != HEAD_PREDICTOR && @@ -291,9 +298,11 @@ public class Sensor { } /** - * This function returns the prediction policy used by this sensor. - * @return returns the prediction policy. one of NO_PREDICTOR, - * HEAD_PREDICTOR, or HAND_PREDICTOR. + * Returns the prediction policy used by this sensor. + * @return the prediction policy. + * + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature. */ public int getPredictionPolicy(){ return predictionPolicy; @@ -332,79 +341,30 @@ public class Sensor { } /** - * Computes the sensor reading consistent with the prediction policy - * and copies that value into the specified argument; calling this method - * with a prediction policy of NO_PREDICTOR will return the last sensor - * reading; calling this method with a prediction policy of HAND_PREDICTOR, - * or HEAD_PREDICTOR will extrapolate previous sensor readings to the - * current time. - * @param read The matrix that will receive the predicted sensor reading + * Retrieves the last sensor reading and copies that value into + * the specified argument. + * + * @param read the matrix that will receive the sensor reading */ - public void getRead(Transform3D read){ - long time; - + public void getRead(Transform3D read) { if(demand_driven == true) device.pollAndProcessInput(); - time = System.currentTimeMillis(); - - // before using prediction, fill in some values - if(num_reads_so_far < 40*SENSOR_READ_COUNT_BUFFER) { - num_reads_so_far++; - read.set(readings[currentIndex].read); - return; - } - - switch(predictionPolicy) { - case NO_PREDICTOR: - read.set(readings[currentIndex].read); - break; - case HAND_PREDICTOR: - read.set(readings[currentIndex].read); - //getPredictedRead(read, time, 3, 2); - break; - case HEAD_PREDICTOR: - read.set(readings[currentIndex].read); - //getPredictedRead(read, time, 3, 2); - break; - } + read.set(readings[currentIndex].read); } /** - * Computes the sensor reading consistent as of time deltaT in the future - * and copies that value into the specified argument; the reading is - * computed using the current prediction policy; a prediction policy of - * NO_PREDICTOR will yield the most recent sensor reading for any - * deltaT argument (i.e., this method is the same as getRead for a prediction - * policy of NO_PREDICTOR). The time argument must be >= 0. - * @param read the matrix that will receive the predicted sensor reading - * @param deltaT the time delta into the future for this read + * Retrieves the last sensor reading and copies that value into + * the specified argument. + * + * @param read the matrix that will receive the sensor reading + * @param deltaT this parameter is ignored + * + * @deprecated As of Java 3D version 1.4, prediction is not a + * supported feature; use <code>getRead(Transform3D)</code> instead. */ public void getRead(Transform3D read, long deltaT){ - long current_time; - - if(deltaT < 0L) { - throw new IllegalArgumentException(J3dI18N.getString("Sensor2")); - } - - if(demand_driven == true) - device.pollAndProcessInput(); - - current_time = System.currentTimeMillis(); - - switch(predictionPolicy) { - case NO_PREDICTOR: - read.set(readings[currentIndex].read); - break; - case HAND_PREDICTOR: - read.set(readings[currentIndex].read); - //getPredictedRead(read, current_time + deltaT, 3, 2); - break; - case HEAD_PREDICTOR: - read.set(readings[currentIndex].read); - //getPredictedRead(read, current_time + deltaT, 3, 2); - break; - } + getRead(read); } /** @@ -566,132 +526,4 @@ public class Sensor { currentIndex = temp; } - /** - * This routine does an nth order fit of the last num_readings, which - * can be plotted on a graph of time vs. sensor reading. There is a - * separate fit done for each of the 16 matrix elements, then an SVD - * done on the final matrix. The curve that is produced takes into - * account non-constant times between each sample (it is fully general). - * This curve can then be used to produce a prediction for any - * time in the future by simply inserting a time value and using the - * solution matrix. - */ - void getPredictedRead(Transform3D transform, long time, int num_readings, - int order) { - - int index = currentIndex; // lock in current_index for MT-safety - long time_basis = readings[index].time; - long tempTime; - - time -= time_basis; - - GMatrix A = new GMatrix(num_readings, order+1); - - for(int i=0 ; i<num_readings ; i++) { - A.setElement(i, 0, 1.0); - tempTime = lastTimeRelative(num_readings-i-1, index, time_basis); - A.setElement(i, 1, (double)tempTime); - for(int j=2; j<=order ; j++) { - // powerAndDiv(time, n) = times^n/n - A.setElement(i, j, powerAndDiv(tempTime, j)); - } - } - - GMatrix A_Transpose = new GMatrix(A); - A_Transpose.transpose(); - GMatrix M = new GMatrix(order+1, order+1); - M.mul(A_Transpose, A); - try { - M.invert(); - } catch (SingularMatrixException e) { - System.out.println("SINGULAR MATRIX EXCEPTION in prediction"); - System.out.println(M); - } - - // TODO: can be class scope - double[] transformArray = new double[16]; - GMatrix solMatrix = new GMatrix(order+1, num_readings); - solMatrix.mul(M,A_Transpose); - - GVector P = new GVector(order+1); - - // fill in the time for which we are trying to predict a sensor value - GVector predTimeVec = new GVector(order+1); - predTimeVec.setElement(0, 1); - predTimeVec.setElement(1, time); - for(int i=2 ; i<=order ; i++) { - predTimeVec.setElement(i, powerAndDiv(time, i)); - } - - GVector R = new GVector(num_readings); - - for(int transElement=0 ; transElement<16 ; transElement++) { - - for(int i=0 ; i<num_readings ; i++) { - R.setElement(i, lastReadRelative(num_readings-i-1, index, - transElement)); - } - - P.mul(solMatrix,R); - transformArray[transElement] = P.dot(predTimeVec); - } - - //Matrix4d temp = new Matrix4d(transformArray); - //localSVD(temp); - //transform.set(temp); - transform.set(transformArray); - transform.normalize(); - } - - /** - * Extracts the kth most recent sensor reading and copies that value into - * the specified argument; where 0 is the most recent sensor reading, 1 is - * the next most recent sensor reading, etc. - * @param read The matrix that will receive the most recent sensor reading - * @param k The kth previous sensor reading - */ - double lastReadRelative(int kth, int base_index, int mat_element){ - // kth should be < sensorReadCount - return - readings[previousIndexRelative(kth, base_index)].read.mat[mat_element]; - } - - /** - * Returns the time associated with the kth most recent sensor reading; - * where 0 is the most recent sensor reading, 1 is the next most recent - * sensor reading, etc. However, unlike the public method, returns - * the kth reading relative to the index given, instead of the - * current_index and returns the time relative to timeBasis. - * @return the time associated with the kthmost recent sensor reading. - */ - long lastTimeRelative(int k, int base_index, long timeBasis){ - // kth should be < sensorReadCount - long time; - time = timeBasis - readings[previousIndexRelative(k, base_index)].time; - return time; - } - - // argument of 0 is last reading, argument of 1 means next to last - // index, etc. , but all of these are relative to *base_index* - int previousIndexRelative(int k, int base_index){ - int temp = base_index - k; - return(temp >= 0 ? temp : MaxSensorReadIndex + temp + 1); - } - - // this method returns (value^order)/order - double powerAndDiv(double value, int order) { - - if(order == 0) - return 1; - else if(order == 1) - return value; - - double total = 1.0; - for(int i=0 ; i< order ; i++) - total *= value; - - total = total / (double)order; - return total; - } - } diff --git a/src/classes/share/javax/media/j3d/SetLiveState.java b/src/classes/share/javax/media/j3d/SetLiveState.java index 84ff55a..6c81c4e 100644 --- a/src/classes/share/javax/media/j3d/SetLiveState.java +++ b/src/classes/share/javax/media/j3d/SetLiveState.java @@ -243,7 +243,7 @@ class SetLiveState extends Object { localToVworldIndex = null; localToVworldKeys = null; - // TODO: optimization for targetThreads computation, require + // XXXX: optimization for targetThreads computation, require // cleanup in GroupRetained.doSetLive() //transformTargetThreads = 0; diff --git a/src/classes/share/javax/media/j3d/Shader.java b/src/classes/share/javax/media/j3d/Shader.java new file mode 100644 index 0000000..f5870ee --- /dev/null +++ b/src/classes/share/javax/media/j3d/Shader.java @@ -0,0 +1,131 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The Shader object is the abstract base class for programmable + * shader code. Currently, only text-based source code shaders are + * supported, so the only subclass of Shader is SourceCodeShader. We + * leave open the possibility for binary (object code) shaders in the + * future. + * + * <p> + * Each instance of a Shader object allows an application to specify + * the source code used in programming the Graphics Pipeline Unit + * (GPU) of the graphics accelerator. A Shader object is constructed + * with modes that specify the <i>shading language</i> and the + * <i>shader type</i>. + * + * <p> + * The shading language specifies the language and runtime environment + * used to program the GPU. The currently defined shading languages + * are GLSL (also known as the OpenGL 2.0 shading language) and + * Cg. Note that not all shading languages are supported on all + * platforms. It is up to the application or utility to query whether + * a particular shading language is supported before using it. The + * value of the <code>shadingLanguage</code> mode is one of: + * <code>SHADING_LANGUAGE_GLSL</code> or + * <code>SHADING_LANGUAGE_CG</code>. + * + *<p> + * The shader type specifies whether the shader is a <i>vertex + * shader</i> or a <i>fragment shader</i>. A vertex shader replaces + * the fixed-function graphics pipeline for vertex operations + * (transformation and lighting). A fragment shader replaces the + * fixed-function graphics pipeline for fragment shading operations + * (texture mapping, texture application, coloring, shading, and so + * forth). The value of the <code>shaderType</code> mode is one of: + * <code>SHADER_TYPE_VERTEX</code> or + * <code>SHADER_TYPE_FRAGMENT</code>. + * + * <p> + * Both the shading language and shader type are immutable modes of + * the Shader object. + * + * <p> + * NOTE: Applications should <i>not</i> extend this class. + * + * @see ShaderProgram + * @see Canvas3D#isShadingLanguageSupported + * + * @since Java 3D 1.4 + */ + +public abstract class Shader extends NodeComponent { + + + /** + * This constant indicates the GLSL shading language. It is one + * of the possible values of the shadingLanguage parameter. + */ + public static final int SHADING_LANGUAGE_GLSL = 1; + + /** + * This constant indicates the Cg shading language. It is one + * of the possible values of the shadingLanguage parameter. + */ + public static final int SHADING_LANGUAGE_CG = 2; + + + /** + * This constant indicates that the shader type is a vertex + * shader. It is one of the possible values of the shaderType + * parameter. + */ + public static final int SHADER_TYPE_VERTEX = 1; + + /** + * This constant indicates that the shader type is a fragment + * shader. It is one of the possible values of the shaderType + * parameter. + */ + public static final int SHADER_TYPE_FRAGMENT = 2; + + + /** + * Not a public constructor, for internal use + */ + Shader() { + } + + /** + * Package scope constructor so it can't be subclassed by classes + * outside the javax.media.j3d package. + */ + Shader(int shadingLanguage, int shaderType) { + ((ShaderRetained)this.retained).initializeShader(shadingLanguage, shaderType); + } + + /** + * Returns the shading language of this shader. + * + * @return the shading language of this shader, one of: + * <code>SHADING_LANGUAGE_GLSL</code> or + * <code>SHADING_LANGUAGE_CG</code>. + */ + public int getShadingLanguage() { + return ((ShaderRetained)this.retained).getShadingLanguage(); + } + + /** + * Returns the type of this shader. + * + * @return the shader type, one of: + * <code>SHADER_TYPE_VERTEX</code> or + * <code>SHADER_TYPE_FRAGMENT</code>. + */ + public int getShaderType() { + return ((ShaderRetained)this.retained).getShaderType(); + } +} + diff --git a/src/classes/share/javax/media/j3d/ShaderAppearance.java b/src/classes/share/javax/media/j3d/ShaderAppearance.java new file mode 100644 index 0000000..2b9be8c --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAppearance.java @@ -0,0 +1,285 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.Hashtable; + +/** + * <p>The ShaderAppearance object defines programmable shading attributes + * that can be set as a component object of a Shape3D node. The + * ShaderAppearance rendering state adds the following attributes in + * addition to those defined by Appearance:</p> + * + * <ul> + * <li>Shader program - specifies the shader program...</li> + * + * <p></p> + * <li>Shader attribute set - specifies the shader parameters, both as + * explicit attributes and as implicit bindings to Java 3D + * state...</li> + * </ul> + * + * <p>The ShaderAppearance object modifies the definition of some of the + * attributes in Appearance:</p> + * + * <ul> + * <li>Coloring attributes - XXXXX</li> + * + * <p></p> + * <li>Line attributes - XXXXX</li> + * + * <p></p> + * <li>Point attributes - XXXXX</li> + * + * <p></p> + * <li>Polygon attributes - XXXXX</li> + * + * <p></p> + * <li>Rendering attributes - XXXXX</li> + * + * <p></p> + * <li>Transparency attributes - XXXXX</li> + * + * <p></p> + * <li>Material - XXXXX</li> + * + * <p></p> + * <li>Texture - XXXXX</li> + * + * <p></p> + * <li>Texture attributes - XXXXX</li> + * + * <p></p> + * <li>Texture coordinate generation - XXXXX</li> + * + * <p></p> + * <li>Texture unit state - XXXXX</li> + * </ul> + * + * @see ShaderProgram + * @see ShaderAttributeSet + * + * @since Java 3D 1.4 + */ +public class ShaderAppearance extends Appearance { + /** + * Specifies that this ShaderAppearance object allows reading its + * ShaderProgram component information. + */ + public static final int + ALLOW_SHADER_PROGRAM_READ = + CapabilityBits.SHADER_APPEARANCE_ALLOW_SHADER_PROGRAM_READ; + + /** + * Specifies that this ShaderAppearance object allows writing its + * ShaderProgram component information. + */ + public static final int + ALLOW_SHADER_PROGRAM_WRITE = + CapabilityBits.SHADER_APPEARANCE_ALLOW_SHADER_PROGRAM_WRITE; + + /** + * Specifies that this ShaderAppearance object allows reading its + * ShaderAttributeSet component information. + */ + public static final int + ALLOW_SHADER_ATTRIBUTE_SET_READ = + CapabilityBits.SHADER_APPEARANCE_ALLOW_SHADER_ATTRIBUTE_SET_READ; + + /** + * Specifies that this ShaderAppearance object allows writing its + * ShaderAttributeSet component information. + */ + public static final int + ALLOW_SHADER_ATTRIBUTE_SET_WRITE = + CapabilityBits.SHADER_APPEARANCE_ALLOW_SHADER_ATTRIBUTE_SET_WRITE; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SHADER_PROGRAM_READ, + ALLOW_SHADER_ATTRIBUTE_SET_READ + }; + + /** + * Constructs a ShaderAppearance component object using defaults for all + * state variables. All component object references are initialized + * to null. + */ + public ShaderAppearance() { + // Just use default values + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } + + /** + * Creates the retained mode ShaderAppearanceRetained object that this + * ShaderAppearance component object will point to. + */ + void createRetained() { + this.retained = new ShaderAppearanceRetained(); + this.retained.setSource(this); + } + + /** + * Sets the ShaderProgram object to the specified object. Setting it to + * null causes a default pass-through shader to be used ??? + * + * @param shaderProgram object that specifies the desired shader program + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public void setShaderProgram(ShaderProgram shaderProgram) { + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_SHADER_PROGRAM_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAppearance0")); + } + + ((ShaderAppearanceRetained)this.retained).setShaderProgram(shaderProgram); + + } + + + /** + * Retrieves the current ShaderProgram object. + * + * @return the ShaderProgram object + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public ShaderProgram getShaderProgram() { + + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_SHADER_PROGRAM_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAppearance1")); + } + return ((ShaderAppearanceRetained)this.retained).getShaderProgram(); + } + + + /** + * Sets the ShaderAttributeSet object to the specified object. Setting it to + * null is equivalent to specifying an empty set of attributes. + * + * @param shaderAttributeSet object that specifies the desired shader attributes + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public void setShaderAttributeSet(ShaderAttributeSet shaderAttributeSet) { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_SHADER_ATTRIBUTE_SET_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAppearance2")); + } + + ((ShaderAppearanceRetained)this.retained).setShaderAttributeSet(shaderAttributeSet); + } + + + /** + * Retrieves the current ShaderAttributeSet object. + * + * @return the ShaderAttributeSet object + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public ShaderAttributeSet getShaderAttributeSet() { + if (isLiveOrCompiled()) { + if(!this.getCapability(ALLOW_SHADER_ATTRIBUTE_SET_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAppearance3")); + } + return ((ShaderAppearanceRetained)this.retained).getShaderAttributeSet(); + } + + + /** + * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) + */ + public NodeComponent cloneNodeComponent() { + ShaderAppearance a = new ShaderAppearance(); + a.duplicateNodeComponent(this); + return a; + } + + /** + * NOTE: Applications should <i>not</i> call this method directly. + * It should only be called by the cloneNode method. + * + * @deprecated replaced with duplicateNodeComponent( + * NodeComponent originalNodeComponent, boolean forceDuplicate) + */ + public void duplicateNodeComponent(NodeComponent originalNodeComponent) { + checkDuplicateNodeComponent(originalNodeComponent); + } + + /** + * Copies all ShaderAppearance information from + * <code>originalNodeComponent</code> into + * the current node. This method is called from the + * <code>cloneNode</code> method which is, in turn, called by the + * <code>cloneTree</code> method.<P> + * + * @param originalNodeComponent the original node to duplicate. + * @param forceDuplicate when set to <code>true</code>, causes the + * <code>duplicateOnCloneTree</code> flag to be ignored. When + * <code>false</code>, the value of each node's + * <code>duplicateOnCloneTree</code> variable determines whether + * NodeComponent data is duplicated or copied. + * + * @exception RestrictedAccessException if this object is part of a live + * or compiled scenegraph. + * + * @see Node#cloneTree + * @see NodeComponent#setDuplicateOnCloneTree + */ + void duplicateAttributes(NodeComponent originalNodeComponent, + boolean forceDuplicate) { + super.duplicateAttributes(originalNodeComponent, forceDuplicate); + + Hashtable hashtable = originalNodeComponent.nodeHashtable; + + ShaderAppearanceRetained app = + (ShaderAppearanceRetained) originalNodeComponent.retained; + + ShaderAppearanceRetained rt = (ShaderAppearanceRetained) retained; + + rt.setShaderProgram((ShaderProgram) getNodeComponent(app.getShaderProgram(), + forceDuplicate, + hashtable)); + } + + /** + * This function is called from getNodeComponent() to see if any of + * the sub-NodeComponents duplicateOnCloneTree flag is true. + * If it is the case, current NodeComponent needs to + * duplicate also even though current duplicateOnCloneTree flag is false. + * This should be overwrite by NodeComponent which contains sub-NodeComponent. + */ + boolean duplicateChild() { + if (super.duplicateChild()) + return true; + + if (getDuplicateOnCloneTree()) + return true; + + ShaderAppearanceRetained rt = (ShaderAppearanceRetained) retained; + + NodeComponent nc; + + nc = rt.getShaderProgram(); + if ((nc != null) && nc.getDuplicateOnCloneTree()) + return true; + + return false; + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAppearanceRetained.java b/src/classes/share/javax/media/j3d/ShaderAppearanceRetained.java new file mode 100644 index 0000000..b8a1936 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAppearanceRetained.java @@ -0,0 +1,360 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.Vector; +import java.util.BitSet; +import java.util.ArrayList; + + +/** + * The Appearance object defines all rendering state that can be set + * as a component object of a Shape3D node. + */ +class ShaderAppearanceRetained extends AppearanceRetained { + + // + // State variables: these should all be initialized to approproate + // Java 3D defaults. + // + + protected ShaderProgramRetained shaderProgram = null; + protected ShaderAttributeSetRetained shaderAttributeSet = null; + protected boolean isMirror = false; // For Debugging. + + static final int SHADER_PROGRAM = 0x0800; + static final int SHADER_ATTRIBUTE_SET = 0x1000; + + /** + * Set the shader program object to the specified object. + * @param shaderProgram object that specifies the desired shader program + * and shader program attributes. + */ + void setShaderProgram(ShaderProgram sp) { + synchronized(liveStateLock) { + if (source.isLive()) { + // System.out.println("**** ShaderAppearceRetained.setShaderProgram()"); + + if (this.shaderProgram != null) { + this.shaderProgram.clearLive(refCount); + this.shaderProgram.removeMirrorUsers(this); + } + + if (sp != null) { + ((ShaderProgramRetained)sp.retained).setLive(inBackgroundGroup, + refCount); + ((ShaderProgramRetained)sp.retained).copyMirrorUsers(this); + } + + sendMessage(SHADER_PROGRAM, + (sp != null ? ((ShaderProgramRetained)sp.retained).mirror : null)); + + } + + if (sp == null) { + this.shaderProgram = null; + } else { + this.shaderProgram = (ShaderProgramRetained)sp.retained; + } + } + } + + + /** + * Retrieves the current shader program object. + * @return current shader program object + */ + ShaderProgram getShaderProgram() { + return (shaderProgram == null ? null : (ShaderProgram)shaderProgram.source); + } + + + /** + * Sets the ShaderAttributeSet object to the specified object. Setting it to + * null is equivalent to specifying an empty set of attributes. + * + * @param shaderAttributeSet object that specifies the desired shader attributes + */ + void setShaderAttributeSet(ShaderAttributeSet sas) { + synchronized(liveStateLock) { + if (source.isLive()) { + // System.out.println("**** ShaderAppearceRetained.setShaderAttributeSet()"); + + if (this.shaderAttributeSet != null) { + this.shaderAttributeSet.clearLive(refCount); + this.shaderAttributeSet.removeMirrorUsers(this); + } + + if (sas != null) { + ((ShaderAttributeSetRetained)sas.retained).setLive(inBackgroundGroup, + refCount); + ((ShaderAttributeSetRetained)sas.retained).copyMirrorUsers(this); + } + + // System.out.println(" -- testing needed!"); + sendMessage(SHADER_ATTRIBUTE_SET, + (sas != null ? + ((ShaderAttributeSetRetained)sas.retained).mirror : null)); + + } + + if (sas == null) { + this.shaderAttributeSet = null; + } else { + this.shaderAttributeSet = (ShaderAttributeSetRetained)sas.retained; + } + } + } + + + /** + * Retrieves the current ShaderAttributeSet object. + * @return current ShaderAttributeSet object + */ + ShaderAttributeSet getShaderAttributeSet() { + return (shaderAttributeSet == null ? null : (ShaderAttributeSet)shaderAttributeSet.source); + + } + + + public boolean equals(Object obj) { + System.out.println("ShaderAppearanceRetained : equals() not tested yet!"); + return ((obj instanceof ShaderAppearanceRetained) && + equals((ShaderAppearanceRetained) obj)); + } + + boolean equals(ShaderAppearanceRetained sApp) { + boolean flag; + flag = (sApp == this); + + // If the reference is the same, we can stop check. + if(flag) + return flag; + + // Check each member's reference for equal. + flag = ((sApp != null) && + (shaderProgram == sApp.shaderProgram) && + (shaderAttributeSet == sApp.shaderAttributeSet)); + + + if (!flag) + return flag; + + return super.equals(sApp); + + } + + + + synchronized void createMirrorObject() { + // System.out.println("ShaderAppearanceRetained : createMirrorObject()"); + + if (mirror == null) { + // we can't check isStatic() since it sub-NodeComponent + // create a new one, we should create a + // new AppearanceRetained() even though isStatic() = true. + // For simplicity, always create a retained side. + mirror = new ShaderAppearanceRetained(); + ((ShaderAppearanceRetained)mirror).isMirror = true; // For Debugging. + } + initMirrorObject(); + } + + /** + * This routine updates the mirror appearance for this appearance. + * It also calls the update method for each node component if it + * is not null. + */ + synchronized void initMirrorObject() { + // System.out.println("ShaderAppearanceRetained : initMirrorObject()"); + + super.initMirrorObject(); + + ShaderAppearanceRetained mirrorApp = (ShaderAppearanceRetained)mirror; + + if(shaderProgram != null) { + mirrorApp.shaderProgram = (ShaderProgramRetained)shaderProgram.mirror; + } + else { + mirrorApp.shaderProgram = null; + } + + if(shaderAttributeSet != null) { + mirrorApp.shaderAttributeSet = + (ShaderAttributeSetRetained)shaderAttributeSet.mirror; + } + else { + // System.out.println("shaderAttributeSet is null"); + mirrorApp.shaderAttributeSet = null; + } + + } + + /** + * Update the "component" field of the mirror object with the + * given "value" + */ + synchronized void updateMirrorObject(int component, Object value) { + + // System.out.println("ShaderAppearanceRetained : updateMirrorObject() this " + this); + super.updateMirrorObject(component, value); + ShaderAppearanceRetained mirrorApp = (ShaderAppearanceRetained)mirror; + if ((component & SHADER_PROGRAM) != 0) { + mirrorApp.shaderProgram = (ShaderProgramRetained)value; + } + else if ((component & SHADER_ATTRIBUTE_SET) != 0) { + mirrorApp.shaderAttributeSet = (ShaderAttributeSetRetained)value; + } + + } + + /** + * This method calls the setLive method of all appearance bundle + * objects. + */ + void doSetLive(boolean backgroundGroup, int refCount) { + // System.out.println("ShaderAppearceRetained.doSetLive()"); + + + if (shaderProgram != null) { + shaderProgram.setLive(backgroundGroup, refCount); + } + + if (shaderAttributeSet != null) { + shaderAttributeSet.setLive(backgroundGroup, refCount); + } + + + // Increment the reference count and initialize the appearance + // mirror object + super.doSetLive(backgroundGroup, refCount); + } + + + /** + * This clearLive routine first calls the superclass's method, then + * it removes itself to the list of lights + */ + void clearLive(int refCount) { + super.clearLive(refCount); + + if (shaderProgram != null) { + shaderProgram.clearLive(refCount); + } + + if (shaderAttributeSet != null) { + shaderAttributeSet.clearLive(refCount); + } + } + + synchronized void addAMirrorUser(Shape3DRetained shape) { + + super.addAMirrorUser(shape); + if (shaderProgram != null) + shaderProgram.addAMirrorUser(shape); + if (shaderAttributeSet != null) + shaderAttributeSet.addAMirrorUser(shape); + } + + synchronized void removeAMirrorUser(Shape3DRetained shape) { + + super.removeAMirrorUser(shape); + if (shaderProgram != null) + shaderProgram.removeAMirrorUser(shape); + if (shaderAttributeSet != null) + shaderAttributeSet.removeAMirrorUser(shape); + } + + + final void sendMessage(int attrMask, Object attr) { + ArrayList univList = new ArrayList(); + ArrayList gaList = Shape3DRetained.getGeomAtomsList(mirror.users, univList); + // Send to rendering attribute structure, regardless of + // whether there are users or not (alternate appearance case ..) + J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; + createMessage.type = J3dMessage.SHADER_APPEARANCE_CHANGED; + createMessage.universe = null; + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + createMessage.args[2] = attr; + createMessage.args[3] = new Integer(changedFrequent); + + VirtualUniverse.mc.processMessage(createMessage); + + //System.out.println("univList.size is " + univList.size()); + for(int i=0; i<univList.size(); i++) { + createMessage = VirtualUniverse.mc.getMessage(); + createMessage.threads = J3dThread.UPDATE_RENDER; + createMessage.type = J3dMessage.SHADER_APPEARANCE_CHANGED; + + createMessage.universe = (VirtualUniverse) univList.get(i); + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + createMessage.args[2] = attr; + + ArrayList gL = (ArrayList) gaList.get(i); + GeometryAtom[] gaArr = new GeometryAtom[gL.size()]; + gL.toArray(gaArr); + createMessage.args[3] = gaArr; + + VirtualUniverse.mc.processMessage(createMessage); + } + } + + + boolean isStatic() { + if (!super.isStatic()) { + return false; + } + + boolean flag = + source.capabilityBitsEmpty() && + ((shaderProgram == null) || + shaderProgram.source.capabilityBitsEmpty()) && + ((shaderAttributeSet == null) || + shaderAttributeSet.source.capabilityBitsEmpty()); + + return flag; + } + + + + boolean isOpaque(int geoType) { + + if (!super.isOpaque(geoType)) { + return false; + } + + // TODO: IMPLEMENT THIS + // TODO: How do we determine whether a ShaderAppearance is opaque??? + return true; + } + + void handleFrequencyChange(int bit) { + // System.out.println("ShaderAppearanceRetained : handleFrequencyChange()"); + super.handleFrequencyChange(bit); + + int mask = 0; + if (bit == ShaderAppearance.ALLOW_SHADER_PROGRAM_WRITE) + mask = SHADER_PROGRAM; + else if (bit == ShaderAppearance.ALLOW_SHADER_ATTRIBUTE_SET_WRITE) + mask = SHADER_ATTRIBUTE_SET; + + + if (mask != 0) + setFrequencyChangeMask(bit, mask); + } +} + + diff --git a/src/classes/share/javax/media/j3d/ShaderAttribute.java b/src/classes/share/javax/media/j3d/ShaderAttribute.java new file mode 100644 index 0000000..7618492 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttribute.java @@ -0,0 +1,77 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttribute object encapsulates a uniform attribute for a + * shader programs. Uniform attributes (variables) are those + * attributes whose values are constant during the rendering of a + * primitive. Their values may change from primitive to primitive, but + * are constant for each vertex (for vertex shaders) or fragment (for + * fragment shaders) of a single primitive. Examples of uniform + * attributes include a transformation matrix, a texture map, lights, + * lookup tables, etc. + * + * <p> + * There are two ways in which values can be specified for uniform + * attributes: explicitly, by providing a value; and implicitly, by + * defining a binding between a Java 3D system attribute and a uniform + * attribute. This functionality is provided by two subclasses of + * ShaderAttribute as follows: + * + * <ul> + * <li>ShaderAttributeObject, in which attributes are expressed as + * <code>(attrName, value)</code> pairs, is used for explicitly + * defined attributes</li> + * <li>ShaderAttributeBinding, in which attributes are expressed as + * <code>(attrName, j3dAttrName)</code> pairs, is used for + * implicitly defined, automatically tracked attributes</li> + * </ul> + * + * @see ShaderAttributeSet + * @see ShaderProgram + * + * @since Java 3D 1.4 + */ + +public abstract class ShaderAttribute extends NodeComponent { + /** + * Name of the shader attribute (immutable) + */ + + /** + * Package scope constructor + * + */ + ShaderAttribute(String attrName) { + if (attrName == null) { + throw new NullPointerException(); + } + + ((ShaderAttributeRetained)this.retained).initializeAttrName(attrName); + } + + /** + * Retrieves the name of this shader attribute. + * + * @return the name of this shader attribute + */ + public String getAttributeName() { + + return ((ShaderAttributeRetained)this.retained).getAttributeName(); + + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeArray.java b/src/classes/share/javax/media/j3d/ShaderAttributeArray.java new file mode 100644 index 0000000..c5ee3db --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeArray.java @@ -0,0 +1,147 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeArray object encapsulates a uniform shader + * attribute whose value is specified explicitly. The shader variable + * <code>attrName</code> is explicitly set to the specified + * <code>value</code> during rendering. <code>attrName</code> must be + * the name of a valid uniform attribute in the shader in which it is + * used. Otherwise, the attribute name will be ignored and a runtime + * error may be generated. The <code>value</code> must be an array + * of one of the allowed classes. The allowed classes are: + * <code>Integer[]</code>, <code>Float[]</code>, + * <code>Tuple{2,3,4}{i,f}[]</code>, <code>Matrix{3,4}f[]</code>. A + * ClassCastException will be thrown if a specified <code>value</code> + * object is not one of the allowed types. Further, the type and length of the + * value is immutable once a ShaderAttributeArray is constructed. + * Subsequent setValue operations must be called with an array of the + * same type and length as the one that was used to construct the + * ShaderAttributeArray. Finally, the type of the <code>value</code> + * object must match the type of the corresponding + * <code>attrName</code> variable in the shader in which it is + * used. Otherwise, the shader will not be able to use the attribute + * and a runtime error may be generated. + * + * @see ShaderAttributeSet + * @see ShaderProgram + * + * @since Java 3D 1.4 + */ + +public class ShaderAttributeArray extends ShaderAttributeObject { + /** + * Constructs a new ShaderAttributeArray object with the specified + * <code>(attrName, value)</code> pair. The specified value + * must be an array of one of the allowed class types. + * A deep copy of the array is stored. + * + * @param attrName the name of the shader attribute + * @param value the value of the shader attribute + * + * @exception NullPointerException if attrName or value is null + * + * @exception ClassCastException if value is not an array of + * one of the allowed classes + */ + public ShaderAttributeArray(String attrName, Object value) { + super(attrName, value); + } + + // Implement abstract getValue method + public Object getValue() { + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_VALUE_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeObject0")); + + return ((ShaderAttributeArrayRetained)this.retained).getValue(); + } + + // Implement abstract setValue method + public void setValue(Object value) { + if (value == null) { + throw new NullPointerException(); + } + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_VALUE_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeObject1")); + + if (isLive()) + ((ShaderAttributeArrayRetained)this.retained).setValue(value); + else + ((ShaderAttributeArrayRetained)this.retained).initValue(value); + + } + + + /** + * Sets the specified array element of the value of this shader + * attribute to the specified value. + * A copy of the object is stored. + * + * @param value the new value of the shader attribute + * + * @exception NullPointerException if value is null + * + * @exception ClassCastException if value is not an instance of + * the same base class as the individual elements of the array object + * used to construct this shader attribute object. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public void setValue(int index, Object value) { + if (value == null) { + throw new NullPointerException(); + } + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_VALUE_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeObject1")); + + if (isLive()) + ((ShaderAttributeArrayRetained)this.retained).setValue(index, value); + else { + ((ShaderAttributeArrayRetained)this.retained).initValue(index, value); + } + } + + /** + * Returns the number of elements in the value array. + * + * @return the number of elements in the value array + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public int length() { + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_VALUE_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeObject0")); + + return ((ShaderAttributeArrayRetained)this.retained).length(); + } + + /** + * Creates a retained mode ShaderAttributeArrayRetained object that this + * ShaderAttributeArray component object will point to. + */ + void createRetained() { + this.retained = new ShaderAttributeArrayRetained(); + this.retained.setSource(this); + } +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeArrayRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeArrayRetained.java new file mode 100644 index 0000000..f4d4a42 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeArrayRetained.java @@ -0,0 +1,996 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeArray object encapsulates a uniform shader + * attribute whose value is specified explicitly. The shader variable + * <code>attrName</code> is explicitly set to the specified + * <code>value</code> during rendering. <code>attrName</code> must be + * the name of a valid uniform attribute in the shader in which it is + * used. Otherwise, the attribute name will be ignored and a runtime + * error may be generated. The <code>value</code> must be an array + * of one of the allowed classes. The allowed classes are: + * <code>Integer[]</code>, <code>Float[]</code>, + * <code>Tuple{2,3,4}{i,f}[]</code>, <code>Matrix{3,4}f[]</code>. A + * ClassCastException will be thrown if a specified <code>value</code> + * object is not one of the allowed types. Further, the type and length of the + * value is immutable once a ShaderAttributeArray is constructed. + * Subsequent setValue operations must be called with an array of the + * same type and length as the one that was used to construct the + * ShaderAttributeArray. Finally, the type of the <code>value</code> + * object must match the type of the corresponding + * <code>attrName</code> variable in the shader in which it is + * used. Otherwise, the shader will not be able to use the attribute + * and a runtime error may be generated. + * + * @see ShaderAttributeSet + * @see ShaderProgram + * + * @since Java 3D 1.4 + */ + +class ShaderAttributeArrayRetained extends ShaderAttributeObjectRetained { + + ShaderAttributeArrayRetained() { + } + + void initValue(int index, Object value) { + /* + System.err.println("ShaderAttributeObjectRetained : attrName = " + attrName + + ", index = " + index + ", value = " + value + + ", value.class = " + value.getClass()); + */ + ((ArrayWrapper)attrWrapper).set(index, value); + + } + + + /** + * Sets the specified array element of the value of this shader + * attribute to the specified value. + * A copy of the object is stored. + * + * @param value the new value of the shader attribute + * + * @exception NullPointerException if value is null + * + * @exception ClassCastException if value is not an instance of + * the same base class as the individual elements of the array object + * used to construct this shader attribute object. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + void setValue(int index, Object value) { + initValue(index, value); + // We should only need to update the array instead of replacing it. + // Until this become a really bottleneck, it will just be a convenience + // method for end user. + // An efficient approach is to + // (1) Create a new ShaderAttributeValue object for the "value" object + // and pass it to sendMessage(), (2) Create a new sendMessage that take in + // a third arguement, ie. index. + setValue(attrWrapper.getRef()); + } + + /** + * Returns the number of elements in the value array. + * + * @return the number of elements in the value array + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + int length() { + return ((ArrayWrapper)attrWrapper).length(); + + } + + // Helper methods ... + + synchronized void createMirrorObject() { + // System.out.println("ShaderAttributeArrayRetained : createMirrorObject"); + // This method should only call by setLive(). + if (mirror == null) { + ShaderAttributeArrayRetained mirrorSAA = new ShaderAttributeArrayRetained(); + mirrorSAA.createObjectData(getValue()); + mirror = mirrorSAA; + mirror.source = source; + + } + initMirrorObject(); + } + + + /** + * Computes the base class from the specified object. A + * ClassCastException is thrown if the object is not an array of + * one of the allowed classes. + */ + int computeClassType(Object value) { + Class objClass = value.getClass(); + if (!objClass.isArray()) { + throw new ClassCastException(objClass + " -- must be array class"); + } + + for (int i = 0; i < classTable.length; i++) { + if (classTableArr[i].isInstance(value)) { + return i; + } + } + throw new ClassCastException(objClass + " -- unrecognized class"); + } + + /** + * Returns the base class represented by the specified class type. + */ + Class getBaseClass(int classType) { + return classTableArr[classType]; + } + + /** + * Creates an attribute wrapper object of the specified class + * type, and stores the specified array of objects. + */ + AttrWrapper createAttrWrapper(Object value, int classType) { + ArrayWrapper attrWrapper = null; + switch (classType) { + case TYPE_INTEGER: + attrWrapper = new IntegerArrayWrapper(); + break; + case TYPE_FLOAT: + attrWrapper = new FloatArrayWrapper(); + break; +// case TYPE_DOUBLE: +// attrWrapper = new DoubleArrayWrapper(); +// break; + case TYPE_TUPLE2I: + attrWrapper = new Tuple2iArrayWrapper(); + break; + case TYPE_TUPLE2F: + attrWrapper = new Tuple2fArrayWrapper(); + break; +// case TYPE_TUPLE2D: +// attrWrapper = new Tuple2dArrayWrapper(); +// break; + case TYPE_TUPLE3I: + attrWrapper = new Tuple3iArrayWrapper(); + break; + case TYPE_TUPLE3F: + attrWrapper = new Tuple3fArrayWrapper(); + break; +// case TYPE_TUPLE3D: +// attrWrapper = new Tuple3dArrayWrapper(); +// break; + case TYPE_TUPLE4I: + attrWrapper = new Tuple4iArrayWrapper(); + break; + case TYPE_TUPLE4F: + attrWrapper = new Tuple4fArrayWrapper(); + break; +// case TYPE_TUPLE4D: +// attrWrapper = new Tuple4dArrayWrapper(); +// break; + case TYPE_MATRIX3F: + attrWrapper = new Matrix3fArrayWrapper(); + break; +// case TYPE_MATRIX3D: +// attrWrapper = new Matrix3dArrayWrapper(); +// break; + case TYPE_MATRIX4F: + attrWrapper = new Matrix4fArrayWrapper(); + break; +// case TYPE_MATRIX4D: +// attrWrapper = new Matrix4dArrayWrapper(); +// break; + default: + // Should never get here + assert false; + return null; + } + + attrWrapper.set(value); + return attrWrapper; + } + + + // + // The following wrapper classes are used to store a copy of the + // user-specified shader attribute value. There is a wrapper class + // for each supported base class. + // + + // Base wrapper class for array attribute types + static abstract class ArrayWrapper extends AttrWrapper { + int length = 0; + + /** + * Returns the length of the array + */ + int length() { + return length; + } + + /** + * Sets the specified array element of the value of this + * shader attribute to the specified value. + */ + abstract void set(int index, Object value); + } + + // Wrapper class for Integer + static class IntegerArrayWrapper extends ArrayWrapper { + private int[] value = new int[0]; + + void set(Object value) { + Integer[] arr = (Integer[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new int[this.length]; + } + for (int i = 0; i < this.length; i++) { + this.value[i] = arr[i].intValue(); + } + } + + void set(int index, Object value) { + this.value[index] = ((Integer)value).intValue(); + } + + Object get() { + Integer[] arr = new Integer[this.length]; + for (int i = 0; i < this.length; i++) { + arr[i] = new Integer(this.value[i]); + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + // Wrapper class for Float + static class FloatArrayWrapper extends ArrayWrapper { + private float[] value = new float[0]; + + void set(Object value) { + Float[] arr = (Float[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new float[this.length]; + } + for (int i = 0; i < this.length; i++) { + this.value[i] = arr[i].floatValue(); + } + } + + void set(int index, Object value) { + this.value[index] = ((Float)value).floatValue(); + } + + Object get() { + Float[] arr = new Float[this.length]; + for (int i = 0; i < this.length; i++) { + arr[i] = new Float(this.value[i]); + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + /* + // Wrapper class for Double + static class DoubleArrayWrapper extends ArrayWrapper { + private double[] value = new double[0]; + + void set(Object value) { + Double[] arr = (Double[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new double[this.length]; + } + for (int i = 0; i < this.length; i++) { + this.value[i] = arr[i].doubleValue(); + } + } + + void set(int index, Object value) { + this.value[index] = ((Double)value).doubleValue(); + } + + Object get() { + Double[] arr = new Double[this.length]; + for (int i = 0; i < this.length; i++) { + arr[i] = new Double(this.value[i]); + } + return arr; + } + + Object getRef() { + return this.value; + } + } + */ + + // Wrapper class for Tuple2i + static class Tuple2iArrayWrapper extends ArrayWrapper { + private int[] value = new int[0]; + + void set(Object value) { + Tuple2i[] arr = (Tuple2i[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new int[this.length*2]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 2; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + } + } + + void set(int index, Object value) { + int j = index * 2; + this.value[j+0] = ((Tuple2i)value).x; + this.value[j+1] = ((Tuple2i)value).y; + } + + Object get() { + Tuple2i[] arr = new Tuple2i[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 2; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + // Wrapper class for Tuple2f + static class Tuple2fArrayWrapper extends ArrayWrapper { + private float[] value = new float[0]; + + void set(Object value) { + Tuple2f[] arr = (Tuple2f[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new float[this.length*2]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 2; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + } + } + + void set(int index, Object value) { + int j = index * 2; + this.value[j+0] = ((Tuple2f)value).x; + this.value[j+1] = ((Tuple2f)value).y; + } + + Object get() { + Tuple2f[] arr = new Tuple2f[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 2; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + /* + // Wrapper class for Tuple2d + static class Tuple2dArrayWrapper extends ArrayWrapper { + private double[] value = new double[0]; + + void set(Object value) { + Tuple2d[] arr = (Tuple2d[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new double[this.length*2]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 2; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + } + } + + void set(int index, Object value) { + int j = index * 2; + this.value[j+0] = ((Tuple2d)value).x; + this.value[j+1] = ((Tuple2d)value).y; + } + + Object get() { + Tuple2d[] arr = new Tuple2d[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 2; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + */ + + // Wrapper class for Tuple3i + static class Tuple3iArrayWrapper extends ArrayWrapper { + private int[] value = new int[0]; + + void set(Object value) { + Tuple3i[] arr = (Tuple3i[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new int[this.length*3]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 3; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + this.value[j+2] = arr[i].z; + } + } + + void set(int index, Object value) { + int j = index * 3; + this.value[j+0] = ((Tuple3i)value).x; + this.value[j+1] = ((Tuple3i)value).y; + this.value[j+2] = ((Tuple3i)value).z; + } + + Object get() { + Tuple3i[] arr = new Tuple3i[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 3; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + arr[i].z = this.value[j+2]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + // Wrapper class for Tuple3f + static class Tuple3fArrayWrapper extends ArrayWrapper { + private float[] value = new float[0]; + + void set(Object value) { + Tuple3f[] arr = (Tuple3f[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new float[this.length*3]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 3; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + this.value[j+2] = arr[i].z; + } + } + + void set(int index, Object value) { + int j = index * 3; + this.value[j+0] = ((Tuple3f)value).x; + this.value[j+1] = ((Tuple3f)value).y; + this.value[j+2] = ((Tuple3f)value).z; + } + + Object get() { + Tuple3f[] arr = new Tuple3f[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 3; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + arr[i].z = this.value[j+2]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + /* + // Wrapper class for Tuple3d + static class Tuple3dArrayWrapper extends ArrayWrapper { + private double[] value = new double[0]; + + void set(Object value) { + Tuple3d[] arr = (Tuple3d[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new double[this.length*3]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 3; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + this.value[j+2] = arr[i].z; + } + } + + void set(int index, Object value) { + int j = index * 3; + this.value[j+0] = ((Tuple3d)value).x; + this.value[j+1] = ((Tuple3d)value).y; + this.value[j+2] = ((Tuple3d)value).z; + } + + Object get() { + Tuple3d[] arr = new Tuple3d[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 3; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + arr[i].z = this.value[j+2]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + */ + + // Wrapper class for Tuple4i + static class Tuple4iArrayWrapper extends ArrayWrapper { + private int[] value = new int[0]; + + void set(Object value) { + Tuple4i[] arr = (Tuple4i[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new int[this.length*4]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 4; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + this.value[j+2] = arr[i].z; + this.value[j+3] = arr[i].w; + } + } + + void set(int index, Object value) { + int j = index * 4; + this.value[j+0] = ((Tuple4i)value).x; + this.value[j+1] = ((Tuple4i)value).y; + this.value[j+2] = ((Tuple4i)value).z; + this.value[j+3] = ((Tuple4i)value).w; + } + + Object get() { + Tuple4i[] arr = new Tuple4i[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 4; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + arr[i].z = this.value[j+2]; + arr[i].w = this.value[j+3]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + // Wrapper class for Tuple4f + static class Tuple4fArrayWrapper extends ArrayWrapper { + private float[] value = new float[0]; + + void set(Object value) { + Tuple4f[] arr = (Tuple4f[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new float[this.length*4]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 4; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + this.value[j+2] = arr[i].z; + this.value[j+3] = arr[i].w; + } + } + + void set(int index, Object value) { + int j = index * 4; + this.value[j+0] = ((Tuple4f)value).x; + this.value[j+1] = ((Tuple4f)value).y; + this.value[j+2] = ((Tuple4f)value).z; + this.value[j+3] = ((Tuple4f)value).w; + } + + Object get() { + Tuple4f[] arr = new Tuple4f[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 4; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + arr[i].z = this.value[j+2]; + arr[i].w = this.value[j+3]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + /* + // Wrapper class for Tuple4d + static class Tuple4dArrayWrapper extends ArrayWrapper { + private double[] value = new double[0]; + + void set(Object value) { + Tuple4d[] arr = (Tuple4d[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new double[this.length*4]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 4; + this.value[j+0] = arr[i].x; + this.value[j+1] = arr[i].y; + this.value[j+2] = arr[i].z; + this.value[j+3] = arr[i].w; + } + } + + void set(int index, Object value) { + int j = index * 4; + this.value[j+0] = ((Tuple4d)value).x; + this.value[j+1] = ((Tuple4d)value).y; + this.value[j+2] = ((Tuple4d)value).z; + this.value[j+3] = ((Tuple4d)value).w; + } + + Object get() { + Tuple4d[] arr = new Tuple4d[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 4; + arr[i].x = this.value[j+0]; + arr[i].y = this.value[j+1]; + arr[i].z = this.value[j+2]; + arr[i].w = this.value[j+3]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + */ + + // Wrapper class for Matrix3f + static class Matrix3fArrayWrapper extends ArrayWrapper { + private float[] value = new float[0]; + + void set(Object value) { + Matrix3f[] arr = (Matrix3f[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new float[this.length * 9]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 9; + this.value[j+0] = arr[i].m00; + this.value[j+1] = arr[i].m01; + this.value[j+2] = arr[i].m02; + this.value[j+3] = arr[i].m10; + this.value[j+4] = arr[i].m11; + this.value[j+5] = arr[i].m12; + this.value[j+6] = arr[i].m20; + this.value[j+7] = arr[i].m21; + this.value[j+8] = arr[i].m22; + } + } + + void set(int index, Object value) { + int j = index * 9; + Matrix3f m = (Matrix3f)value; + + this.value[j+0] = m.m00; + this.value[j+1] = m.m01; + this.value[j+2] = m.m02; + this.value[j+3] = m.m10; + this.value[j+4] = m.m11; + this.value[j+5] = m.m12; + this.value[j+6] = m.m20; + this.value[j+7] = m.m21; + this.value[j+8] = m.m22; + } + + Object get() { + Matrix3f[] arr = new Matrix3f[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 9; + arr[i].m00 = this.value[j+0]; + arr[i].m01 = this.value[j+1]; + arr[i].m02 = this.value[j+2]; + arr[i].m10 = this.value[j+3]; + arr[i].m11 = this.value[j+4]; + arr[i].m12 = this.value[j+5]; + arr[i].m20 = this.value[j+6]; + arr[i].m21 = this.value[j+7]; + arr[i].m22 = this.value[j+8]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + /* + // Wrapper class for Matrix3d + static class Matrix3dArrayWrapper extends ArrayWrapper { + private double[] value = new double[0]; + + void set(Object value) { + Matrix3d[] arr = (Matrix3d[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new double[this.length * 9]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 9; + this.value[j+0] = arr[i].m00; + this.value[j+1] = arr[i].m01; + this.value[j+2] = arr[i].m02; + this.value[j+3] = arr[i].m10; + this.value[j+4] = arr[i].m11; + this.value[j+5] = arr[i].m12; + this.value[j+6] = arr[i].m20; + this.value[j+7] = arr[i].m21; + this.value[j+8] = arr[i].m22; + } + } + + void set(int index, Object value) { + int j = index * 9; + Matrix3d m = (Matrix3d)value; + + this.value[j+0] = m.m00; + this.value[j+1] = m.m01; + this.value[j+2] = m.m02; + this.value[j+3] = m.m10; + this.value[j+4] = m.m11; + this.value[j+5] = m.m12; + this.value[j+6] = m.m20; + this.value[j+7] = m.m21; + this.value[j+8] = m.m22; + } + + Object get() { + Matrix3d[] arr = new Matrix3d[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 9; + arr[i].m00 = this.value[j+0]; + arr[i].m01 = this.value[j+1]; + arr[i].m02 = this.value[j+2]; + arr[i].m10 = this.value[j+3]; + arr[i].m11 = this.value[j+4]; + arr[i].m12 = this.value[j+5]; + arr[i].m20 = this.value[j+6]; + arr[i].m21 = this.value[j+7]; + arr[i].m22 = this.value[j+8]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + */ + + // Wrapper class for Matrix4f + static class Matrix4fArrayWrapper extends ArrayWrapper { + private float[] value = new float[0]; + + void set(Object value) { + Matrix4f[] arr = (Matrix4f[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new float[this.length * 16]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 16; + this.value[j+0] = arr[i].m00; + this.value[j+1] = arr[i].m01; + this.value[j+2] = arr[i].m02; + this.value[j+3] = arr[i].m03; + this.value[j+4] = arr[i].m10; + this.value[j+5] = arr[i].m11; + this.value[j+6] = arr[i].m12; + this.value[j+7] = arr[i].m13; + this.value[j+8] = arr[i].m20; + this.value[j+9] = arr[i].m21; + this.value[j+10] = arr[i].m22; + this.value[j+11] = arr[i].m23; + this.value[j+12] = arr[i].m30; + this.value[j+13] = arr[i].m31; + this.value[j+14] = arr[i].m32; + this.value[j+15] = arr[i].m33; + } + } + + void set(int index, Object value) { + int j = index * 16; + Matrix4f m = (Matrix4f)value; + + this.value[j+0] = m.m00; + this.value[j+1] = m.m01; + this.value[j+2] = m.m02; + this.value[j+3] = m.m03; + this.value[j+4] = m.m10; + this.value[j+5] = m.m11; + this.value[j+6] = m.m12; + this.value[j+7] = m.m13; + this.value[j+8] = m.m20; + this.value[j+9] = m.m21; + this.value[j+10] = m.m22; + this.value[j+11] = m.m23; + this.value[j+12] = m.m30; + this.value[j+13] = m.m31; + this.value[j+14] = m.m32; + this.value[j+15] = m.m33; + } + + Object get() { + Matrix4f[] arr = new Matrix4f[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 16; + arr[i].m00 = this.value[j+0]; + arr[i].m01 = this.value[j+1]; + arr[i].m02 = this.value[j+2]; + arr[i].m03 = this.value[j+3]; + arr[i].m10 = this.value[j+4]; + arr[i].m11 = this.value[j+5]; + arr[i].m12 = this.value[j+6]; + arr[i].m13 = this.value[j+7]; + arr[i].m20 = this.value[j+8]; + arr[i].m21 = this.value[j+9]; + arr[i].m22 = this.value[j+10]; + arr[i].m23 = this.value[j+11]; + arr[i].m30 = this.value[j+12]; + arr[i].m31 = this.value[j+13]; + arr[i].m32 = this.value[j+14]; + arr[i].m33 = this.value[j+15]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + + /* + // Wrapper class for Matrix4d + static class Matrix4dArrayWrapper extends ArrayWrapper { + private double[] value = new double[0]; + + void set(Object value) { + Matrix4d[] arr = (Matrix4d[])value; + if (this.length != arr.length) { + this.length = arr.length; + this.value = new double[this.length * 16]; + } + for (int i = 0; i < this.length; i++) { + int j = i * 16; + this.value[j+0] = arr[i].m00; + this.value[j+1] = arr[i].m01; + this.value[j+2] = arr[i].m02; + this.value[j+3] = arr[i].m03; + this.value[j+4] = arr[i].m10; + this.value[j+5] = arr[i].m11; + this.value[j+6] = arr[i].m12; + this.value[j+7] = arr[i].m13; + this.value[j+8] = arr[i].m20; + this.value[j+9] = arr[i].m21; + this.value[j+10] = arr[i].m22; + this.value[j+11] = arr[i].m23; + this.value[j+12] = arr[i].m30; + this.value[j+13] = arr[i].m31; + this.value[j+14] = arr[i].m32; + this.value[j+15] = arr[i].m33; + } + } + + void set(int index, Object value) { + int j = index * 16; + Matrix4d m = (Matrix4d)value; + + this.value[j+0] = m.m00; + this.value[j+1] = m.m01; + this.value[j+2] = m.m02; + this.value[j+3] = m.m03; + this.value[j+4] = m.m10; + this.value[j+5] = m.m11; + this.value[j+6] = m.m12; + this.value[j+7] = m.m13; + this.value[j+8] = m.m20; + this.value[j+9] = m.m21; + this.value[j+10] = m.m22; + this.value[j+11] = m.m23; + this.value[j+12] = m.m30; + this.value[j+13] = m.m31; + this.value[j+14] = m.m32; + this.value[j+15] = m.m33; + } + + Object get() { + Matrix4d[] arr = new Matrix4d[this.length]; + for (int i = 0; i < this.length; i++) { + int j = i * 16; + arr[i].m00 = this.value[j+0]; + arr[i].m01 = this.value[j+1]; + arr[i].m02 = this.value[j+2]; + arr[i].m03 = this.value[j+3]; + arr[i].m10 = this.value[j+4]; + arr[i].m11 = this.value[j+5]; + arr[i].m12 = this.value[j+6]; + arr[i].m13 = this.value[j+7]; + arr[i].m20 = this.value[j+8]; + arr[i].m21 = this.value[j+9]; + arr[i].m22 = this.value[j+10]; + arr[i].m23 = this.value[j+11]; + arr[i].m30 = this.value[j+12]; + arr[i].m31 = this.value[j+13]; + arr[i].m32 = this.value[j+14]; + arr[i].m33 = this.value[j+15]; + } + return arr; + } + + Object getRef() { + return this.value; + } + } + */ +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeBinding.java b/src/classes/share/javax/media/j3d/ShaderAttributeBinding.java new file mode 100644 index 0000000..608fbfc --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeBinding.java @@ -0,0 +1,128 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeBinding object encapsulates a uniform attribute + * whose value is bound to a Java 3D system attribute. The + * shader variable <code>attrName</code> is implicitly set to the + * value of the corresponding Java 3D system attribute + * <code>j3dAttrName</code> during rendering. <code>attrName</code> + * must be the name of a valid uniform attribute in the shader in + * which it is used. Otherwise, the attribute name will be ignored and + * a runtime error may be generated. <code>j3dAttrName</code> must be + * the name of a predefined Java 3D system attribute. An + * IllegalArgumentException will be thrown if the specified + * <code>j3dAttrName</code> is not one of the predefined system + * attributes. Further, the type of the <code>j3dAttrName</code> + * attribute must match the type of the corresponding + * <code>attrName</code> variable in the shader in which it is + * used. Otherwise, the shader will not be able to use the attribute + * and a runtime error may be generated. + * + * <p> + * Following is the list of predefined Java 3D system attributes:<br> + * + * <ul> + * <font color="#ff0000"><i>TODO: replace the following with + * the real system attributes table</i></font><br> + * <table BORDER=1 CELLSPACING=2 CELLPADDING=2> + * <tr> + * <td><b>Name</b></td> + * <td><b>Type</b></td> + * <td><b>Description</b></td> + * </tr> + * <tr> + * <td><code>something</code></td> + * <td>Float</td> + * <td>This is something (of course)</td> + * </tr> + * <tr> + * <td><code>somethingElse</code></td> + * <td>Tuple3f</td> + * <td>This is something else</td> + * </tr> + * </table> + * </ul> + * + * <p> + * Depending on the shading language (and profile) being used, several + * Java 3D state attributes are automatically made available to the + * shader program as pre-defined uniform attributes. The application + * doesn't need to do anything to pass these attributes in to the + * shader program. The implementation of each shader language (e.g., + * Cg, GLSL) defines its own mapping from Java 3D attribute to uniform + * variable name. + * + * <p> + * A list of these attributes for each shader language can be found in + * the concrete subclass of ShaderProgram for that shader language. + * + * <p> + * <font color="#ff0000"><i>NOTE: This class is not yet + * implemented.</i></font><br> + * + * @see ShaderAttributeSet + * @see ShaderProgram + * + * @since Java 3D 1.4 + */ + +public class ShaderAttributeBinding extends ShaderAttribute { + + /** + * Constructs a new ShaderAttributeBinding from the specified + * <code>(attrName, j3dAttrName)</code> pair. + * + * @param attrName the name of the shader attribute to be added + * @param j3dAttrName the name of the Java 3D attribute + * to bind to the shader attribute + * + * @exception UnsupportedOperationException this class is not + * yet implemented + * + * @exception NullPointerException if attrName or j3dAttrName is null + * + * @exception IllegalArgumentException if j3dAttrName is not the name + * of a valid predefined Java 3D system attribute + */ + public ShaderAttributeBinding(String attrName, String j3dAttrName) { + super(attrName); + ((ShaderAttributeBindingRetained)this.retained).initJ3dAttrName(j3dAttrName); + // TODO: implement this class + throw new UnsupportedOperationException(J3dI18N.getString("ShaderAttributeBinding0")); + } + + /** + * Retrieves the name of the Java 3D system attribute that is bound to this + * shader attribute. + * + * @return the name of the Java 3D system attribute that is bound to this + * shader attribute + */ + public String getJ3DAttributeName() { + return ((ShaderAttributeBindingRetained)this.retained).getJ3DAttributeName(); + } + + /** + * Creates a retained mode ShaderAttributeBindingRetained object that this + * ShaderAttributeBinding component object will point to. + */ + void createRetained() { + this.retained = new ShaderAttributeBindingRetained(); + this.retained.setSource(this); + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeBindingRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeBindingRetained.java new file mode 100644 index 0000000..b580406 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeBindingRetained.java @@ -0,0 +1,57 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeBinding object encapsulates a uniform attribute + * whose value is bound to a Java 3D system attribute. The + * shader variable <code>attrName</code> is implicitly set to the + * value of the corresponding Java 3D system attribute + * <code>j3dAttrName</code> during rendering. <code>attrName</code> + * must be the name of a valid uniform attribute in the shader in + * which it is used. Otherwise, the attribute name will be ignored and + * a runtime error may be generated. <code>j3dAttrName</code> must be + * the name of a predefined Java 3D system attribute. An + * IllegalArgumentException will be thrown if the specified + * <code>j3dAttrName</code> is not one of the predefined system + * attributes. Further, the type of the <code>j3dAttrName</code> + * attribute must match the type of the corresponding + * <code>attrName</code> variable in the shader in which it is + * used. Otherwise, the shader will not be able to use the attribute + * and a runtime error may be generated. + */ + +class ShaderAttributeBindingRetained extends ShaderAttributeRetained { + String j3dAttrName; + + ShaderAttributeBindingRetained() { + } + + void initJ3dAttrName(String j3dAttrName) { + this.j3dAttrName = j3dAttrName; + } + + /** + * Retrieves the name of the Java 3D system attribute that is bound to this + * shader attribute. + * + * @return the name of the Java 3D system attribute that is bound to this + * shader attribute + */ + String getJ3DAttributeName() { + return j3dAttrName; + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeObject.java b/src/classes/share/javax/media/j3d/ShaderAttributeObject.java new file mode 100644 index 0000000..b3a275d --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeObject.java @@ -0,0 +1,130 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeObject class is an abstract class that + * encapsulates a uniform shader attribute whose value is specified + * explicitly. This class has concrete subclasses for single-value + * attributes (ShaderAttributeValue) and array attributes + * (ShaderAttributeArray). The shader variable <code>attrName</code> + * is explicitly set to the specified <code>value</code> during + * rendering. <code>attrName</code> must be the name of a valid + * uniform attribute in the shader in which it is used. Otherwise, the + * attribute name will be ignored and a runtime error may be + * generated. The <code>value</code> must be an instance of one of the + * allowed classes or an array of one the allowed classes. The allowed + * classes are: <code>Integer</code>, <code>Float</code>, + * <code>Tuple{2,3,4}{i,f}</code>, + * <code>Matrix{3,4}f</code>. A ClassCastException will be thrown + * if a specified <code>value</code> object is not one of the allowed + * types. Further, the type of the value is immutable once a + * ShaderAttributeObject is constructed. Subsequent setValue + * operations must be called with an object of the same type as the + * one that was used to construct the ShaderAttributeObject. Finally, + * the type of the <code>value</code> object must match the type of + * the corresponding <code>attrName</code> variable in the shader in + * which it is used. Otherwise, the shader will not be able to use the + * attribute and a runtime error may be generated. + * + * @see ShaderAttributeSet + * @see ShaderProgram + * + * @since Java 3D 1.4 + */ + +public abstract class ShaderAttributeObject extends ShaderAttribute { + + /** + * Specifies that this ShaderAttributeObject allows reading its value. + */ + public static final int + ALLOW_VALUE_READ = + CapabilityBits.SHADER_ATTRIBUTE_OBJECT_ALLOW_VALUE_READ; + + /** + * Specifies that this ShaderAttributeObject allows writing its value. + */ + public static final int + ALLOW_VALUE_WRITE = + CapabilityBits.SHADER_ATTRIBUTE_OBJECT_ALLOW_VALUE_WRITE; + + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_VALUE_READ + }; + + + /** + * Package scope constructor + */ + ShaderAttributeObject(String attrName, Object value) { + super(attrName); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((ShaderAttributeObjectRetained)this.retained).createObjectData(value); + } + + + /** + * Retrieves the value of this shader attribute. + * A copy of the object is returned. + * + * @return a copy of the value of this shader attribute + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public abstract Object getValue(); + + /** + * Sets the value of this shader attribute to the specified value. + * A copy of the object is stored. + * + * @param value the new value of the shader attribute + * + * @exception NullPointerException if value is null + * + * @exception ClassCastException if value is not an instance of + * the same base class as the object used to construct this shader + * attribute object. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public abstract void setValue(Object value); + + /** + * Retrieves the base class of the value of this shader attribute. + * This class will always be one of the allowable classes, even if + * a subclass was used to construct this shader attribute object. + * For example, if this shader attribute object was constructed + * with an instance of <code>javax.vecmath.Point3f</code>, the + * returned class would be <code>javax.vecmath.Tuple3f</code>. + * + * @return the base class of the value of this shader attribute + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public Class getValueClass() { + + return ((ShaderAttributeObjectRetained)this.retained).getValueClass(); + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeObjectRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeObjectRetained.java new file mode 100644 index 0000000..a66335c --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeObjectRetained.java @@ -0,0 +1,311 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.ArrayList; +import javax.vecmath.*; + +/** + * The ShaderAttributeObjectRetained class is an abstract class that + * encapsulates a uniform shader attribute whose value is specified + * explicitly. This class has concrete subclasses for single-value + * attributes (ShaderAttributeValueRetained) and array attributes + * (ShaderAttributeArrayRetained). The shader variable <code>attrName</code> + * is explicitly set to the specified <code>value</code> during + * rendering. <code>attrName</code> must be the name of a valid + * uniform attribute in the shader in which it is used. Otherwise, the + * attribute name will be ignored and a runtime error may be + * generated. The <code>value</code> must be an instance of one of the + * allowed classes or an array of one the allowed classes. The allowed + * classes are: <code>Integer</code>, <code>Float</code>, + * <code>Tuple{2,3,4}{i,f}</code>, + * <code>Matrix{3,4}f</code>. A ClassCastException will be thrown + * if a specified <code>value</code> object is not one of the allowed + * types. Further, the type of the value is immutable once a + * ShaderAttributeObjectRetained is constructed. Subsequent setValue + * operations must be called with an object of the same type as the + * one that was used to construct the ShaderAttributeObjectRetained. + * Finally, the type of the <code>value</code> object must match the type + * of the corresponding <code>attrName</code> variable in the shader in + * which it is used. Otherwise, the shader will not be able to use the + * attribute and a runtime error may be generated. + * + * @see ShaderAttributeSetRetained + * @see ShaderProgramRetained + * + * @since Java 3D 1.4 + */ + +abstract class ShaderAttributeObjectRetained extends ShaderAttributeRetained { + + private int classType; + private Class baseClass; + AttrWrapper attrWrapper; + + /** + * Package scope constructor + */ + ShaderAttributeObjectRetained() { + } + + void createObjectData(Object value) { + + classType = computeClassType(value); + baseClass = getBaseClass(classType); + attrWrapper = createAttrWrapper(value, classType); + /* + System.err.println(" classType = " + classType + + ", baseClass = " + baseClass + + ", attrWrapper.get() = " + attrWrapper.get()); + */ + } + + + void initValue(Object value) { + /* + System.err.println("ShaderAttributeObjectRetained : attrName = " + attrName + + ", value = " + value + + ", value.class = " + value.getClass()); + */ + attrWrapper.set(value); + + } + + /** + * Retrieves the value of this shader attribute. + * A copy of the object is returned. + */ + Object getValue() { + return attrWrapper.get(); + } + + /** + * Sets the value of this shader attribute to the specified value. + * A copy of the object is stored. + * + * @param value the new value of the shader attribute + * + * @exception NullPointerException if value is null + * + * @exception ClassCastException if value is not an instance of + * the same base class as the object used to construct this shader + * attribute object. + * + */ + void setValue(Object value) { + initValue(value); + AttrWrapper valueWrapper = createAttrWrapper(value, this.classType); + sendMessage(SHADER_ATTRIBUTE_VALUE_UPDATE, valueWrapper); + } + + /** + * Retrieves the base class of the value of this shader attribute. + * This class will always be one of the allowable classes, even if + * a subclass was used to construct this shader attribute object. + * For example, if this shader attribute object was constructed + * with an instance of <code>javax.vecmath.Point3f</code>, the + * returned class would be <code>javax.vecmath.Tuple3f</code>. + * + * @return the base class of the value of this shader attribute + */ + Class getValueClass() { + return baseClass; + } + + /** + * Initializes a mirror object. + */ + synchronized void initMirrorObject() { + super.initMirrorObject(); + ((ShaderAttributeObjectRetained)mirror).initValue(getValue()); + } + + /** + * Update the "component" field of the mirror object with the given "value" + */ + synchronized void updateMirrorObject(int component, Object value) { + + //System.out.println("ShaderAttributeObjectRetained : updateMirrorObject"); + ShaderAttributeObjectRetained mirrorSAV = (ShaderAttributeObjectRetained)mirror; + if ((component & SHADER_ATTRIBUTE_VALUE_UPDATE) != 0) { + //System.out.println(" -- SHADER_ATTRIBUTE_VALUE_UPDATE"); + mirrorSAV.attrWrapper = (AttrWrapper) value; + } + } + + final void sendMessage(int attrMask, Object attr) { + + ArrayList univList = new ArrayList(); + ArrayList gaList = Shape3DRetained.getGeomAtomsList(mirror.users, univList); + + // Send to rendering attribute structure, regardless of + // whether there are users or not (alternate appearance case ..) + J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; + createMessage.type = J3dMessage.SHADER_ATTRIBUTE_CHANGED; + createMessage.universe = null; + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + createMessage.args[2] = attr; + // System.out.println("changedFreqent1 = "+changedFrequent); + createMessage.args[3] = new Integer(changedFrequent); + VirtualUniverse.mc.processMessage(createMessage); + + // System.out.println("univList.size is " + univList.size()); + for(int i=0; i<univList.size(); i++) { + createMessage = VirtualUniverse.mc.getMessage(); + createMessage.threads = J3dThread.UPDATE_RENDER; + createMessage.type = J3dMessage.SHADER_ATTRIBUTE_CHANGED; + + createMessage.universe = (VirtualUniverse) univList.get(i); + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + createMessage.args[2] = attr; + + ArrayList gL = (ArrayList)gaList.get(i); + GeometryAtom[] gaArr = new GeometryAtom[gL.size()]; + gL.toArray(gaArr); + createMessage.args[3] = gaArr; + + VirtualUniverse.mc.processMessage(createMessage); + } + + } + + + // Enumerated types representing allowed classes for shader + // attributes. + // + // NOTE that the values for these enums are used as an index into + // the tables of classes, so the values must start at 0 and + // increment by 1. Also, the order must be the same as the order + // of the entries in each of the two class tables. + static final int TYPE_INTEGER = 0; + static final int TYPE_FLOAT = 1; + static final int TYPE_TUPLE2I = 2; + static final int TYPE_TUPLE2F = 3; + static final int TYPE_TUPLE3I = 4; + static final int TYPE_TUPLE3F = 5; + static final int TYPE_TUPLE4I = 6; + static final int TYPE_TUPLE4F = 7; + static final int TYPE_MATRIX3F = 8; + static final int TYPE_MATRIX4F = 9; + + // Double-precision is not supported in the current version. Uncomment the + // following if future support is done. +// static final int TYPE_DOUBLE = 10; +// static final int TYPE_TUPLE2D = 11; +// static final int TYPE_TUPLE3D = 12; +// static final int TYPE_TUPLE4D = 13; +// static final int TYPE_MATRIX3D = 14; +// static final int TYPE_MATRIX4D = 15; + + static final Class classTable[] = { + Integer.class, + Float.class, + Tuple2i.class, + Tuple2f.class, + Tuple3i.class, + Tuple3f.class, + Tuple4i.class, + Tuple4f.class, + Matrix3f.class, + Matrix4f.class, + + // Double-precision is not supported in the current version. Uncomment the + // following if future support is done. +// Double.class, +// Tuple2d.class, +// Tuple3d.class, +// Tuple4d.class, +// Matrix3d.class, +// Matrix4d.class, + }; + + static final Class classTableArr[] = { + Integer[].class, + Float[].class, + Tuple2i[].class, + Tuple2f[].class, + Tuple3i[].class, + Tuple3f[].class, + Tuple4i[].class, + Tuple4f[].class, + Matrix3f[].class, + Matrix4f[].class, + + // Double-precision is not supported in the current version. Uncomment the + // following if future support is done. +// Double[].class, +// Tuple2d[].class, +// Tuple3d[].class, +// Tuple4d[].class, +// Matrix3d[].class, +// Matrix4d[].class, + }; + + + /** + * Computes the base class from the specified object. A + * ClassCastException is thrown if the object is not an instance + * or array of one of the allowed classes. + */ + abstract int computeClassType(Object value); + + /** + * Returns the base class represented by the specified class type. + */ + abstract Class getBaseClass(int classType); + + /** + * Creates an attribute wrapper object of the specified class + * type, and stores the specified object. + */ + abstract AttrWrapper createAttrWrapper(Object value, int classType); + + + /** + * Base wrapper class for subclasses that are used to store a copy + * of the user-specified shader attribute value. There is a + * wrapper class for each supported base class in ShaderAttributeValue + * and ShaderAttributeArray. The value is stored in a Java primitive array. + */ + static abstract class AttrWrapper { + /** + * Stores a copy of the specified object in the wrapper object + */ + abstract void set(Object value); + + /** + * Returns a copy of the wrapped object + */ + abstract Object get(); + + /** + * Returns a reference to the internal primitive array used to + * wrap the object; note that the caller of this method must + * treat the data as read-only. It is intended only as a means + * to pass data down to native methods. + */ + abstract Object getRef(); + } + + int getClassType() { + return classType; + } + + void setClassType(int classType) { + this.classType = classType; + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeRetained.java new file mode 100644 index 0000000..64cbdc0 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeRetained.java @@ -0,0 +1,82 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeRetained object encapsulates a uniform attribute for a + * shader programs. Uniform attributes (variables) are those + * attributes whose values are constant during the rendering of a + * primitive. Their values may change from primitive to primitive, but + * are constant for each vertex (for vertex shaders) or fragment (for + * fragment shaders) of a single primitive. Examples of uniform + * attributes include a transformation matrix, a texture map, lights, + * lookup tables, etc. + * + * <p> + * There are two ways in which values can be specified for uniform + * attributes: explicitly, by providing a value; and implicitly, by + * defining a binding between a Java 3D system attribute and a uniform + * attribute. This functionality is provided by two subclasses of + * ShaderAttributeRetained as follows: + * + * <ul> + * <li>ShaderAttributeObjectRetained, in which attributes are expressed as + * <code>(attrName, value)</code> pairs, is used for explicitly + * defined attributes</li> + * <li>ShaderAttributeBindingRetained, in which attributes are expressed as + * <code>(attrName, j3dAttrName)</code> pairs, is used for + * implicitly defined, automatically tracked attributes</li> + * </ul> + * + * @see ShaderAttributeSetRetained + * @see ShaderProgramRetained + * + * @since Java 3D 1.4 + */ + +abstract class ShaderAttributeRetained extends NodeComponentRetained { + // A list of pre-defined bits to indicate which component + // in this ShaderAttribute object changed. + static final int SHADER_ATTRIBUTE_VALUE_UPDATE = 0x001; + + /** + * Name of the shader attribute (immutable) + */ + String attrName; + + /** + * Package scope constructor + */ + ShaderAttributeRetained() { + } + + void initializeAttrName(String attrName) { + this.attrName = attrName; + } + + /** + * Retrieves the name of this shader attribute. + * + * @return the name of this shader attribute + */ + String getAttributeName() { + return attrName; + } + + void initMirrorObject() { + ((ShaderAttributeObjectRetained)mirror).initializeAttrName(this.attrName); + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeSet.java b/src/classes/share/javax/media/j3d/ShaderAttributeSet.java new file mode 100644 index 0000000..ad75b11 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeSet.java @@ -0,0 +1,263 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; +import javax.vecmath.*; + +/** + * The ShaderAttributeSet object provides uniform attributes to shader + * programs. Uniform attributes (variables) are those attributes whose + * values are constant during the rendering of a primitive. Their + * values may change from primitive to primitive, but are constant for + * each vertex (for vertex shaders) or fragment (for fragment shaders) + * of a single primitive. Examples of uniform attributes include a + * transformation matrix, a texture map, lights, lookup tables, etc. + * The ShaderAttributeSet object contains a set of ShaderAttribute + * objects. Each ShaderAttribute object defines the value of a single + * uniform shader variable. The set of attributes is unique with respect + * to attribute names: no two attributes in the set will have the same + * name. + * + * <p> + * There are two ways in which values can be specified for uniform + * attributes: explicitly, by providing a value; and implicitly, by + * defining a binding between a Java 3D system attribute and a uniform + * attribute. This functionality is provided by two subclasses of + * ShaderAttribute: ShaderAttributeObject, which is used to specify + * explicitly defined attributes; and ShaderAttributeBinding, which is + * used to specify implicitly defined, automatically tracked attributes. + * + * <p> + * Depending on the shading language (and profile) being used, several + * Java 3D state attributes are automatically made available to the + * shader program as pre-defined uniform attributes. The application + * doesn't need to do anything to pass these attributes in to the + * shader program. The implementation of each shader language (e.g., + * Cg, GLSL) defines its own bindings from Java 3D attribute to uniform + * variable name. A list of these attributes for each shader language + * can be found in the concrete subclass of ShaderProgram for that + * shader language. + * + * @see ShaderAttribute + * @see ShaderProgram + * @see ShaderAppearance#setShaderAttributeSet + * + * @since Java 3D 1.4 + */ + +public class ShaderAttributeSet extends NodeComponent { + + /** + * Specifies that this ShaderAttributeSet object allows reading + * its attributes. + */ + public static final int + ALLOW_ATTRIBUTES_READ = + CapabilityBits.SHADER_ATTRIBUTE_SET_ALLOW_ATTRIBUTES_READ; + + /** + * Specifies that this ShaderAttributeSet object allows writing + * its attributes. + */ + public static final int + ALLOW_ATTRIBUTES_WRITE = + CapabilityBits.SHADER_ATTRIBUTE_SET_ALLOW_ATTRIBUTES_WRITE; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_ATTRIBUTES_READ + }; + + /** + * Constructs an empty ShaderAttributeSet object. The attributes set + * is initially empty. + */ + public ShaderAttributeSet() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } + + // + // Methods for dealing with the (name, value) pairs for explicit + // attributes + // + + /** + * Adds the specified shader attribute to the attributes set. + * The newly specified attribute replaces an attribute with the + * same name, if one already exists in the attributes set. + * + * @param attr the shader attribute to be added to the set + * + * @exception NullPointerException if attr is null + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public void put(ShaderAttribute attr) { + if (attr == null) { + throw new NullPointerException(); + } + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_ATTRIBUTES_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeSet1")); + + ((ShaderAttributeSetRetained)this.retained).put(attr); + + } + + /** + * Retrieves the shader attribute with the specified + * <code>attrName</code> from the attributes set. If attrName does + * not exist in the attributes set, null is returned. + * + * @param attrName the name of the shader attribute to be retrieved + * + * @exception NullPointerException if attrName is null + * + * @return a the shader attribute associated with the specified + * attribute name, or null if the name is not in the attributes + * set + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public ShaderAttribute get(String attrName) { + + if (attrName == null) { + throw new NullPointerException(); + } + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_ATTRIBUTES_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeSet0")); + + return ((ShaderAttributeSetRetained)this.retained).get(attrName); + } + + /** + * Removes the shader attribute with the specified + * <code>attrName</code> from the attributes set. If attrName does + * not exist in the attributes set then nothing happens. + * + * @param attrName the name of the shader attribute to be removed + * + * @exception NullPointerException if attrName is null + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public void remove(String attrName) { + if (attrName == null) { + throw new NullPointerException(); + } + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_ATTRIBUTES_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeSet1")); + + ((ShaderAttributeSetRetained)this.retained).remove(attrName); + } + + /** + * Removes the specified shader attribute from the attributes + * set. If the attribute does not exist in the attributes set then + * nothing happens. Note that this method will <i>not</i> remove a + * shader object other than the one specified, even if it has the + * same name as the specified attribute. Applications that wish to + * remove an attribute by name should use + * <code>removeAttribute(String)</code>. + * + * @param attr the shader attribute to be removed + * + * @exception NullPointerException if attr is null + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public void remove(ShaderAttribute attr) { + if (attr == null) { + throw new NullPointerException(); + } + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_ATTRIBUTES_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeSet1")); + + ((ShaderAttributeSetRetained)this.retained).remove(attr); + } + + /** + * Removes all shader attributes from the attributes set. The + * attributes set will be empty following this call. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public void clear() { + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_ATTRIBUTES_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeSet1")); + + ((ShaderAttributeSetRetained)this.retained).clear(); + } + + /** + * Returns a shallow copy of the attributes set. + * + * @return a shallow copy of the attributes set + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public ShaderAttribute[] getAll() { + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_ATTRIBUTES_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeSet0")); + + return ((ShaderAttributeSetRetained)this.retained).getAll(); + } + + /** + * Returns the number of elements in the attributes set. + * + * @return the number of elements in the attributes set + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public int size() { + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_ATTRIBUTES_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeSet0")); + + return ((ShaderAttributeSetRetained)this.retained).size(); + } + + /** + * Creates a retained mode ShaderAttributeSetRetained object that this + * ShaderAttributeSet component object will point to. + */ + void createRetained() { + // System.out.println("ShaderAttributeSet : createRetained() ..."); + this.retained = new ShaderAttributeSetRetained(); + this.retained.setSource(this); + } +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeSetRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeSetRetained.java new file mode 100644 index 0000000..965387b --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeSetRetained.java @@ -0,0 +1,390 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; +import javax.vecmath.*; + +/** + * The ShaderAttributeSet object provides uniform attributes to shader + * programs. Uniform attributes (variables) are those attributes whose + * values are constant during the rendering of a primitive. Their + * values may change from primitive to primitive, but are constant for + * each vertex (for vertex shaders) or fragment (for fragment shaders) + * of a single primitive. Examples of uniform attributes include a + * transformation matrix, a texture map, lights, lookup tables, etc. + * The ShaderAttributeSet object contains a set of ShaderAttribute + * objects. Each ShaderAttribute object defines the value of a single + * uniform shader variable. The set of attributes is unique with respect + * to attribute names: no two attributes in the set will have the same + * name. + * + * <p> + * There are two ways in which values can be specified for uniform + * attributes: explicitly, by providing a value; and implicitly, by + * defining a binding between a Java 3D system attribute and a uniform + * attribute. This functionality is provided by two subclasses of + * ShaderAttribute: ShaderAttributeObject, which is used to specify + * explicitly defined attributes; and ShaderAttributeBinding, which is + * used to specify implicitly defined, automatically tracked attributes. + * + * <p> + * Depending on the shading language (and profile) being used, several + * Java 3D state attributes are automatically made available to the + * shader program as pre-defined uniform attributes. The application + * doesn't need to do anything to pass these attributes in to the + * shader program. The implementation of each shader language (e.g., + * Cg, GLSL) defines its own bindings from Java 3D attribute to uniform + * variable name. A list of these attributes for each shader language + * can be found in the concrete subclass of ShaderProgram for that + * shader language. + * + * @see ShaderAttribute + * @see ShaderProgram + * @see ShaderAppearance#setShaderAttributeSet + * + * @since Java 3D 1.4 + */ + +class ShaderAttributeSetRetained extends NodeComponentRetained { + // A list of pre-defined bits to indicate which attribute + // operation in this ShaderAttributeSet object is needed. + static final int ATTRIBUTE_SET_PUT = 0x01; + + static final int ATTRIBUTE_SET_REMOVE = 0x02; + + static final int ATTRIBUTE_SET_CLEAR = 0x04; + + private Map attrs = new HashMap(); + + // Lock used for synchronization of live state + Object liveStateLock = new Object(); + + /** + * Constructs an empty ShaderAttributeSetretained object. The attributes set + * is initially empty. + */ + ShaderAttributeSetRetained() { + } + + // + // Methods for dealing with the (name, value) pairs for explicit + // attributes + // + + /** + * Adds the specified shader attribute to the attributes set. + * The newly specified attribute replaces an attribute with the + * same name, if one already exists in the attributes set. + * + * @param attr the shader attribute to be added to the set + * + */ + void put(ShaderAttribute attr) { + synchronized(liveStateLock) { + // System.out.println("ShaderAttributeSetRetained : put()"); + ShaderAttributeRetained sAttr = (ShaderAttributeRetained)attr.retained; + // System.out.println("attr is " + attr ); + // System.out.println("attrName is " + sAttr.attrName + " attr.Retained is "+ sAttr ); + assert(sAttr != null); + attrs.put(sAttr.attrName, sAttr); + + if (source.isLive()) { + sAttr.setLive(inBackgroundGroup, refCount); + sAttr.copyMirrorUsers(this); + + sendMessage(ATTRIBUTE_SET_PUT, sAttr.mirror); + } + } + } + + /** + * Retrieves the shader attribute with the specified + * <code>attrName</code> from the attributes set. If attrName does + * not exist in the attributes set, null is returned. + * + * @param attrName the name of the shader attribute to be retrieved + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + ShaderAttribute get(String attrName) { + return (ShaderAttribute)((ShaderAttributeRetained)attrs.get(attrName)).source; + } + + /** + * Removes the shader attribute with the specified + * <code>attrName</code> from the attributes set. If attrName does + * not exist in the attributes set then nothing happens. + * + * @param attrName the name of the shader attribute to be removed + */ + void remove(String attrName) { + synchronized(liveStateLock) { + ShaderAttributeRetained sAttr = (ShaderAttributeRetained)attrs.get(attrName); + attrs.remove(attrName); + if (source.isLive()) { + sAttr.clearLive(refCount); + sAttr.removeMirrorUsers(this); + + sendMessage(ATTRIBUTE_SET_REMOVE, attrName); + } + } + } + + /** + * Removes the specified shader attribute from the attributes + * set. If the attribute does not exist in the attributes set then + * nothing happens. Note that this method will <i>not</i> remove a + * shader object other than the one specified, even if it has the + * same name as the specified attribute. Applications that wish to + * remove an attribute by name should use + * <code>removeAttribute(String)</code>. + * + * @param attr the shader attribute to be removed + */ + void remove(ShaderAttribute attr) { + synchronized(liveStateLock) { + String attrName = attr.getAttributeName(); + if (attrs.get(attrName) == attr) { + attrs.remove(attrName); + if (source.isLive()) { + ((ShaderAttributeRetained)attr.retained).clearLive(refCount); + ((ShaderAttributeRetained)attr.retained).removeMirrorUsers(this); + + sendMessage(ATTRIBUTE_SET_REMOVE, attrName); + } + } + } + } + + /** + * Removes all shader attributes from the attributes set. The + * attributes set will be empty following this call. + * + */ + void clear() { + synchronized(liveStateLock) { + attrs.clear(); + if(source.isLive()) { + ShaderAttributeRetained[] sAttrs = new ShaderAttributeRetained[attrs.size()]; + sAttrs = (ShaderAttributeRetained[])attrs.values().toArray(sAttrs); + for (int i = 0; i < sAttrs.length; i++) { + sAttrs[i].clearLive(refCount); + sAttrs[i].removeMirrorUsers(this); + } + sendMessage(ATTRIBUTE_SET_CLEAR, null); + } + } + } + + /** + * Returns a shallow copy of the attributes set. + * + * @return a shallow copy of the attributes set + * + */ + ShaderAttribute[] getAll() { + + ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs.size()]; + ShaderAttribute[] sAttrs = new ShaderAttribute[sAttrsRetained.length]; + sAttrsRetained = (ShaderAttributeRetained[])attrs.values().toArray(sAttrsRetained); + for(int i=0; i < sAttrsRetained.length; i++) { + sAttrs[i] = (ShaderAttribute) sAttrsRetained[i].source; + } + + return sAttrs; + } + + /** + * Returns the number of elements in the attributes set. + * + * @return the number of elements in the attributes set + * + */ + int size() { + return attrs.size(); + } + + + void updateNative(Canvas3D cv, ShaderProgramRetained shaderProgram) { + shaderProgram.setShaderAttributes(cv, this); + } + + Map getAttrs() { + return attrs; + } + + + void setLive(boolean backgroundGroup, int refCount) { + + // System.out.println("ShaderAttributeSetRetained.setLive()"); + ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs.size()]; + sAttrsRetained = (ShaderAttributeRetained[])attrs.values().toArray(sAttrsRetained); + for(int i=0; i < sAttrsRetained.length; i++) { + sAttrsRetained[i].setLive(backgroundGroup, refCount); + } + + super.doSetLive(backgroundGroup, refCount); + super.markAsLive(); + } + + synchronized void addAMirrorUser(Shape3DRetained shape) { + + super.addAMirrorUser(shape); + + ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs.size()]; + sAttrsRetained = (ShaderAttributeRetained[])attrs.values().toArray(sAttrsRetained); + for(int i=0; i < sAttrsRetained.length; i++) { + sAttrsRetained[i].addAMirrorUser(shape); + } + } + + synchronized void removeAMirrorUser(Shape3DRetained shape) { + super.removeAMirrorUser(shape); + + ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs.size()]; + sAttrsRetained = (ShaderAttributeRetained[])attrs.values().toArray(sAttrsRetained); + for(int i=0; i < sAttrsRetained.length; i++) { + sAttrsRetained[i].removeAMirrorUser(shape); + } + } + + + synchronized void removeMirrorUsers(NodeComponentRetained node) { + super.removeMirrorUsers(node); + + ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs.size()]; + sAttrsRetained = (ShaderAttributeRetained[])attrs.values().toArray(sAttrsRetained); + for(int i=0; i < sAttrsRetained.length; i++) { + sAttrsRetained[i].removeMirrorUsers(node); + } + } + + synchronized void copyMirrorUsers(NodeComponentRetained node) { + super.copyMirrorUsers(node); + + ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs.size()]; + sAttrsRetained = (ShaderAttributeRetained[])attrs.values().toArray(sAttrsRetained); + for(int i=0; i < sAttrsRetained.length; i++) { + sAttrsRetained[i].copyMirrorUsers(node); + } + } + + void clearLive(int refCount) { + // System.out.println("ShaderAttributeSetRetained.clearLive()"); + + super.clearLive(refCount); + + ShaderAttributeRetained[] sAttrsRetained = new ShaderAttributeRetained[attrs.size()]; + sAttrsRetained = (ShaderAttributeRetained[])attrs.values().toArray(sAttrsRetained); + for(int i=0; i < sAttrsRetained.length; i++) { + sAttrsRetained[i].clearLive(refCount); + } + } + + synchronized void createMirrorObject() { + // System.out.println("ShaderAttributeSetRetained : createMirrorObject"); + // This method should only call by setLive(). + if (mirror == null) { + ShaderAttributeSetRetained mirrorSAS = new ShaderAttributeSetRetained(); + mirror = mirrorSAS; + mirror.source = source; + + } + initMirrorObject(); + } + + void initMirrorObject() { + + ShaderAttributeRetained[] sAttrs = new ShaderAttributeRetained[attrs.size()]; + sAttrs = (ShaderAttributeRetained[])attrs.values().toArray(sAttrs); + // Need to copy the mirror attrs + for (int i = 0; i < sAttrs.length; i++) { + ShaderAttributeRetained mirrorSA = (ShaderAttributeRetained) sAttrs[i].mirror; + assert(mirrorSA != null); + ((ShaderAttributeSetRetained)mirror).attrs.put(mirrorSA.attrName, mirrorSA); + } + } + + /** + * Update the "component" field of the mirror object with the given "value" + */ + synchronized void updateMirrorObject(int component, Object value) { + + // System.out.println("ShaderAttributeSetRetained : updateMirrorObject"); + + ShaderAttributeSetRetained mirrorSAS = (ShaderAttributeSetRetained)mirror; + + if ((component & ATTRIBUTE_SET_PUT) != 0) { + // System.out.println(" -- ATTRIBUTE_SET_PUT"); + ShaderAttributeRetained mirrorSA = (ShaderAttributeRetained)value; + assert(mirrorSA != null); + ((ShaderAttributeSetRetained)mirror).attrs.put(mirrorSA.attrName, mirrorSA); + } + else if((component & ATTRIBUTE_SET_REMOVE) != 0) { + // System.out.println(" -- ATTRIBUTE_SET_REMOVE"); + ((ShaderAttributeSetRetained)mirror).attrs.remove((String)value); + } + else if((component & ATTRIBUTE_SET_CLEAR) != 0) { + // System.out.println(" -- ATTRIBUTE_SET_CLEAR"); + ((ShaderAttributeSetRetained)mirror).attrs.clear(); + } + else { + assert(false); + } + } + + final void sendMessage(int attrMask, Object attr) { + + ArrayList univList = new ArrayList(); + ArrayList gaList = Shape3DRetained.getGeomAtomsList(mirror.users, univList); + + // Send to rendering attribute structure, regardless of + // whether there are users or not (alternate appearance case ..) + J3dMessage createMessage = VirtualUniverse.mc.getMessage(); + createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES; + createMessage.type = J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED; + createMessage.universe = null; + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + createMessage.args[2] = attr; + // System.out.println("changedFreqent1 = "+changedFrequent); + createMessage.args[3] = new Integer(changedFrequent); + VirtualUniverse.mc.processMessage(createMessage); + + // System.out.println("univList.size is " + univList.size()); + for(int i=0; i<univList.size(); i++) { + createMessage = VirtualUniverse.mc.getMessage(); + createMessage.threads = J3dThread.UPDATE_RENDER; + createMessage.type = J3dMessage.SHADER_ATTRIBUTE_SET_CHANGED; + + createMessage.universe = (VirtualUniverse) univList.get(i); + createMessage.args[0] = this; + createMessage.args[1]= new Integer(attrMask); + createMessage.args[2] = attr; + + ArrayList gL = (ArrayList)gaList.get(i); + GeometryAtom[] gaArr = new GeometryAtom[gL.size()]; + gL.toArray(gaArr); + createMessage.args[3] = gaArr; + + VirtualUniverse.mc.processMessage(createMessage); + } + + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeValue.java b/src/classes/share/javax/media/j3d/ShaderAttributeValue.java new file mode 100644 index 0000000..1f9dc0a --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeValue.java @@ -0,0 +1,100 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeValue object encapsulates a uniform shader + * attribute whose value is specified explicitly. The shader variable + * <code>attrName</code> is explicitly set to the specified + * <code>value</code> during rendering. <code>attrName</code> must be + * the name of a valid uniform attribute in the shader in which it is + * used. Otherwise, the attribute name will be ignored and a runtime + * error may be generated. The <code>value</code> must be an instance + * of one of the allowed classes. The allowed classes are: + * <code>Integer</code>, <code>Float</code>, + * <code>Tuple{2,3,4}{i,f}</code>, <code>Matrix{3,4}f</code>. A + * ClassCastException will be thrown if a specified <code>value</code> + * object is not one of the allowed types. Further, the type of the + * value is immutable once a ShaderAttributeValue is constructed. + * Subsequent setValue operations must be called with an object of the + * same type as the one that was used to construct the + * ShaderAttributeValue. Finally, the type of the <code>value</code> + * object must match the type of the corresponding + * <code>attrName</code> variable in the shader in which it is + * used. Otherwise, the shader will not be able to use the attribute + * and a runtime error may be generated. + * + * @see ShaderAttributeSet + * @see ShaderProgram + * + * @since Java 3D 1.4 + */ + +public class ShaderAttributeValue extends ShaderAttributeObject { + /** + * Constructs a new ShaderAttributeValue object with the specified + * <code>(attrName, value)</code> pair. + * A copy of the object is stored. + * + * @param attrName the name of the shader attribute + * @param value the value of the shader attribute + * + * @exception NullPointerException if attrName or value is null + * + * @exception ClassCastException if value is not an instance of + * one of the allowed classes + */ + public ShaderAttributeValue(String attrName, Object value) { + super(attrName, value); + } + + // Implement abstract getValue method + public Object getValue() { + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_VALUE_READ)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeObject0")); + + return ((ShaderAttributeValueRetained)this.retained).getValue(); + } + + // Implement abstract setValue method + public void setValue(Object value) { + + if (value == null) { + throw new NullPointerException(); + } + + if (isLiveOrCompiled()) + if (!this.getCapability(ALLOW_VALUE_WRITE)) + throw new CapabilityNotSetException(J3dI18N.getString("ShaderAttributeObject1")); + + if (isLive()) + ((ShaderAttributeValueRetained)this.retained).setValue(value); + else + ((ShaderAttributeValueRetained)this.retained).initValue(value); + + } + + /** + * Creates a retained mode ShaderAttributeValueRetained object that this + * ShaderAttributeValue component object will point to. + */ + void createRetained() { + this.retained = new ShaderAttributeValueRetained(); + this.retained.setSource(this); + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderAttributeValueRetained.java b/src/classes/share/javax/media/j3d/ShaderAttributeValueRetained.java new file mode 100644 index 0000000..758672c --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderAttributeValueRetained.java @@ -0,0 +1,499 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; + +/** + * The ShaderAttributeValueRetained object encapsulates a uniform shader + * attribute whose value is specified explicitly. The shader variable + * <code>attrName</code> is explicitly set to the specified + * <code>value</code> during rendering. <code>attrName</code> must be + * the name of a valid uniform attribute in the shader in which it is + * used. Otherwise, the attribute name will be ignored and a runtime + * error may be generated. The <code>value</code> must be an instance + * of one of the allowed classes. The allowed classes are: + * <code>Integer</code>, <code>Float</code>, + * <code>Tuple{2,3,4}{i,f}</code>, <code>Matrix{3,4}f</code>. A + * ClassCastException will be thrown if a specified <code>value</code> + * object is not one of the allowed types. Further, the type of the + * value is immutable once a ShaderAttributeValue is constructed. + * Subsequent setValue operations must be called with an object of the + * same type as the one that was used to construct the + * ShaderAttributeValue. Finally, the type of the <code>value</code> + * object must match the type of the corresponding + * <code>attrName</code> variable in the shader in which it is + * used. Otherwise, the shader will not be able to use the attribute + * and a runtime error may be generated. + * + * @see ShaderAttributeSetRetained + * @see ShaderProgramRetained + * + * @since Java 3D 1.4 + */ + +class ShaderAttributeValueRetained extends ShaderAttributeObjectRetained { + + ShaderAttributeValueRetained() { + } + + synchronized void createMirrorObject() { + // System.out.println("ShaderAttributeValueRetained : createMirrorObject"); + // This method should only call by setLive(). + if (mirror == null) { + ShaderAttributeValueRetained mirrorSAV = new ShaderAttributeValueRetained(); + mirrorSAV.createObjectData(getValue()); + mirror = mirrorSAV; + mirror.source = source; + + } + initMirrorObject(); + } + + /** + * Computes the base class from the specified object. A + * ClassCastException is thrown if the object is not an instance + * of one of the allowed classes. + */ + int computeClassType(Object value) { + Class objClass = value.getClass(); + if (objClass.isArray()) { + throw new ClassCastException(objClass + " -- array class not allowed"); + } + + for (int i = 0; i < classTable.length; i++) { + if (classTable[i].isInstance(value)) { + return i; + } + } + throw new ClassCastException(objClass + " -- unrecognized class"); + } + + /** + * Returns the base class represented by the specified class type. + */ + Class getBaseClass(int classType) { + return classTable[classType]; + } + + /** + * Creates an attribute wrapper object of the specified class + * type, and stores the specified object. + */ + AttrWrapper createAttrWrapper(Object value, int classType) { + ValueWrapper attrWrapper = null; + switch (classType) { + case TYPE_INTEGER: + attrWrapper = new IntegerWrapper(); + break; + case TYPE_FLOAT: + attrWrapper = new FloatWrapper(); + break; +// case TYPE_DOUBLE: +// attrWrapper = new DoubleWrapper(); +// break; + case TYPE_TUPLE2I: + attrWrapper = new Tuple2iWrapper(); + break; + case TYPE_TUPLE2F: + attrWrapper = new Tuple2fWrapper(); + break; +// case TYPE_TUPLE2D: +// attrWrapper = new Tuple2dWrapper(); +// break; + case TYPE_TUPLE3I: + attrWrapper = new Tuple3iWrapper(); + break; + case TYPE_TUPLE3F: + attrWrapper = new Tuple3fWrapper(); + break; +// case TYPE_TUPLE3D: +// attrWrapper = new Tuple3dWrapper(); +// break; + case TYPE_TUPLE4I: + attrWrapper = new Tuple4iWrapper(); + break; + case TYPE_TUPLE4F: + attrWrapper = new Tuple4fWrapper(); + break; +// case TYPE_TUPLE4D: +// attrWrapper = new Tuple4dWrapper(); +// break; + case TYPE_MATRIX3F: + attrWrapper = new Matrix3fWrapper(); + break; +// case TYPE_MATRIX3D: +// attrWrapper = new Matrix3dWrapper(); +// break; + case TYPE_MATRIX4F: + attrWrapper = new Matrix4fWrapper(); + break; +// case TYPE_MATRIX4D: +// attrWrapper = new Matrix4dWrapper(); +// break; + default: + // Should never get here + assert false; + return null; + } + + attrWrapper.set(value); + return attrWrapper; + } + + // + // The following wrapper classes are used to store a copy of the + // user-specified shader attribute value. There is a wrapper class + // for each supported base class. + // + + // Base wrapper class for non-array attribute types + static abstract class ValueWrapper extends AttrWrapper { + // No additional fields or methods are defined in this class + } + + // Wrapper class for Integer + static class IntegerWrapper extends ValueWrapper { + private int[] value = new int[1]; + + void set(Object value) { + this.value[0] = ((Integer)value).intValue(); + } + + Object get() { + return new Integer(this.value[0]); + } + + Object getRef() { + return this.value; + } + } + + // Wrapper class for Float + static class FloatWrapper extends ValueWrapper { + private float[] value = new float[1]; + + void set(Object value) { + this.value[0] = ((Float)value).floatValue(); + } + + Object get() { + return new Float(this.value[0]); + } + + Object getRef() { + return this.value; + } + } + + /* + // Wrapper class for Double + static class DoubleWrapper extends ValueWrapper { + private double[] value = new double[1]; + + void set(Object value) { + this.value[0] = ((Double)value).doubleValue(); + } + + Object get() { + return new Double(value[0]); + } + + Object getRef() { + return value; + } + } + */ + + // Wrapper class for Tuple2i + static class Tuple2iWrapper extends ValueWrapper { + private int[] value = new int[2]; + + void set(Object value) { + ((Tuple2i)value).get(this.value); + } + + Object get() { + return new Point2i(value); + } + + Object getRef() { + return value; + } + } + + // Wrapper class for Tuple2f + static class Tuple2fWrapper extends ValueWrapper { + private float[] value = new float[2]; + + void set(Object value) { + ((Tuple2f)value).get(this.value); + } + + Object get() { + return new Point2f(value); + } + + Object getRef() { + return value; + } + } + + /* + // Wrapper class for Tuple2d + static class Tuple2dWrapper extends ValueWrapper { + private double[] value = new double[2]; + + void set(Object value) { + ((Tuple2d)value).get(this.value); + } + + Object get() { + return new Point2d(value); + } + + Object getRef() { + return value; + } + } + */ + + // Wrapper class for Tuple3i + static class Tuple3iWrapper extends ValueWrapper { + private int[] value = new int[3]; + + void set(Object value) { + ((Tuple3i)value).get(this.value); + } + + Object get() { + return new Point3i(value); + } + + Object getRef() { + return value; + } + } + + // Wrapper class for Tuple3f + static class Tuple3fWrapper extends ValueWrapper { + private float[] value = new float[3]; + + void set(Object value) { + ((Tuple3f)value).get(this.value); + } + + Object get() { + return new Point3f(value); + } + + Object getRef() { + return value; + } + } + + /* + // Wrapper class for Tuple3d + static class Tuple3dWrapper extends ValueWrapper { + private double[] value = new double[3]; + + void set(Object value) { + ((Tuple3d)value).get(this.value); + } + + Object get() { + return new Point3d(value); + } + + Object getRef() { + return value; + } + } + */ + + // Wrapper class for Tuple4i + static class Tuple4iWrapper extends ValueWrapper { + private int[] value = new int[4]; + + void set(Object value) { + ((Tuple4i)value).get(this.value); + } + + Object get() { + return new Point4i(value); + } + + Object getRef() { + return value; + } + } + + // Wrapper class for Tuple4f + static class Tuple4fWrapper extends ValueWrapper { + private float[] value = new float[4]; + + void set(Object value) { + ((Tuple4f)value).get(this.value); + } + + Object get() { + return new Point4f(value); + } + + Object getRef() { + return value; + } + } + + /* + // Wrapper class for Tuple4d + static class Tuple4dWrapper extends ValueWrapper { + private double[] value = new double[4]; + + void set(Object value) { + ((Tuple4d)value).get(this.value); + } + + Object get() { + return new Point4d(value); + } + + Object getRef() { + return value; + } + } + */ + + // Wrapper class for Matrix3f + static class Matrix3fWrapper extends ValueWrapper { + private float[] value = new float[9]; + + void set(Object value) { + Matrix3f m = (Matrix3f)value; + this.value[0] = m.m00; + this.value[1] = m.m01; + this.value[2] = m.m02; + this.value[3] = m.m10; + this.value[4] = m.m11; + this.value[5] = m.m12; + this.value[6] = m.m20; + this.value[7] = m.m21; + this.value[8] = m.m22; + } + + Object get() { + return new Matrix3f(value); + } + + Object getRef() { + return value; + } + } + + /* + // Wrapper class for Matrix3d + static class Matrix3dWrapper extends ValueWrapper { + private double[] value = new double[9]; + + void set(Object value) { + Matrix3d m = (Matrix3d)value; + this.value[0] = m.m00; + this.value[1] = m.m01; + this.value[2] = m.m02; + this.value[3] = m.m10; + this.value[4] = m.m11; + this.value[5] = m.m12; + this.value[6] = m.m20; + this.value[7] = m.m21; + this.value[8] = m.m22; + } + + Object get() { + return new Matrix3d(value); + } + + Object getRef() { + return value; + } + } + */ + + // Wrapper class for Matrix4f + static class Matrix4fWrapper extends ValueWrapper { + private float[] value = new float[16]; + + void set(Object value) { + Matrix4f m = (Matrix4f)value; + this.value[0] = m.m00; + this.value[1] = m.m01; + this.value[2] = m.m02; + this.value[3] = m.m03; + this.value[4] = m.m10; + this.value[5] = m.m11; + this.value[6] = m.m12; + this.value[7] = m.m13; + this.value[8] = m.m20; + this.value[9] = m.m21; + this.value[10] = m.m22; + this.value[11] = m.m23; + this.value[12] = m.m30; + this.value[13] = m.m31; + this.value[14] = m.m32; + this.value[15] = m.m33; + } + + Object get() { + return new Matrix4f(value); + } + + Object getRef() { + return value; + } + } + + /* + // Wrapper class for Matrix4d + static class Matrix4dWrapper extends ValueWrapper { + private double[] value = new double[16]; + + void set(Object value) { + Matrix4d m = (Matrix4d)value; + this.value[0] = m.m00; + this.value[1] = m.m01; + this.value[2] = m.m02; + this.value[3] = m.m03; + this.value[4] = m.m10; + this.value[5] = m.m11; + this.value[6] = m.m12; + this.value[7] = m.m13; + this.value[8] = m.m20; + this.value[9] = m.m21; + this.value[10] = m.m22; + this.value[11] = m.m23; + this.value[12] = m.m30; + this.value[13] = m.m31; + this.value[14] = m.m32; + this.value[15] = m.m33; + } + + Object get() { + return new Matrix4d(value); + } + + Object getRef() { + return value; + } + } + */ + +} diff --git a/src/classes/share/javax/media/j3d/ShaderBin.java b/src/classes/share/javax/media/j3d/ShaderBin.java new file mode 100644 index 0000000..0e4ad74 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderBin.java @@ -0,0 +1,363 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import javax.vecmath.*; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; + + +// XXXX : We should have a common Bin object that all other Bins extend from. + + +//class ShaderBin extends Object implements ObjectUpdate, NodeComponentUpdate { +class ShaderBin implements ObjectUpdate { + + /** + * Node component dirty mask. + */ + static final int SHADER_PROGRAM_DIRTY = 0x1; + static final int SHADER_ATTRIBUTE_SET_DIRTY = 0x2; + + + /** + * The RenderBin for this object + */ + RenderBin renderBin = null; + + /** + * The AttributeBin that this ShaderBin resides + */ + AttributeBin attributeBin = null; + + /** + * The references to the next and previous ShaderBins in the + * list. + */ + ShaderBin next = null; + ShaderBin prev = null; + + /** + * The list of TextureBins in this ShaderBin + */ + TextureBin textureBinList = null; + + /** + * The list of TextureBins to be added for the next frame + */ + ArrayList addTextureBins = new ArrayList(); + + boolean onUpdateList = false; + + int numEditingTextureBins = 0; + + int componentDirty = 0; + ShaderAppearanceRetained shaderAppearance = null; + ShaderProgramRetained shaderProgram = null; + ShaderAttributeSetRetained shaderAttributeSet = new ShaderAttributeSetRetained(); + + ShaderBin(ShaderAppearanceRetained sApp, RenderBin rBin) { + reset(sApp, rBin); + } + + void reset(ShaderAppearanceRetained sApp, RenderBin rBin) { + prev = null; + next = null; + renderBin = rBin; + attributeBin = null; + textureBinList = null; + onUpdateList = false; + numEditingTextureBins = 0; + addTextureBins.clear(); + if(sApp != null) { + shaderProgram = sApp.shaderProgram; + shaderAttributeSet = sApp.shaderAttributeSet; + } + else { + shaderProgram = null; + shaderAttributeSet = null; + } + shaderAppearance = sApp; + } + + void clear() { + reset(null, null); + } + + /** + * This tests if the qiven ra.shaderProgram match this shaderProgram + */ + boolean equals(ShaderAppearanceRetained sApp) { + + ShaderProgramRetained sp; + ShaderAttributeSetRetained ss; + + if (sApp == null) { + sp = null; + ss = null; + } else { + sp = sApp.shaderProgram; + ss = sApp.shaderAttributeSet; + } + + if((shaderProgram != sp) || (shaderAttributeSet != ss)) { + return false; + } + + return true; + + } + + public void updateObject() { + TextureBin t; + int i; + + if (addTextureBins.size() > 0) { + t = (TextureBin)addTextureBins.get(0); + if (textureBinList == null) { + textureBinList = t; + + } + else { + // Look for a TextureBin that has the same texture + insertTextureBin(t); + } + for (i = 1; i < addTextureBins.size() ; i++) { + t = (TextureBin)addTextureBins.get(i); + // Look for a TextureBin that has the same texture + insertTextureBin(t); + + } + } + addTextureBins.clear(); + onUpdateList = false; + + } + + void insertTextureBin(TextureBin t) { + TextureBin tb; + int i; + TextureRetained texture = null; + + if (t.texUnitState != null && t.texUnitState.length > 0) { + if (t.texUnitState[0] != null) { + texture = t.texUnitState[0].texture; + } + } + + // use the texture in the first texture unit as the sorting criteria + if (texture != null) { + tb = textureBinList; + while (tb != null) { + if (tb.texUnitState == null || tb.texUnitState[0] == null || + tb.texUnitState[0].texture != texture) { + tb = tb.next; + } else { + // put it here + t.next = tb; + t.prev = tb.prev; + if (tb.prev == null) { + textureBinList = t; + } + else { + tb.prev.next = t; + } + tb.prev = t; + return; + } + } + } + // Just put it up front + t.prev = null; + t.next = textureBinList; + textureBinList.prev = t; + textureBinList = t; + + t.tbFlag &= ~TextureBin.RESORT; + } + + + /** + * reInsert textureBin if the first texture is different from + * the previous bin and different from the next bin + */ + void reInsertTextureBin(TextureBin tb) { + + TextureRetained texture = null, + prevTexture = null, + nextTexture = null; + + if (tb.texUnitState != null && tb.texUnitState[0] != null) { + texture = tb.texUnitState[0].texture; + } + + if (tb.prev != null && tb.prev.texUnitState != null) { + prevTexture = tb.prev.texUnitState[0].texture; + } + + if (texture != prevTexture) { + if (tb.next != null && tb.next.texUnitState != null) { + nextTexture = tb.next.texUnitState[0].texture; + } + if (texture != nextTexture) { + if (tb.prev != null && tb.next != null) { + tb.prev.next = tb.next; + tb.next.prev = tb.prev; + insertTextureBin(tb); + } + } + } + } + + + + /** + * Adds the given TextureBin to this AttributeBin. + */ + void addTextureBin(TextureBin t, RenderBin rb, RenderAtom ra) { + + t.environmentSet = this.attributeBin.environmentSet; + t.attributeBin = this.attributeBin; + t.shaderBin = this; + + attributeBin.updateFromShaderBin(ra); + addTextureBins.add(t); + + if (!onUpdateList) { + rb.objUpdateList.add(this); + onUpdateList = true; + } + } + + /** + * Removes the given TextureBin from this ShaderBin. + */ + void removeTextureBin(TextureBin t) { + + // If the TextureBin being remove is contained in addTextureBins, + // then remove the TextureBin from the addList + if (addTextureBins.contains(t)) { + addTextureBins.remove(addTextureBins.indexOf(t)); + } + else { + if (t.prev == null) { // At the head of the list + textureBinList = t.next; + if (t.next != null) { + t.next.prev = null; + } + } else { // In the middle or at the end. + t.prev.next = t.next; + if (t.next != null) { + t.next.prev = t.prev; + } + } + } + + t.shaderBin = null; + t.prev = null; + t.next = null; + + t.clear(); + + renderBin.textureBinFreelist.add(t); + + if (textureBinList == null && addTextureBins.size() == 0 ) { + // Note: Removal of this shaderBin as a user of the rendering + // atttrs is done during removeRenderAtom() in RenderMolecule.java + attributeBin.removeShaderBin(this); + } + } + + /** + * Renders this ShaderBin + */ + void render(Canvas3D cv) { + + TextureBin tb; + + // System.out.println("ShaderBin.render() shaderProgram = " + shaderProgram); + + // include this ShaderBin to the to-be-updated list in canvas + cv.setStateToUpdate(Canvas3D.SHADERBIN_BIT, this); + + tb = textureBinList; + while (tb != null) { + tb.render(cv); + tb = tb.next; + } + } + + void updateTransparentAttributes(Canvas3D cv) { + + // include this ShaderBin to the to-be-updated state set in canvas + cv.setStateToUpdate(Canvas3D.SHADERBIN_BIT, this); + } + + void updateAttributes(Canvas3D cv) { + + // System.out.println("ShaderBin.updateAttributes() shaderProgram is " + shaderProgram); + if (shaderProgram != null) { + // Compile, link, and enable shader program + shaderProgram.updateNative(cv, true); + + if (shaderAttributeSet != null) { + shaderAttributeSet.updateNative(cv, shaderProgram); + } + + } + else { + if (cv.shaderProgram != null) { + // Disable shader program + cv.shaderProgram.updateNative(cv, false); + } + } + + cv.shaderBin = this; + cv.shaderProgram = shaderProgram; + } + + void updateNodeComponent() { + // System.out.println("ShaderBin.updateNodeComponent() ..."); + + // We don't need to clone shaderProgram. + // ShaderProgram object can't be modified once it is live, + // so each update should be a new reference. + if ((componentDirty & SHADER_PROGRAM_DIRTY) != 0) { + // System.out.println(" - SHADER_PROGRAM_DIRTY"); + + shaderProgram = shaderAppearance.shaderProgram; + } + + // We need to clone the shaderAttributeSet. + if ((componentDirty & SHADER_ATTRIBUTE_SET_DIRTY) != 0) { + // System.out.println(" - SHADER_ATTRIBUTE_SET_DIRTY"); + + HashMap attrs = (HashMap)shaderAttributeSet.getAttrs(); + attrs.clear(); + if(shaderAppearance.shaderAttributeSet != null) { + attrs.putAll(shaderAppearance.shaderAttributeSet.getAttrs()); + } + } + + componentDirty = 0; + } + + void incrActiveTextureBin() { + numEditingTextureBins++; + } + + void decrActiveTextureBin() { + numEditingTextureBins--; + } +} diff --git a/src/classes/share/javax/media/j3d/ShaderError.java b/src/classes/share/javax/media/j3d/ShaderError.java new file mode 100644 index 0000000..52c60f7 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderError.java @@ -0,0 +1,410 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.io.PrintStream; + +/** + * ShaderError is a container object that holds the details of + * a runtime error that occurs while compiling or executing a + * programmable shader. + * + * @since Java 3D 1.4 + */ +public class ShaderError extends Object { + private int errorCode = NO_ERROR; + private String errorMessage = null; + private String detailMessage = null; + private Canvas3D canvas = null; + private Shape3D shape = null; + private Geometry geometry = null; + private ShaderAppearance shaderApp = null; + private ShaderProgram shaderProgram = null; + private Shader shader = null; + private ShaderAttributeSet shaderAttributeSet = null; + private ShaderAttribute shaderAttribute = null; + + /** + * Indicates that no error occurred. + */ + public static final int NO_ERROR = 0; + + /** + * Indicates that an error occurred while compiling a shader. + */ + public static final int COMPILE_ERROR = 1; + + /** + * Indicates that an error occurred while linking a shader. + */ + public static final int LINK_ERROR = 2; + + /** + * Indicates a error in looking up a vertex attribute + * name within a given shader program. + */ + public static final int VERTEX_ATTRIBUTE_LOOKUP_ERROR = 3; + + /** + * Indicates a error in looking up the location of a uniform + * shader attribute name within a given shader program. + */ + public static final int SHADER_ATTRIBUTE_LOOKUP_ERROR = 4; + + /** + * Indicates a error caused by a ShaderAttribute whose name does not + * appear in the list of shader attribute names in the corresponding + * ShaderProgram object. + */ + public static final int SHADER_ATTRIBUTE_NAME_NOT_SET_ERROR = 5; + + /** + * Indicates a error in the type of the attribute versus what the shader + * program was expecting. + */ + public static final int SHADER_ATTRIBUTE_TYPE_ERROR = 6; + + /** + * Indicates that the specified shading language is not supported + * on the screen display device. + */ + public static final int UNSUPPORTED_LANGUAGE_ERROR = 7; + + + /** + * Constructs a new ShaderError object indicating no error. The + * error code is set to <code>NO_ERROR</code>. All other fields + * are initialized to null, including the error message. + */ + public ShaderError() { + } + + /** + * Constructs a new ShaderError object with the given error code + * and message. All other fields are initialized to null. + * + * @param errorCode the error code for this shader error. + * + * @param errorMessage a short error message describing this + * shader error. + */ + public ShaderError(int errorCode, String errorMessage) { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } + + /** + * Prints a verbose error report to System.err. This verbose + * output includes the error code, error message, detail message, + * and all relevant Java 3D objects. + */ + public void printVerbose() { + printVerbose(System.err); + } + + /** + * Prints a verbose error report to the specified PrintStream. + * This verbose output includes the error code, error message, + * detail message, and all relevant Java 3D objects. + * + * @param printStream the print stream on which to print the error + * report. + */ + public void printVerbose(PrintStream printStream) { + printStream.println(this); + if (canvas != null) { + printStream.println("canvas = " + canvas); + } + if (shape != null) { + printStream.println("shape = " + shape); + } + if (geometry != null) { + printStream.println("geometry = " + geometry); + } + if (shaderApp != null) { + printStream.println("shaderApp = " + shaderApp); + } + if (shaderProgram != null) { + printStream.println("shaderProgram = " + shaderProgram); + } + if (shader != null) { + printStream.println("shader = " + shader); + } + if (shaderAttributeSet != null) { + printStream.println("shaderAttributeSet = " + shaderAttributeSet); + } + if (shaderAttribute != null) { + printStream.println("shaderAttribute = " + shaderAttribute); + } + + if (detailMessage != null) { + printStream.println(); + printStream.println("Detail Message"); + printStream.println("--------------"); + printStream.println(detailMessage); + } + } + + /** + * Sets the error code for this shader error. This represents the + * type of error that occurred. + * + * @param errorCode the error code for this shader error. + */ + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + /** + * Returns the error code for this shader error. + * + * @return the error code. + */ + public int getErrorCode() { + return errorCode; + } + + /** + * Sets the error message for this shader error. This is a short + * message describing the error, and is included as part of + * toString(). + * + * @param errorMessage a short error message describing this + * shader error. + */ + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + /** + * Returns the error message for this shader error. + * + * @return a short error message describing this shader error. + */ + public String getErrorMessage() { + return errorMessage; + } + + /** + * Sets the detail message for this shader error. This is a + * detailed error message, typically produced by the shader + * compiler, and is not included as part of toString(). + * + * @param detailMessage a detailed message describing this shader + * error in more detail. + */ + public void setDetailMessage(String detailMessage) { + this.detailMessage = detailMessage; + } + + /** + * Returns the detail message for this shader error. + * + * @return the detail message for this shader error. + */ + public String getDetailMessage() { + return detailMessage; + } + + /** + * Sets the canvas associated with this shader error. + * + * @param canvas the canvas associated with this shader error. + */ + public void setCanvas3D(Canvas3D canvas) { + this.canvas = canvas; + } + + /** + * Returns the canvas associated with this shader error. + * + * @return the canvas associated with this shader error. + */ + public Canvas3D getCanvas3D() { + return this.canvas; + } + + /** + * Sets the shape node associated with this shader error. + * + * @param shape the shape node associated with this shader error. + */ + public void setShape3D(Shape3D shape) { + this.shape = shape; + } + + /** + * Returns the shape node associated with this shader error. + * + * @return the shape node associated with this shader error. + */ + public Shape3D getShape3D() { + return this.shape; + } + + /** + * Sets the geometry associated with this shader error. + * + * @param geometry the geometry associated with this shader error. + */ + public void setGeometry(Geometry geometry) { + this.geometry = geometry; + } + + /** + * Returns the geometry associated with this shader error. + * + * @return the geometry associated with this shader error. + */ + public Geometry getGeometry() { + return this.geometry; + } + + /** + * Sets the shader appearance associated with this shader error. + * + * @param shaderApp the shader appearance associated with this shader error. + */ + public void setShaderAppearance(ShaderAppearance shaderApp) { + this.shaderApp = shaderApp; + } + + /** + * Returns the shader appearance associated with this shader error. + * + * @return the shader appearance associated with this shader error. + */ + public ShaderAppearance getShaderAppearance() { + return this.shaderApp; + } + + /** + * Sets the shader program associated with this shader error. + * + * @param shaderProgram the shader program associated with this shader error. + */ + public void setShaderProgram(ShaderProgram shaderProgram) { + this.shaderProgram = shaderProgram; + } + + /** + * Returns the shader program associated with this shader error. + * + * @return the shader program associated with this shader error. + */ + public ShaderProgram getShaderProgram() { + return this.shaderProgram; + } + + /** + * Sets the shader object associated with this shader error. + * + * @param shader the shader object associated with this shader error. + */ + public void setShader(Shader shader) { + this.shader = shader; + } + + /** + * Returns the shader object associated with this shader error. + * + * @return the shader object associated with this shader error. + */ + public Shader getShader() { + return this.shader; + } + + /** + * Sets the shader attribute set associated with this shader error. + * + * @param shaderAttributeSet the shader attribute set associated with this shader error. + */ + public void setShaderAttributeSet(ShaderAttributeSet shaderAttributeSet) { + this.shaderAttributeSet = shaderAttributeSet; + } + + /** + * Returns the shader attribute set associated with this shader error. + * + * @return the shader attribute set associated with this shader error. + */ + public ShaderAttributeSet getShaderAttributeSet() { + return this.shaderAttributeSet; + } + + /** + * Sets the shader attribute associated with this shader error. + * + * @param shaderAttribute the shader attribute associated with this shader error. + */ + public void setShaderAttribute(ShaderAttribute shaderAttribute) { + this.shaderAttribute = shaderAttribute; + } + + /** + * Returns the shader attribute associated with this shader error. + * + * @return the shader attribute associated with this shader error. + */ + public ShaderAttribute getShaderAttribute() { + return this.shaderAttribute; + } + + + /** + * Returns a short string that describes this shader error. The + * string is composed of the textual description of the errorCode, + * a ": ", and the errorMessage field. If the errorMessage is + * null then the ": " and the errorMessage are omitted. + * + * @return a string representation of this shader error. + */ + public String toString() { + // Concatenate string representation of error code with error message + String errorCodeStr; + switch (errorCode) { + case NO_ERROR: + errorCodeStr = "NO_ERROR"; + break; + case COMPILE_ERROR: + errorCodeStr = "COMPILE_ERROR"; + break; + case LINK_ERROR: + errorCodeStr = "LINK_ERROR"; + break; + case VERTEX_ATTRIBUTE_LOOKUP_ERROR: + errorCodeStr = "VERTEX_ATTRIBUTE_LOOKUP_ERROR"; + break; + case SHADER_ATTRIBUTE_LOOKUP_ERROR: + errorCodeStr = "SHADER_ATTRIBUTE_LOOKUP_ERROR"; + break; + case SHADER_ATTRIBUTE_NAME_NOT_SET_ERROR: + errorCodeStr = "SHADER_ATTRIBUTE_NAME_NOT_SET_ERROR"; + break; + case SHADER_ATTRIBUTE_TYPE_ERROR: + errorCodeStr = "SHADER_ATTRIBUTE_TYPE_ERROR"; + break; + case UNSUPPORTED_LANGUAGE_ERROR: + errorCodeStr = "UNSUPPORTED_LANGUAGE_ERROR"; + break; + default: + errorCodeStr = "UNKNOWN ERROR CODE (" + errorCode + ")"; + } + + if (errorMessage == null) { + return errorCodeStr; + } + + return errorCodeStr + ": " + errorMessage; + } +} diff --git a/src/classes/share/javax/media/j3d/ShaderErrorListener.java b/src/classes/share/javax/media/j3d/ShaderErrorListener.java new file mode 100644 index 0000000..978a251 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderErrorListener.java @@ -0,0 +1,33 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * Listener interface for monitoring errors in Shader Programs. + * Compile and link errors are reported by the shader compiler, as are + * runtime errors, such as those resulting from shader attributes that + * aren't found or are of the wrong type. + * + * @see VirtualUniverse#addShaderErrorListener + * + * @since Java 3D 1.4 + */ +public interface ShaderErrorListener { + /** + * Invoked when an error occurs while compiling, linking or + * executing a programmable shader. + * + * @param error object that contains the details of the error. + */ + public void errorOccurred(ShaderError error); +} diff --git a/src/classes/share/javax/media/j3d/ShaderProgram.java b/src/classes/share/javax/media/j3d/ShaderProgram.java new file mode 100644 index 0000000..2d4fc72 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderProgram.java @@ -0,0 +1,194 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The ShaderProgram node component object is the abstract base class + * for programmable shader programs. Each concrete instance of a + * ShaderProgram is a container for a set of Shader objects. The set + * of Shaders contained in the ShaderProgram is a complete program for + * the Graphics Pipeline Unit (GPU) of the graphics accelerator. It is + * specified using the shader language defined by the + * ShaderProgram. The currently defined shader languages are: Cg and + * GLSL. + * + * <p> + * NOTE: Applications should <i>not</i> extend this class. + * + * @see Shader + * @see ShaderAppearance#setShaderProgram + * + * @since Java 3D 1.4 + */ + +public abstract class ShaderProgram extends NodeComponent { + + /** + * Specifies that this ShaderProgram object allows reading + * its shaders. + */ + public static final int ALLOW_SHADERS_READ = + CapabilityBits.SHADER_PROGRAM_ALLOW_SHADERS_READ; + + /** + * Specifies that this ShaderProgram object allows reading + * its shader or vertex attribute names. + */ + public static final int ALLOW_NAMES_READ = + CapabilityBits.SHADER_PROGRAM_ALLOW_NAMES_READ; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SHADERS_READ, + ALLOW_NAMES_READ + }; + + /* + * Default values (copied from GeometryArray.java): + * + * vertexAttrNames : null<br> + */ + + /** + * Package scope constructor so it can't be subclassed by classes + * outside the javax.media.j3d package. + */ + ShaderProgram() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } + + /** + * Sets the vertex attribute names array for this ShaderProgram + * object. Each element in the array specifies the shader + * attribute name that is bound to the corresponding numbered + * vertex attribute within a GeometryArray object that uses this + * shader program. Array element 0 specifies the name of + * GeometryArray vertex attribute 0, array element 1 specifies the + * name of GeometryArray vertex attribute 1, and so forth. + * The array of names may be null or empty (0 length), but the + * elements of the array must be non-null. + * + * @param vertexAttrNames array of vertex attribute names for this + * shader program. A copy of this array is made. + * + * @exception RestrictedAccessException if the method is called + * when this object is part of live or compiled scene graph. + * + * @exception NullPointerException if any element in the + * vertexAttrNames array is null. + */ + public abstract void setVertexAttrNames(String[] vertexAttrNames); + + /** + * Retrieves the vertex attribute names array from this + * ShaderProgram object. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @return a copy of this ShaderProgram's array of vertex attribute names. + */ + public abstract String[] getVertexAttrNames(); + + + /** + * Sets the shader attribute names array for this ShaderProgram + * object. Each element in the array specifies a shader + * attribute name that may be set via a ShaderAttribute object. + * Only those attributes whose names that appear in the shader + * attribute names array can be set for a given shader program. + * The array of names may be null or empty (0 length), but the + * elements of the array must be non-null. + * + * <p> + * TODO: finish this. + * + * @param shaderAttrNames array of shader attribute names for this + * shader program. A copy of this array is made. + * + * @exception RestrictedAccessException if the method is called + * when this object is part of live or compiled scene graph. + * + * @exception NullPointerException if any element in the + * shaderAttrNames array is null. + */ + public abstract void setShaderAttrNames(String[] shaderAttrNames); + + /** + * Retrieves the shader attribute names array from this + * ShaderProgram object. + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @return a copy of this ShaderProgram's array of shader attribute names. + */ + public abstract String[] getShaderAttrNames(); + + + /** + * Copies the specified array of shaders into this shader + * program. This method makes a shallow copy of the array. The + * array of shaders may be null or empty (0 length), but the + * elements of the array must be non-null. The shading + * language of each shader in the array must match the + * subclass. Subclasses may impose additional restrictions. + * + * @param shaders array of Shader objects to be copied into this + * ShaderProgram + * + * @exception RestrictedAccessException if the method is called + * when this object is part of live or compiled scene graph. + * + * @exception IllegalArgumentException if the shading language of + * any shader in the shaders array doesn't match the type of the + * subclass. + * + * @exception NullPointerException if any element in the + * shaders array is null. + */ + public abstract void setShaders(Shader[] shaders); + + /** + * Retrieves the array of shaders from this shader program. A + * shallow copy of the array is returned. The return value may + * be null. + * + * @return a copy of this ShaderProgram's array of Shader objects + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + */ + public abstract Shader[] getShaders(); + + + // Default shader error listener class + private static ShaderErrorListener defaultErrorListener = null; + + synchronized static ShaderErrorListener getDefaultErrorListener() { + if (defaultErrorListener == null) { + defaultErrorListener = new DefaultErrorListener(); + } + + return defaultErrorListener; + } + + static class DefaultErrorListener implements ShaderErrorListener { + public void errorOccurred(ShaderError error) { + System.err.println(); + System.err.println("DefaultShaderErrorListener.errorOccurred:"); + error.printVerbose(); + } + } +} diff --git a/src/classes/share/javax/media/j3d/ShaderProgramRetained.java b/src/classes/share/javax/media/j3d/ShaderProgramRetained.java new file mode 100644 index 0000000..fadcda0 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderProgramRetained.java @@ -0,0 +1,1196 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.*; +import javax.vecmath.*; + +/** + * The ShaderProgramRetained object is a component object of an AppearanceRetained + * object that defines the shader properties used when programmable shader is + * enabled. ShaderProgramRetained object is an abstract class. All shader program + * objects must be created as either a GLSLShaderProgramRetained object or a + * CgShaderProgramRetained object. + */ +abstract class ShaderProgramRetained extends NodeComponentRetained { + + // Each element in the array corresponds to a unique renderer if shared + // context or a unique canvas otherwise. + protected ShaderProgramData shaderProgramData[]; + + // Flag indicating whether an UNSUPPORTED_LANGUAGE_ERROR has + // already been reported for this shader program object. It is + // set in verifyShaderProgram and cleared in setLive or clearLive. + // TODO KCR: Add code to clear this in setLive or clearLive + private boolean unsupportedErrorReported = false; + + // Flag indicating whether a LINK_ERROR has occurred for this shader program + // object. It is set in updateNative to indicate that the linkShaderProgram + // operation failed. It is cleared in setLive or clearLive. + // TODO KCR: Add code to clear this in setLive or clearLive + private boolean linkErrorOccurred = false; + + // an array of shaders used by this shader program + protected ShaderRetained[] shaders; + + // an array of vertex attribute names + protected String[] vertexAttrNames; + + // an array of (uniform) shader attribute names + protected String[] shaderAttrNames; + + // Set of ShaderAttribute objects for which we have already reported an error + private HashSet shaderAttrErrorSet = null; + + // need to synchronize access from multiple rendering threads + Object resourceLock = new Object(); + + /** + * Sets the vertex attribute names array for this ShaderProgram + * object. Each element in the array specifies the shader + * attribute name that is bound to the corresponding numbered + * vertex attribute within a GeometryArray object that uses this + * shader program. Array element 0 specifies the name of + * GeometryArray vertex attribute 0, array element 1 specifies the + * name of GeometryArray vertex attribute 1, and so forth. + * The array of names may be null or empty (0 length), but the + * elements of the array must be non-null. + * + * @param vertexAttrNames array of vertex attribute names for this + * shader program. A copy of this array is made. + */ + void setVertexAttrNames(String[] vertexAttrNames) { + if (vertexAttrNames == null) { + this.vertexAttrNames = null; + } + else { + this.vertexAttrNames = (String[])vertexAttrNames.clone(); + } + } + + + /** + * Retrieves the vertex attribute names array from this + * ShaderProgram object. + * + * @return a copy of this ShaderProgram's array of vertex attribute names. + */ + String[] getVertexAttrNames() { + + if (vertexAttrNames == null) { + return null; + } + + return (String[])vertexAttrNames.clone(); + + } + + + /** + * Sets the shader attribute names array for this ShaderProgram + * object. Each element in the array specifies a shader + * attribute name that may be set via a ShaderAttribute object. + * Only those attributes whose names that appear in the shader + * attribute names array can be set for a given shader program. + * The array of names may be null or empty (0 length), but the + * elements of the array must be non-null. + * + * @param shaderAttrNames array of shader attribute names for this + * shader program. A copy of this array is made. + */ + void setShaderAttrNames(String[] shaderAttrNames) { + if (shaderAttrNames == null) { + this.shaderAttrNames = null; + } + else { + this.shaderAttrNames = (String[])shaderAttrNames.clone(); + } + } + + + /** + * Retrieves the shader attribute names array from this + * ShaderProgram object. + * + * @return a copy of this ShaderProgram's array of shader attribute names. + */ + + String[] getShaderAttrNames() { + + if (shaderAttrNames == null) { + return null; + } + + return (String[])shaderAttrNames.clone(); + + } + + + + /** + * Copies the specified array of shaders into this shader + * program. This method makes a shallow copy of the array. The + * array of shaders may be null or empty (0 length), but the + * elements of the array must be non-null. The shading + * language of each shader in the array must match the + * subclass. Subclasses may impose additional restrictions. + * + * @param shaders array of Shader objects to be copied into this + * ShaderProgram + * + * @exception CapabilityNotSetException if appropriate capability is + * not set and this object is part of live or compiled scene graph + * + * @exception IllegalArgumentException if the shading language of + * any shader in the shaders array doesn't match the type of the + * subclass. + */ + void setShaders(Shader[] shaders) { + + if (shaders == null) { + this.shaders = null; + return; + } + + this.shaders = new ShaderRetained[shaders.length]; + + // Copy vertex and fragment shader + for (int i = 0; i < shaders.length; i++) { + this.shaders[i] = (ShaderRetained)shaders[i].retained; + } + + } + + /** + * Retrieves the array of shaders from this shader program. A + * shallow copy of the array is returned. The return value may + * be null. + * + * @return a copy of this ShaderProgram's array of Shader objects + * + */ + Shader[] getShaders() { + + if (shaders == null) { + return null; + } else { + Shader shads[] = + new Shader[shaders.length]; + for (int i = 0; i < shaders.length; i++) { + if (shaders[i] != null) { + shads[i] = (Shader) shaders[i].source; + } else { + shads[i] = null; + } + } + return shads; + } + } + + /** + * Method to create the native shader. + */ + abstract ShaderError createShader(long ctx, ShaderRetained shader, long[] shaderIdArr); + + /** + * Method to destroy the native shader. + */ + abstract ShaderError destroyShader(long ctx, long shaderId); + + /** + * Method to compile the native shader. + */ + abstract ShaderError compileShader(long ctx, long shaderId, String source); + + /** + * Method to create the native shader program. + */ + abstract ShaderError createShaderProgram(long ctx, long[] shaderProgramIdArr); + + /** + * Method to destroy the native shader program. + */ + abstract ShaderError destroyShaderProgram(long ctx, long shaderProgramId); + + /** + * Method to link the native shader program. + */ + abstract ShaderError linkShaderProgram(long ctx, long shaderProgramId, long[] shaderIds); + + /** + * Method to bind a vertex attribute name to the specified index. + */ + abstract ShaderError bindVertexAttrName(long ctx, long shaderProgramId, String attrName, int attrIndex); + + /** + * Method to lookup a list of (uniform) shader attribute names and return + * information about the attributes. + */ + abstract void lookupShaderAttrNames(long ctx, long shaderProgramId, String[] attrNames, AttrNameInfo[] attrNameInfoArr); + + /* + * Method to lookup a list of vertex attribute names. + */ + abstract void lookupVertexAttrNames(long ctx, long shaderProgramId, String[] attrNames, boolean[] errArr); + + /** + * Method to use the native shader program. + */ + abstract ShaderError enableShaderProgram(long ctx, long shaderProgramId); + + /** + * Method to disable the native shader program. + */ + abstract ShaderError disableShaderProgram(long ctx); + + // ShaderAttributeValue methods + + abstract ShaderError setUniform1i(long ctx, + long shaderProgramId, + long uniformLocation, + int value); + + abstract ShaderError setUniform1f(long ctx, + long shaderProgramId, + long uniformLocation, + float value); + + abstract ShaderError setUniform2i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + abstract ShaderError setUniform2f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + abstract ShaderError setUniform3i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + abstract ShaderError setUniform3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + abstract ShaderError setUniform4i(long ctx, + long shaderProgramId, + long uniformLocation, + int[] value); + + abstract ShaderError setUniform4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + abstract ShaderError setUniformMatrix3f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + abstract ShaderError setUniformMatrix4f(long ctx, + long shaderProgramId, + long uniformLocation, + float[] value); + + + // ShaderAttributeArray methods + + abstract ShaderError setUniform1iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setUniform1fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setUniform2iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setUniform2fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setUniform3iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setUniform3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setUniform4iArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + int[] value); + + abstract ShaderError setUniform4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setUniformMatrix3fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + abstract ShaderError setUniformMatrix4fArray(long ctx, + long shaderProgramId, + long uniformLocation, + int numElements, + float[] value); + + + /** + * Method to return a flag indicating whether this + * ShaderProgram is supported on the specified Canvas. + */ + abstract boolean isSupported(Canvas3D cv); + + + void setLive(boolean backgroundGroup, int refCount) { + + // System.out.println("ShaderProgramRetained.setLive()"); + + if (shaders != null) { + for (int i = 0; i < shaders.length; i++){ + shaders[i].setLive(backgroundGroup, refCount); + } + } + + super.doSetLive(backgroundGroup, refCount); + super.markAsLive(); + + } + + void clearLive(int refCount) { + + // System.out.println("ShaderProgramRetained.clearLive()"); + + super.clearLive(refCount); + + if (shaders != null) { + for (int i = 0; i < shaders.length; i++) { + shaders[i].clearLive(refCount); + } + } + } + + /** + * Method to enable the native shader program. + */ + private ShaderError enableShaderProgram(Canvas3D cv, int cvRdrIndex) { + assert(cvRdrIndex >= 0); + synchronized(resourceLock) { + return enableShaderProgram(cv.ctx, + shaderProgramData[cvRdrIndex].getShaderProgramId()); + } + + } + + /** + * Method to disable the native shader program. + */ + private ShaderError disableShaderProgram(Canvas3D cv) { + return disableShaderProgram(cv.ctx); + } + + /** + * Initializes a mirror object. + */ + synchronized void initMirrorObject() { + + // Create mirror copy of shaders + if (this.shaders == null) { + ((ShaderProgramRetained)mirror).shaders = null; + } + else { + ((ShaderProgramRetained)mirror).shaders = new ShaderRetained[this.shaders.length]; + // Copy vertex and fragment shader + for (int i = 0; i < this.shaders.length; i++) { + ((ShaderProgramRetained)mirror).shaders[i] = + (ShaderRetained)this.shaders[i].mirror; + } + } + ((ShaderProgramRetained)mirror).shaderProgramData = null; + + // Create mirror copy of vertex attribute names + if (this.vertexAttrNames == null) { + ((ShaderProgramRetained)mirror).vertexAttrNames = null; + } + else { + ((ShaderProgramRetained)mirror).vertexAttrNames = (String[])this.vertexAttrNames.clone(); + } + + // Create mirror copy of shader attribute names + if (this.shaderAttrNames == null) { + ((ShaderProgramRetained)mirror).shaderAttrNames = null; + } + else { + ((ShaderProgramRetained)mirror).shaderAttrNames = (String[])this.shaderAttrNames.clone(); + } + + // Clear shader attribute error set + ((ShaderProgramRetained)mirror).shaderAttrErrorSet = null; + } + + /** + * Update the "component" field of the mirror object with the given "value" + */ + synchronized void updateMirrorObject(int component, Object value) { + + // ShaderProgram can't be modified once it is live. + assert(false); + System.out.println("ShaderProgramRetained : updateMirrorObject NOT IMPLEMENTED YET"); + } + + /** + * Method to create a ShaderProgramData object for the specified + * canvas/renderer if it doesn't already exist + */ + private void createShaderProgramData(int cvRdrIndex) { + // Create shaderProgram resources if it has not been done. + synchronized(resourceLock) { + if(shaderProgramData == null) { + // We rely on Java to initial the array elements to null. + shaderProgramData = new ShaderProgramData[cvRdrIndex+1]; + } + else if(shaderProgramData.length <= cvRdrIndex) { + // We rely on Java to initial the array elements to null. + ShaderProgramData[] tempSPData = new ShaderProgramData[cvRdrIndex+1]; + System.arraycopy(shaderProgramData, 0, + tempSPData, 0, + shaderProgramData.length); + shaderProgramData = tempSPData; + } + + if(shaderProgramData[cvRdrIndex] == null) { + shaderProgramData[cvRdrIndex] = new ShaderProgramData(); + } + } + } + + /** + * Method to create the native shader program. We must already have + * called createShaderProgramData for this cvRdrIndex. + */ + private ShaderError createShaderProgram(Canvas3D cv, int cvRdrIndex) { + // Create shaderProgram resources if it has not been done. + synchronized(resourceLock) { + assert(shaderProgramData[cvRdrIndex].getShaderProgramId() == 0); + + long[] spIdArr = new long[1]; + ShaderError err = createShaderProgram(cv.ctx, spIdArr); + if(err != null) { + return err; + } + shaderProgramData[cvRdrIndex].setShaderProgramId(spIdArr[0]); + } + + return null; + } + + /** + * Method to link the native shader program. + */ + private ShaderError linkShaderProgram(Canvas3D cv, int cvRdrIndex, + ShaderRetained[] shaders) { + synchronized(resourceLock) { + long[] shaderIds = new long[shaders.length]; + for(int i=0; i<shaders.length; i++) { + synchronized(shaders[i]) { + shaderIds[i] = shaders[i].shaderIds[cvRdrIndex]; + } + } + ShaderError err = + linkShaderProgram(cv.ctx, + shaderProgramData[cvRdrIndex].getShaderProgramId(), + shaderIds); + if(err != null) { + return err; + } + shaderProgramData[cvRdrIndex].setLinked(true); + } + + return null; + } + + + private ShaderError bindVertexAttrName(Canvas3D cv, int cvRdrIndex, String attrName, int attrIndex) { + assert(attrName != null); + synchronized(resourceLock) { + long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); +// System.err.println("attrName = " + attrName); + ShaderError err = bindVertexAttrName(cv.ctx, shaderProgramId, attrName, attrIndex); + if (err != null) { + return err; + } + } + return null; + } + + private void lookupVertexAttrNames(Canvas3D cv, int cvRdrIndex, String[] attrNames) { + synchronized(resourceLock) { + long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); + + boolean[] errArr = new boolean[attrNames.length]; + lookupVertexAttrNames(cv.ctx, shaderProgramId, attrNames, errArr); + + for (int i = 0; i < attrNames.length; i++) { + // Report non-fatal error if detected + if (errArr[i]) { + String errMsg = "Vertex Attribute name lookup failed: " + attrNames[i]; + ShaderError err = new ShaderError(ShaderError.VERTEX_ATTRIBUTE_LOOKUP_ERROR, errMsg); + err.setShaderProgram((ShaderProgram)this.source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + } + } + } + } + + + private void lookupShaderAttrNames(Canvas3D cv, int cvRdrIndex, String[] attrNames) { + synchronized(resourceLock) { + long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); + + AttrNameInfo[] attrNameInfoArr = new AttrNameInfo[attrNames.length]; + lookupShaderAttrNames(cv.ctx, shaderProgramId, attrNames, attrNameInfoArr); + + for (int i = 0; i < attrNames.length; i++) { + shaderProgramData[cvRdrIndex].setAttrNameInfo(attrNames[i], attrNameInfoArr[i]); + + // Report non-fatal error if location is invalid (-1) + if (attrNameInfoArr[i].getLocation() == -1) { + String errMsg = "Attribute name lookup failed: " + attrNames[i]; + ShaderError err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_LOOKUP_ERROR, errMsg); + err.setShaderProgram((ShaderProgram)this.source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + } + } + } + } + + + /** + * Method to return the shaderProgram data for the specified canvas or renderer + */ + private ShaderProgramData getShaderProgramData(int cvRdrIndex) { + synchronized(resourceLock) { + return shaderProgramData[cvRdrIndex]; + } + } + + /** + * Method to create the native shader. + */ + private ShaderError createShader(Canvas3D cv, int cvRdrIndex, ShaderRetained shader) { + + // Create shaderProgram resources if it has not been done. + synchronized(shader.resourceLock) { + if(shader.shaderIds == null){ + // We rely on Java to initial the array elements to 0 or false; + shader.shaderIds = new long[cvRdrIndex+1]; + shader.compiled = new boolean[cvRdrIndex+1]; + } else if( shader.shaderIds.length <= cvRdrIndex) { + // We rely on Java to initial the array elements to 0 or false; + long[] tempSIds = new long[cvRdrIndex+1]; + boolean[] tempCompiled = new boolean[cvRdrIndex+1]; + + System.arraycopy(shader.shaderIds, 0, + tempSIds, 0, + shader.shaderIds.length); + shader.shaderIds = tempSIds; + + System.arraycopy(shader.compiled, 0, + tempCompiled, 0, + shader.compiled.length); + shader.compiled = tempCompiled; + } + + if(shader.shaderIds[cvRdrIndex] != 0) { + // We have already created the shaderId for this Canvas. + return null; + } + + long[] shaderIdArr = new long[1]; + ShaderError err = createShader(cv.ctx, shader, shaderIdArr); + if(err != null) { + return err; + } + shader.shaderIds[cvRdrIndex] = shaderIdArr[0]; + } + return null; + } + + /** + * Method to compile the native shader. + */ + private ShaderError compileShader(Canvas3D cv, int cvRdrIndex, ShaderRetained shader) { + + synchronized(shader.resourceLock) { + + if(shader.compiled[cvRdrIndex] == true) { + // We have already compiled the shaderId for this Canvas. + return null; + } + + String source = ((SourceCodeShaderRetained)shader).getShaderSource(); + ShaderError err = compileShader(cv.ctx, shader.shaderIds[cvRdrIndex], source); + if(err != null) { + return err; + } + shader.compiled[cvRdrIndex] = true; + } + + return null; + } + + /** + * Send a message to the notification thread, which will call the + * shader error listeners. + */ + void notifyErrorListeners(Canvas3D cv, ShaderError err) { + J3dNotification notification = new J3dNotification(); + notification.type = J3dNotification.SHADER_ERROR; + notification.universe = cv.view.universe; + notification.args[0] = err; + VirtualUniverse.mc.sendNotification(notification); + } + + + /** + * This method checks whether this ShaderProgram is supported on + * the specified Canvas. If it isn't supported, it will report a + * ShaderError unless an error has already been reported for this + * shader program. + */ + private boolean verifyShaderProgramSupported(Canvas3D cv) { + boolean supported = isSupported(cv); + if (!supported && !unsupportedErrorReported) { + String errorMsg = J3dI18N.getString("ShaderProgramRetained0"); + ShaderError err = new ShaderError(ShaderError.UNSUPPORTED_LANGUAGE_ERROR, errorMsg); + err.setShaderProgram((ShaderProgram)this.source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + unsupportedErrorReported = true; + } + return supported; + } + + /** + * Method to destroy the native shader. + */ + void destroyShader(Canvas3D cv, int cvRdrIndex, ShaderRetained shader) { + if (!verifyShaderProgramSupported(cv)) { + return; + } + + // Destroy shader resource if it exists + synchronized(shader.resourceLock) { + // Check whether an entry in the shaderIds array has been allocated + if (shader.shaderIds == null || shader.shaderIds.length <= cvRdrIndex) { + return; + } + + // Nothing to do if the shaderId is 0 + if (shader.shaderIds[cvRdrIndex] == 0) { + return; + } + + // Destroy the native resource and set the ID to 0 for this canvas/renderer + // Ignore any possible shader error, because there is no meaningful way to report it + destroyShader(cv.ctx, shader.shaderIds[cvRdrIndex]); + shader.shaderIds[cvRdrIndex] = 0; + } + } + + + /** + * Method to destroy the native shader program. + */ + void destroyShaderProgram(Canvas3D cv, int cvRdrIndex) { + if (!verifyShaderProgramSupported(cv)) { + return; + } + + // Destroy shaderProgram resource if it exists + synchronized(resourceLock) { + assert(shaderProgramData != null && + shaderProgramData.length > cvRdrIndex && + shaderProgramData[cvRdrIndex] != null); + +// // Check whether an entry in the shaderProgramData array has been allocated +// if (shaderProgramData == null || +// shaderProgramData.length <= cvRdrIndex || +// shaderProgramData[cvRdrIndex] == null) { +// return; +// } + + long shaderProgramId = shaderProgramData[cvRdrIndex].getShaderProgramId(); + // Nothing to do if the shaderProgramId is 0 + if (shaderProgramId == 0) { + return; + } + + // Destroy the native resource, set the ID to 0 for this canvas/renderer, + // and clear the bit in the resourceCreationMask + // Ignore any possible shader error, because there is no meaningful way to report it + destroyShaderProgram(cv.ctx, shaderProgramId); + // Reset this ShaderProgramData object. + shaderProgramData[cvRdrIndex].reset(); + } + } + + + /** + * updateNative is called while traversing the RenderBin to + * update the shader program state + */ + void updateNative(Canvas3D cv, boolean enable) { + // System.out.println("ShaderProgramRetained.updateNative : "); + + final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != 0; + final int cvRdrIndex = useSharedCtx ? cv.screen.renderer.rendererId : cv.canvasId; + + // Create ShaderProgramData object for this canvas/renderer if it doesn't already exist + createShaderProgramData(cvRdrIndex); + + // Check whether this shader program type is supported for this canvas + if (!verifyShaderProgramSupported(cv)) { + return; + } + + // Just disable shader program and return if enable parameter is set to false + if (!enable) { + // Given the current design, disableShaderProgram cannot return a non-null value, + // so no need to check it + disableShaderProgram(cv); + return; + } + + // Just disable shader program and return if array of shaders is empty, + // or if a previous attempt to link resulted in an error + if (shaders == null || shaders.length == 0 || linkErrorOccurred) { + disableShaderProgram(cv); + return; + } + + boolean loadShaderProgram = false; // flag indicating whether to reload all shaderProgram states + if (getShaderProgramData(cvRdrIndex).getShaderProgramId() == 0) { + loadShaderProgram = true; + } + + //System.out.println(".... loadShaderProgram = " + loadShaderProgram); + //System.out.println(".... resourceCreationMask= " + resourceCreationMask); + + ShaderError err = null; + boolean errorOccurred = false; + if (loadShaderProgram) { + if (useSharedCtx) { + // TODO : Need to test useSharedCtx case. ** Untested case ** + cv.makeCtxCurrent(cv.screen.renderer.sharedCtx); + } + + // Create shader resources if not already done + for(int i=0; i < shaders.length; i++) { + if (shaders[i].compileErrorOccurred) { + errorOccurred = true; + } + else { + err = createShader(cv, cvRdrIndex, shaders[i]); + if (err != null) { + err.setShaderProgram((ShaderProgram)this.source); + err.setShader((Shader)shaders[i].source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + errorOccurred = true; + } + else { + err = compileShader(cv, cvRdrIndex, shaders[i]); + if (err != null) { + err.setShaderProgram((ShaderProgram)this.source); + err.setShader((Shader)shaders[i].source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + destroyShader(cv, cvRdrIndex, shaders[i]); + shaders[i].compileErrorOccurred = true; + errorOccurred = true; + } + } + } + } + + // Create shader program + if (!errorOccurred) { + err = createShaderProgram(cv, cvRdrIndex); + if (err != null) { + err.setShaderProgram((ShaderProgram)this.source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + errorOccurred = true; + } + } + + boolean linked = getShaderProgramData(cvRdrIndex).isLinked(); + if (!linked) { + // Bind vertex attribute names + if (!errorOccurred) { + if (vertexAttrNames != null) { +// System.err.println("vertexAttrNames.length = " + vertexAttrNames.length); + for (int i = 0; i < vertexAttrNames.length; i++) { + err = bindVertexAttrName(cv, cvRdrIndex, vertexAttrNames[i], i); + // Report non-fatal error, if one was detected + if (err != null) { + err.setShaderProgram((ShaderProgram)this.source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + } + } + } + } + + // Link shader program + if (!errorOccurred) { + err = linkShaderProgram(cv, cvRdrIndex, shaders); + if (err != null) { + err.setShaderProgram((ShaderProgram)this.source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + destroyShaderProgram(cv, cvRdrIndex); + linkErrorOccurred = true; + errorOccurred = true; + } + } + + // lookup vertex attribute names + if (!errorOccurred) { + if (vertexAttrNames != null) { + lookupVertexAttrNames(cv, cvRdrIndex, vertexAttrNames); + } + } + + // Lookup shader attribute names + if (!errorOccurred) { + if (shaderAttrNames != null) { +// System.err.println("shaderAttrNames.length = " + shaderAttrNames.length); + lookupShaderAttrNames(cv, cvRdrIndex, shaderAttrNames); + } + } + } + + // Restore current context if we changed it to the shareCtx + if (useSharedCtx) { + cv.makeCtxCurrent(cv.ctx); + } + + // If compilation or link error occured, disable shader program and return + if (errorOccurred) { + disableShaderProgram(cv); + return; + } + } + + // Now we can enable the shader program + enableShaderProgram(cv, cvRdrIndex); + } + + /** + * Update native value for ShaderAttributeValue class + */ + ShaderError setUniformAttrValue(long ctx, long shaderProgramId, long loc, + ShaderAttributeValueRetained sav) { + + switch (sav.getClassType()) { + case ShaderAttributeObjectRetained.TYPE_INTEGER: + return setUniform1i(ctx, shaderProgramId, loc, + ((int[])sav.attrWrapper.getRef())[0]); + + case ShaderAttributeObjectRetained.TYPE_FLOAT: + return setUniform1f(ctx, shaderProgramId, loc, + ((float[])sav.attrWrapper.getRef())[0]); + + case ShaderAttributeObjectRetained.TYPE_TUPLE2I: + return setUniform2i(ctx, shaderProgramId, loc, + (int[])sav.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE2F: + return setUniform2f(ctx, shaderProgramId, loc, + (float[])sav.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE3I: + return setUniform3i(ctx, shaderProgramId, loc, + (int[])sav.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE3F: + return setUniform3f(ctx, shaderProgramId, loc, + (float[])sav.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE4I: + return setUniform4i(ctx, shaderProgramId, loc, + (int[])sav.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE4F: + return setUniform4f(ctx, shaderProgramId, loc, + (float[])sav.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_MATRIX3F: + return setUniformMatrix3f(ctx, shaderProgramId, loc, + (float[])sav.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_MATRIX4F: + return setUniformMatrix4f(ctx, shaderProgramId, loc, + (float[])sav.attrWrapper.getRef()); + + default: + // Should never get here + assert false : "Unrecognized ShaderAttributeValue classType"; + return null; + } + } + + /** + * Update native value for ShaderAttributeArray class + */ + ShaderError setUniformAttrArray(long ctx, long shaderProgramId, long loc, + ShaderAttributeArrayRetained saa) { + + switch (saa.getClassType()) { + case ShaderAttributeObjectRetained.TYPE_INTEGER: + return setUniform1iArray(ctx, shaderProgramId, loc, saa.length(), + ((int[])saa.attrWrapper.getRef())); + + case ShaderAttributeObjectRetained.TYPE_FLOAT: + return setUniform1fArray(ctx, shaderProgramId, loc, saa.length(), + ((float[])saa.attrWrapper.getRef())); + + case ShaderAttributeObjectRetained.TYPE_TUPLE2I: + return setUniform2iArray(ctx, shaderProgramId, loc, saa.length(), + (int[])saa.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE2F: + return setUniform2fArray(ctx, shaderProgramId, loc, saa.length(), + (float[])saa.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE3I: + return setUniform3iArray(ctx, shaderProgramId, loc, saa.length(), + (int[])saa.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE3F: + return setUniform3fArray(ctx, shaderProgramId, loc, saa.length(), + (float[])saa.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE4I: + return setUniform4iArray(ctx, shaderProgramId, loc, saa.length(), + (int[])saa.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_TUPLE4F: + return setUniform4fArray(ctx, shaderProgramId, loc, saa.length(), + (float[])saa.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_MATRIX3F: + return setUniformMatrix3fArray(ctx, shaderProgramId, loc, saa.length(), + (float[])saa.attrWrapper.getRef()); + + case ShaderAttributeObjectRetained.TYPE_MATRIX4F: + return setUniformMatrix4fArray(ctx, shaderProgramId, loc, saa.length(), + (float[])saa.attrWrapper.getRef()); + + default: + // Should never get here + assert false : "Unrecognized ShaderAttributeArray classType"; + return null; + } + + } + + + void setShaderAttributes(Canvas3D cv, ShaderAttributeSetRetained attributeSet) { + final boolean useSharedCtx = cv.useSharedCtx && cv.screen.renderer.sharedCtx != 0; + final int cvRdrIndex = useSharedCtx ? cv.screen.renderer.rendererId : cv.canvasId; + ShaderProgramData spData = getShaderProgramData(cvRdrIndex); + + // Just return if shader program wasn't linked successfully + if (!spData.isLinked()) { + return; + } + + long shaderProgramId = spData.getShaderProgramId(); + + Iterator attrs = attributeSet.getAttrs().values().iterator(); + while (attrs.hasNext()) { + ShaderError err = null; + ShaderAttributeRetained saRetained = (ShaderAttributeRetained)attrs.next(); + + // Lookup attribute info for the specified attrName; null means + // that the name does not appear in the ShaderProgram, so we will + // report an error. + AttrNameInfo attrNameInfo = spData.getAttrNameInfo(saRetained.getAttributeName()); + if(attrNameInfo == null) { +// System.err.println("ShaderProgramRetained : attrLocation (" + saRetained.getAttributeName() + ") is null."); + String errMsg = "Attribute name not set in ShaderProgram: " + saRetained.getAttributeName(); // TODO: I18N + err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_NAME_NOT_SET_ERROR, errMsg); + } else { + long loc = attrNameInfo.getLocation(); + if (loc != -1) { + if (saRetained instanceof ShaderAttributeValueRetained) { + ShaderAttributeValueRetained savRetained = (ShaderAttributeValueRetained)saRetained; + if (attrNameInfo.isArray() || + (savRetained.getClassType() != attrNameInfo.getType())) { + String errMsg = "Attribute type mismatch: " + savRetained.getAttributeName(); // TODO: I18N + err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_TYPE_ERROR, errMsg); + } + else { + err = setUniformAttrValue(cv.ctx, shaderProgramId, loc, savRetained); + } + } else if (saRetained instanceof ShaderAttributeArrayRetained) { + ShaderAttributeArrayRetained saaRetained = (ShaderAttributeArrayRetained)saRetained; + if (!attrNameInfo.isArray() || + (saaRetained.getClassType() != attrNameInfo.getType())) { + String errMsg = "Attribute type mismatch: " + saaRetained.getAttributeName(); // TODO: I18N + err = new ShaderError(ShaderError.SHADER_ATTRIBUTE_TYPE_ERROR, errMsg); + } + else { + err = setUniformAttrArray(cv.ctx, shaderProgramId, loc, saaRetained); + } + } else if (saRetained instanceof ShaderAttributeBindingRetained) { + assert false; + throw new RuntimeException("not implemented"); + } else { + assert false; + } + } + } + + if (err != null) { + // Before reporting the ShaderAttribute error, check + // whether it has already been reported for this ShaderProgram + if (shaderAttrErrorSet == null) { + shaderAttrErrorSet = new HashSet(); + } + if (shaderAttrErrorSet.add(saRetained.source)) { + err.setShaderProgram((ShaderProgram)this.source); + err.setShaderAttributeSet((ShaderAttributeSet)attributeSet.source); + err.setShaderAttribute((ShaderAttribute)saRetained.source); + err.setCanvas3D(cv); + notifyErrorListeners(cv, err); + } + } + } + } + + class ShaderProgramData extends Object { + + // shaderProgramId use by native code. + private long shaderProgramId = 0; + + // linked flag for native. + private boolean linked = false; + + // A map of locations for ShaderAttributes. + private HashMap attrNameInfoMap = new HashMap(); + + /** ShaderProgramData Constructor */ + ShaderProgramData() { + } + + void reset() { + shaderProgramId = 0; + linked = false; + attrNameInfoMap.clear(); + } + + void setShaderProgramId(long shaderProgramId) { + this.shaderProgramId = shaderProgramId; + } + + long getShaderProgramId() { + return this.shaderProgramId; + } + + void setLinked(boolean linked) { + this.linked = linked; + } + + boolean isLinked() { + return linked; + } + + void setAttrNameInfo(String shaderAttribute, AttrNameInfo attrNameInfo) { + assert(shaderAttribute != null); + attrNameInfoMap.put(shaderAttribute, attrNameInfo); + } + + AttrNameInfo getAttrNameInfo(String shaderAttribute) { + return (AttrNameInfo) attrNameInfoMap.get(shaderAttribute); + } + + + } + + // Data associated with an attribute name + class AttrNameInfo { + void setLocation(long loc) { + this.loc = loc; + } + + long getLocation() { + return loc; + } + + void setType(int type) { + this.type = type; + } + + int getType() { + return type; + } + + boolean isArray() { + return isArray; + } + + void setArray(boolean isArray) { + this.isArray = isArray; + } + + // Location of attribute name in linked shader program + private long loc; + + // boolean indicating whether the attribute is an array + private boolean isArray; + + // type of shader attribute + private int type; + } + +} diff --git a/src/classes/share/javax/media/j3d/ShaderRetained.java b/src/classes/share/javax/media/j3d/ShaderRetained.java new file mode 100644 index 0000000..a050b50 --- /dev/null +++ b/src/classes/share/javax/media/j3d/ShaderRetained.java @@ -0,0 +1,78 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +import java.util.*; + +/** + * The ShaderRetained object is the abstract base class for programmable + * shader code. Currently, only text-based source code shaders are + * supported, so the only subclass of Shader is SourceCodeShader. We + * leave open the possibility for binary (object code) shaders in the + * future. + */ +abstract class ShaderRetained extends NodeComponentRetained { + int shadingLanguage; + int shaderType; + + // shaderId use by native code. One per Canvas. + long[] shaderIds; + boolean[] compiled; + + // Flag indicating whether a COMPILE_ERROR has occurred for this shader + // object. It is set in updateNative to indicate that the compileShader + // operation failed. It is cleared in setLive or clearLive. + // TODO KCR: Add code to clear this in setLive or clearLive + boolean compileErrorOccurred = false; + + // need to synchronize access from multiple rendering threads + Object resourceLock = new Object(); + + void initializeShader(int shadingLanguage, int shaderType) { + this.shadingLanguage = shadingLanguage; + this.shaderType = shaderType; + } + + int getShadingLanguage() { + return shadingLanguage; + } + + int getShaderType() { + return shaderType; + } + + void setLive(boolean inBackgroundGroup, int refCount) { + // System.out.println("SourceCodeShaderRetained.setLive()"); + super.setLive(inBackgroundGroup, refCount); + } + + void clearLive(int refCount) { + // System.out.println("SourceCodeShaderRetained.clearLive()"); + super.clearLive(refCount); + } + + /** + * Shader object doesn't really have mirror object. + * But it's using the updateMirrorObject interface to propagate + * the changes to the users + */ + synchronized void updateMirrorObject(int component, Object value) { + System.out.println("Shader.updateMirrorObject not implemented yet!"); + } + + void handleFrequencyChange(int bit) { + System.out.println("Shader.handleFrequencyChange not implemented yet!"); + } + +} + diff --git a/src/classes/share/javax/media/j3d/Shape3D.java b/src/classes/share/javax/media/j3d/Shape3D.java index 6a9f5d7..5c4394c 100644 --- a/src/classes/share/javax/media/j3d/Shape3D.java +++ b/src/classes/share/javax/media/j3d/Shape3D.java @@ -111,6 +111,14 @@ public class Shape3D extends Leaf { public static final int ALLOW_APPEARANCE_OVERRIDE_WRITE = CapabilityBits.SHAPE3D_ALLOW_APPEARANCE_OVERRIDE_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_GEOMETRY_READ, + ALLOW_APPEARANCE_READ, + ALLOW_COLLISION_BOUNDS_READ, + ALLOW_APPEARANCE_OVERRIDE_READ + }; + /** * Constructs a Shape3D node with default parameters. The default * values are as follows: @@ -127,6 +135,8 @@ public class Shape3D extends Leaf { * that default values are used for all appearance attributes. */ public Shape3D() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -141,7 +151,10 @@ public class Shape3D extends Leaf { * this shape node. */ public Shape3D(Geometry geometry) { - ((Shape3DRetained)retained).setGeometry(geometry, 0); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((Shape3DRetained)retained).setGeometry(geometry, 0); } /** @@ -155,7 +168,10 @@ public class Shape3D extends Leaf { * @param appearance the appearance component of the shape node */ public Shape3D(Geometry geometry, Appearance appearance) { - ((Shape3DRetained)retained).setGeometry(geometry, 0); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((Shape3DRetained)retained).setGeometry(geometry, 0); ((Shape3DRetained)retained).setAppearance(appearance); } diff --git a/src/classes/share/javax/media/j3d/Shape3DCompileRetained.java b/src/classes/share/javax/media/j3d/Shape3DCompileRetained.java index e4514d4..a3e604d 100644 --- a/src/classes/share/javax/media/j3d/Shape3DCompileRetained.java +++ b/src/classes/share/javax/media/j3d/Shape3DCompileRetained.java @@ -424,81 +424,139 @@ class Shape3DCompileRetained extends Shape3DRetained { * @exception IllegalArgumentException if <code>path</code> is * invalid. */ - boolean intersect(SceneGraphPath path, - PickShape pickShape, double[] dist) { - - // This method will not do bound intersect check, as it assume - // caller has already done that. ( For performance and code - // simplification reasons. ) - - Transform3D localToVworld = path.getTransform(); - int i; - - if (localToVworld == null) { + PickShape pickShape, double[] dist) { + + int flags; + PickInfo pickInfo = new PickInfo(); + + Transform3D localToVworld = path.getTransform(); + if (localToVworld == null) { throw new IllegalArgumentException(J3dI18N.getString("Shape3DRetained3")); } - - Transform3D t3d = VirtualUniverse.mc.getTransform3D(null); - t3d.invert(localToVworld); - PickShape newPS = pickShape.transform(t3d); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t3d); - - Shape3D shape = (Shape3D) path.getObject(); + pickInfo.setLocalToVWorldRef( localToVworld); + + Shape3D shape = (Shape3D) path.getObject(); // Get the geometries for this shape only, since the compiled // geomtryList contains several shapes - ArrayList glist = (ArrayList) geometryInfo.get(shape.id); - - int geomListSize = glist.size(); - - Point3d iPnt = Shape3DRetained.getPoint3d(); + ArrayList glist = (ArrayList) geometryInfo.get(shape.id); + + // System.out.println("Shape3DCompileRetained.intersect() : "); + if (dist == null) { + // System.out.println(" no dist request ...."); + return intersect(pickInfo, pickShape, 0, glist); + } + + flags = PickInfo.CLOSEST_DISTANCE; + if (intersect(pickInfo, pickShape, flags, glist)) { + dist[0] = pickInfo.getClosestDistance(); + return true; + } + + return false; + + } + + boolean intersect(PickInfo pickInfo, PickShape pickShape, int flags, + ArrayList geometryList) { + + Transform3D localToVworld = pickInfo.getLocalToVWorldRef(); + + Transform3D t3d = new Transform3D(); + t3d.invert(localToVworld); + PickShape newPS = pickShape.transform(t3d); + + int geomListSize = geometryList.size(); GeometryRetained geometry; - if (dist == null) { - for (i=0; i < geomListSize; i++) { - Geometry g = (Geometry) glist.get(i); - if (g != null && g.retained != null) { - geometry = (GeometryRetained)g.retained; + if (((flags & PickInfo.CLOSEST_INTERSECTION_POINT) == 0) && + ((flags & PickInfo.CLOSEST_DISTANCE) == 0) && + ((flags & PickInfo.CLOSEST_GEOM_INFO) == 0) && + ((flags & PickInfo.ALL_GEOM_INFO) == 0)) { + + for (int i=0; i < geomListSize; i++) { + geometry = (GeometryRetained) geometryList.get(i); + if (geometry != null) { if (geometry.mirrorGeometry != null) { geometry = geometry.mirrorGeometry; } - - if (geometry.intersect(newPS, null, iPnt)) { - Shape3DRetained.freePoint3d(iPnt); + // Need to modify this method + // if (geometry.intersect(newPS, null, null)) { + if (geometry.intersect(newPS, null, 0, null)) { return true; } } } - } else { + } + else { + double distance; double minDist = Double.POSITIVE_INFINITY; - // TODO : BugId 4351579 -- Need to return the index of nearest - // intersected geometry too. - - for (i=0; i < geomListSize; i++) { - Geometry g = (Geometry) glist.get(i); - if (g != null && g.retained != null) { - geometry = (GeometryRetained)g.retained; + Point3d closestIPnt = new Point3d(); + Point3d iPnt = new Point3d(); + Point3d iPntVW = new Point3d(); + PickInfo.IntersectionInfo closestInfo = null; + PickInfo.IntersectionInfo intersectionInfo + = pickInfo.createIntersectionInfo(); + + if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { + closestInfo = pickInfo.createIntersectionInfo(); + } + + for (int i=0; i < geomListSize; i++) { + geometry = (GeometryRetained) geometryList.get(i); + if (geometry != null) { if (geometry.mirrorGeometry != null) { geometry = geometry.mirrorGeometry; } - if (geometry.intersect(newPS, dist, iPnt)) { - localToVworld.transform(iPnt); - dist[0] = pickShape.distance(iPnt); - if (minDist > dist[0]) { - minDist = dist[0]; - } + if (geometry.intersect(newPS, intersectionInfo, flags, iPnt)) { + + iPntVW.set(iPnt); + localToVworld.transform(iPntVW); + distance = pickShape.distance(iPntVW); + + if (minDist > distance) { + minDist = distance; + closestIPnt.set(iPnt); + + if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { + closestInfo.setGeometry((Geometry) geometry.source); + closestInfo.setGeometryIndex(i); + closestInfo.setIntersectionPoint(closestIPnt); + closestInfo.setDistance(distance); + closestInfo.setVertexIndices(intersectionInfo.getVertexIndices()); + } + } + + if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { + + intersectionInfo.setGeometry((Geometry) geometry.source); + intersectionInfo.setGeometryIndex(i); + intersectionInfo.setIntersectionPoint(iPnt); + intersectionInfo.setDistance(distance); + // VertexIndices has been computed in intersect method. + pickInfo.insertIntersectionInfo(intersectionInfo); + intersectionInfo = pickInfo.createIntersectionInfo(); + } } } } - - if (minDist < Double.POSITIVE_INFINITY) { - dist[0] = minDist; - Shape3DRetained.freePoint3d(iPnt); + + if (minDist < Double.POSITIVE_INFINITY) { + if ((flags & PickInfo.CLOSEST_DISTANCE) != 0) { + pickInfo.setClosestDistance(minDist); + } + if((flags & PickInfo.CLOSEST_INTERSECTION_POINT) != 0) { + pickInfo.setClosestIntersectionPoint(closestIPnt); + } + if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { + pickInfo.insertIntersectionInfo(closestInfo); + } return true; } } - - Shape3DRetained.freePoint3d(iPnt); + return false; - } + + } + } diff --git a/src/classes/share/javax/media/j3d/Shape3DRetained.java b/src/classes/share/javax/media/j3d/Shape3DRetained.java index 8e097bd..8d3002c 100644 --- a/src/classes/share/javax/media/j3d/Shape3DRetained.java +++ b/src/classes/share/javax/media/j3d/Shape3DRetained.java @@ -580,97 +580,6 @@ class Shape3DRetained extends LeafRetained { return (appearance == null ? null: (Appearance) appearance.source); } - - /** - * Check if the geometry component of this shape node under path - * intersects with the pickShape. - * This is an expensive method. It should only be called if and only - * if the path's bound intersects pickShape. - * @exception IllegalArgumentException if <code>path</code> is - * invalid. - */ - - boolean intersect(SceneGraphPath path, - PickShape pickShape, double[] dist) { - - // This method will not do bound intersect check, as it assume - // caller has already done that. ( For performance and code - // simplification reasons. ) - - Transform3D localToVworld = path.getTransform(); - int i; - - if (localToVworld == null) { - throw new IllegalArgumentException(J3dI18N.getString("Shape3DRetained3")); - } - - // Support OrientedShape3D here. - // TODO - BugId : 4363899 - APIs issue : OrientedShape3D's intersect needs view - // info. temp. fix use the primary view. - if (this instanceof OrientedShape3DRetained) { - Transform3D orientedTransform = ((OrientedShape3DRetained)this). - getOrientedTransform(getPrimaryViewIdx()); - localToVworld.mul(orientedTransform); - } - - Transform3D t3d = VirtualUniverse.mc.getTransform3D(null); - t3d.invert(localToVworld); - PickShape newPS = pickShape.transform(t3d); - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, t3d); - - // TODO: For optimization - Should do a geobounds check of - // each geometry first. But this doesn't work for - // OrientedShape3D case... - int geomListSize = geometryList.size(); - Point3d iPnt = getPoint3d(); - GeometryRetained geometry; - - if (dist == null) { - for (i=0; i < geomListSize; i++) { - geometry = (GeometryRetained) geometryList.get(i); - if (geometry != null) { - if (geometry.mirrorGeometry != null) { - geometry = geometry.mirrorGeometry; - } - if (geometry.intersect(newPS, null, iPnt)) { - freePoint3d(iPnt); - return true; - } - } - } - } else { - double minDist = Double.POSITIVE_INFINITY; - // TODO : BugId 4351579 -- Need to return the index of nearest - // intersected geometry too. - - for (i=0; i < geomListSize; i++) { - geometry = (GeometryRetained) geometryList.get(i); - if (geometry != null) { - if (geometry.mirrorGeometry != null) { - geometry = geometry.mirrorGeometry; - } - if (geometry.intersect(newPS, dist, iPnt)) { - localToVworld.transform(iPnt); - dist[0] = pickShape.distance(iPnt); - if (minDist > dist[0]) { - minDist = dist[0]; - } - } - } - } - - if (minDist < Double.POSITIVE_INFINITY) { - dist[0] = minDist; - freePoint3d(iPnt); - return true; - } - } - - freePoint3d(iPnt); - - return false; - } - void setAppearanceOverrideEnable(boolean flag) { if (((Shape3D)this.source).isLive()) { @@ -703,7 +612,153 @@ class Shape3DRetained extends LeafRetained { boolean getAppearanceOverrideEnable() { return appearanceOverrideEnable; } + + boolean intersect(PickInfo pickInfo, PickShape pickShape, int flags ) { + + Transform3D localToVworld = pickInfo.getLocalToVWorldRef(); + + // Support OrientedShape3D here. + // Note - BugId : 4363899 - APIs issue : OrientedShape3D's intersect needs view + // info. temp. fix use the primary view. + if (this instanceof OrientedShape3DRetained) { + Transform3D orientedTransform = ((OrientedShape3DRetained)this). + getOrientedTransform(getPrimaryViewIdx()); + localToVworld.mul(orientedTransform); + } + + Transform3D t3d = new Transform3D(); + t3d.invert(localToVworld); + PickShape newPS = pickShape.transform(t3d); + // Note: For optimization - Should do a geobounds check of + // each geometry first. But this doesn't work for + // OrientedShape3D case... + int geomListSize = geometryList.size(); + GeometryRetained geometry; + + if (((flags & PickInfo.CLOSEST_INTERSECTION_POINT) == 0) && + ((flags & PickInfo.CLOSEST_DISTANCE) == 0) && + ((flags & PickInfo.CLOSEST_GEOM_INFO) == 0) && + ((flags & PickInfo.ALL_GEOM_INFO) == 0)) { + + for (int i=0; i < geomListSize; i++) { + geometry = (GeometryRetained) geometryList.get(i); + if (geometry != null) { + if (geometry.mirrorGeometry != null) { + geometry = geometry.mirrorGeometry; + } + if (geometry.intersect(newPS, null, 0, null)) { + return true; + } + } + } + } else { + double distance; + double minDist = Double.POSITIVE_INFINITY; + Point3d closestIPnt = new Point3d(); + Point3d iPnt = new Point3d(); + Point3d iPntVW = new Point3d(); + PickInfo.IntersectionInfo closestInfo = null; + PickInfo.IntersectionInfo intersectionInfo + = pickInfo.createIntersectionInfo(); + + if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { + closestInfo = pickInfo.createIntersectionInfo(); + } + + for (int i=0; i < geomListSize; i++) { + geometry = (GeometryRetained) geometryList.get(i); + if (geometry != null) { + if (geometry.mirrorGeometry != null) { + geometry = geometry.mirrorGeometry; + } + if (geometry.intersect(newPS, intersectionInfo, flags, iPnt)) { + + iPntVW.set(iPnt); + localToVworld.transform(iPntVW); + distance = pickShape.distance(iPntVW); + + if (minDist > distance) { + minDist = distance; + closestIPnt.set(iPnt); + + if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { + closestInfo.setGeometry((Geometry) geometry.source); + closestInfo.setGeometryIndex(i); + closestInfo.setIntersectionPoint(closestIPnt); + closestInfo.setDistance(distance); + closestInfo.setVertexIndices(intersectionInfo.getVertexIndices()); + } + } + + if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { + + intersectionInfo.setGeometry((Geometry) geometry.source); + intersectionInfo.setGeometryIndex(i); + intersectionInfo.setIntersectionPoint(iPnt); + intersectionInfo.setDistance(distance); + // VertexIndices has been computed in intersect method. + pickInfo.insertIntersectionInfo(intersectionInfo); + intersectionInfo = pickInfo.createIntersectionInfo(); + } + } + } + } + + if (minDist < Double.POSITIVE_INFINITY) { + if ((flags & PickInfo.CLOSEST_DISTANCE) != 0) { + pickInfo.setClosestDistance(minDist); + } + if((flags & PickInfo.CLOSEST_INTERSECTION_POINT) != 0) { + pickInfo.setClosestIntersectionPoint(closestIPnt); + } + if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { + pickInfo.insertIntersectionInfo(closestInfo); + } + return true; + } + } + + return false; + + } + + + /** + * Check if the geometry component of this shape node under path + * intersects with the pickShape. + * This is an expensive method. It should only be called if and only + * if the path's bound intersects pickShape. + * @exception IllegalArgumentException if <code>path</code> is + * invalid. + */ + + boolean intersect(SceneGraphPath path, + PickShape pickShape, double[] dist) { + + int flags; + PickInfo pickInfo = new PickInfo(); + + Transform3D localToVworld = path.getTransform(); + if (localToVworld == null) { + throw new IllegalArgumentException(J3dI18N.getString("Shape3DRetained3")); + } + pickInfo.setLocalToVWorldRef( localToVworld); + //System.out.println("Shape3DRetained.intersect() : "); + if (dist == null) { + //System.out.println(" no dist request ...."); + return intersect(pickInfo, pickShape, 0); + } + + flags = PickInfo.CLOSEST_DISTANCE; + if (intersect(pickInfo, pickShape, flags)) { + dist[0] = pickInfo.getClosestDistance(); + return true; + } + + return false; + + } /** * This sets the immedate mode context flag diff --git a/src/classes/share/javax/media/j3d/SharedGroup.java b/src/classes/share/javax/media/j3d/SharedGroup.java index 3f7ce8d..446c3f2 100644 --- a/src/classes/share/javax/media/j3d/SharedGroup.java +++ b/src/classes/share/javax/media/j3d/SharedGroup.java @@ -67,11 +67,17 @@ public class SharedGroup extends Group { public static final int ALLOW_LINK_READ = CapabilityBits.SHARED_GROUP_ALLOW_LINK_READ; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_LINK_READ + }; /** * Constructs and initializes a new SharedGroup node object. */ public SharedGroup() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } @@ -82,10 +88,12 @@ public class SharedGroup extends Group { * @since Java 3D 1.3 */ public Link[] getLinks() { - if (isLiveOrCompiled()) - if (!this.getCapability(ALLOW_LINK_READ)) + if (isLiveOrCompiled()) { + if (!this.getCapability(ALLOW_LINK_READ)) { throw new CapabilityNotSetException(J3dI18N.getString("SharedGroup1")); - return ((SharedGroupRetained)retained).getLinks(); + } + } + return ((SharedGroupRetained)retained).getLinks(); } diff --git a/src/classes/share/javax/media/j3d/SharedGroupRetained.java b/src/classes/share/javax/media/j3d/SharedGroupRetained.java index ed69d9f..694671f 100644 --- a/src/classes/share/javax/media/j3d/SharedGroupRetained.java +++ b/src/classes/share/javax/media/j3d/SharedGroupRetained.java @@ -329,7 +329,7 @@ class SharedGroupRetained extends GroupRetained implements TargetsInterface { s.transformTargets = savedTransformTargets; s.hashkeyIndex = savedHashkeyIndex; /* -// TODO : port this +// XXXX : port this for (int i=0; i < children.size(); i++) { if ((childContains[i][0] & ILLEGAL_LEAF_MASK) != 0) { throw new IllegalSharingException(J3dI18N.getString("SharedGroupRetained0")); } @@ -472,7 +472,7 @@ class SharedGroupRetained extends GroupRetained implements TargetsInterface { s.switchTargets = null; - // TODO: This is a hack since removeNodeData is called before + // XXXX: This is a hack since removeNodeData is called before // children are clearLives int[] tempIndex = null; // Don't keep the indices if everything will be cleared @@ -778,7 +778,7 @@ class SharedGroupRetained extends GroupRetained implements TargetsInterface { public void propagateTargetThreads(int type, int childTargetThreads) { if (type == TargetsInterface.TRANSFORM_TARGETS) { LinkRetained ln; - // TODO : For now we'll OR more than exact. + // XXXX : For now we'll OR more than exact. //targetThreads = localTargetThreads | childTargetThreads; targetThreads = targetThreads | childTargetThreads; for(int i=0; i<parents.size(); i++) { diff --git a/src/classes/share/javax/media/j3d/Sound.java b/src/classes/share/javax/media/j3d/Sound.java index a11d8a9..ac70b9b 100644 --- a/src/classes/share/javax/media/j3d/Sound.java +++ b/src/classes/share/javax/media/j3d/Sound.java @@ -440,7 +440,26 @@ public abstract class Sound extends Leaf { */ public static final int INFINITE_LOOPS = -1; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_CHANNELS_USED_READ, + ALLOW_CONT_PLAY_READ, + ALLOW_DURATION_READ, + ALLOW_ENABLE_READ, + ALLOW_INITIAL_GAIN_READ, + ALLOW_IS_PLAYING_READ, + ALLOW_IS_READY_READ, + ALLOW_LOOP_READ, + ALLOW_MUTE_READ, + ALLOW_PAUSE_READ, + ALLOW_PRIORITY_READ, + ALLOW_RATE_SCALE_FACTOR_READ, + ALLOW_RELEASE_READ, + ALLOW_SCHEDULING_BOUNDS_READ, + ALLOW_SOUND_DATA_READ + }; + + /** * Constructs and initializes a new Sound node using default * parameters. The following defaults values are used: @@ -460,6 +479,8 @@ public abstract class Sound extends Leaf { * </ul> */ public Sound() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -471,6 +492,9 @@ public abstract class Sound extends Leaf { * @param initialGain overall amplitude scale factor applied to sound source */ public Sound(MediaContainer soundData, float initialGain) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((SoundRetained)this.retained).setSoundData(soundData); ((SoundRetained)this.retained).setInitialGain(initialGain); } @@ -498,6 +522,9 @@ public abstract class Sound extends Leaf { boolean enable, Bounds region, float priority ) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((SoundRetained)this.retained).setSoundData(soundData); ((SoundRetained)this.retained).setInitialGain(initialGain); ((SoundRetained)this.retained).setLoop(loopCount); @@ -533,6 +560,9 @@ public abstract class Sound extends Leaf { Bounds region, float priority, float rateFactor ) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((SoundRetained)this.retained).setSoundData(soundData); ((SoundRetained)this.retained).setInitialGain(initialGain); ((SoundRetained)this.retained).setLoop(loopCount); diff --git a/src/classes/share/javax/media/j3d/SoundRetained.java b/src/classes/share/javax/media/j3d/SoundRetained.java index 5d6e744..f0b2145 100644 --- a/src/classes/share/javax/media/j3d/SoundRetained.java +++ b/src/classes/share/javax/media/j3d/SoundRetained.java @@ -448,7 +448,7 @@ abstract class SoundRetained extends LeafRetained if (debugFlag) debugPrint("setSchedulingBounds for a NULL region"); } - // TODO: test that this works - could not new Bounds() since + // XXXX: test that this works - could not new Bounds() since // Bounds is an abstract class and can't be instantiated dispatchAttribChange(BOUNDS_DIRTY_BIT, region); if (source != null && source.isLive()) { @@ -501,7 +501,7 @@ abstract class SoundRetained extends LeafRetained } else { boundingLeaf = null; } - // TODO: since BoundingLeaf constructor only takes Bounds + // XXXX: since BoundingLeaf constructor only takes Bounds // test if region passed into dispatchAttribChange correctly. dispatchAttribChange(BOUNDING_LEAF_DIRTY_BIT, region); if (source != null && source.isLive()) { @@ -628,7 +628,7 @@ abstract class SoundRetained extends LeafRetained } loadedAtoms[atomCount-1] = atom; // store reference to new atom // all atoms sample durations SHOULD be the same so store it in node - this.duration = atom.sampleLength; // TODO: refine later? in ms + this.duration = atom.sampleLength; // XXXX: refine later? in ms } else { // atom is NOT loaded or has been unloaded; remove from list if (atomCount == 0) @@ -1004,7 +1004,7 @@ abstract class SoundRetained extends LeafRetained ms.inImmCtx = inImmCtx; ms.setSoundData(getSoundData()); -// TODO: copy ms.atoms array from this.atoms +// XXXX: copy ms.atoms array from this.atoms ms.parent = parent; ms.inSharedGroup = false; @@ -1136,7 +1136,7 @@ abstract class SoundRetained extends LeafRetained super.clearLive(s); -// TODO: if (inSharedGroup) +// XXXX: if (inSharedGroup) if (s.inSharedGroup) { for (int i=0; i<s.keys.length; i++) { @@ -1195,7 +1195,7 @@ abstract class SoundRetained extends LeafRetained /* // This makes passed in sound look just like this sound // QUESTION: DOesn't appread to be called -// TODO: ...if so, remove... +// XXXX: ...if so, remove... synchronized void update(SoundRetained sound) { if (debugFlag) debugPrint("Sound.update ******** entered ***** this = " + this + @@ -1219,13 +1219,13 @@ abstract class SoundRetained extends LeafRetained // QUESTION: With code below, no sound schedulingRegion found // sound.schedulingRegion = schedulingRegion; // sound.boundingLeaf = boundingLeaf; -// TODO: clone of region used in Traverse code, why not here??? +// XXXX: clone of region used in Traverse code, why not here??? // if (schedulingRegion != null) // sound.schedulingRegion = (Bounds)schedulingRegion.clone(); -// TODO: BoundingLeafRetained boundingLeaf ... +// XXXX: BoundingLeafRetained boundingLeaf ... // WHAT ABOUT transformedRegion?? -// TODO: Update ALL fields +// XXXX: Update ALL fields // ALL THE BELOW USED TO COMMENTED OUT vvvvvvvvvvvvvvvvvvvvvvvvvvvvv sound.sampleLength = sampleLength; sound.loopStartOffset = loopStartOffset; diff --git a/src/classes/share/javax/media/j3d/SoundScheduler.java b/src/classes/share/javax/media/j3d/SoundScheduler.java index 778c366..15981b6 100644 --- a/src/classes/share/javax/media/j3d/SoundScheduler.java +++ b/src/classes/share/javax/media/j3d/SoundScheduler.java @@ -102,7 +102,7 @@ class SoundScheduler extends J3dStructure { * This prioritized sound list is NO longer re-create instead sounds * are insert, shuffled or removed as messages are processed. */ - // TODO: (Enhancement) should have a seperate list for + // XXXX: (Enhancement) should have a seperate list for // background sound and a list for positional sounds ArrayList prioritizedSounds = new ArrayList(); @@ -322,7 +322,7 @@ class SoundScheduler extends J3dStructure { auralAttribsChanged = true; } else if (node instanceof ViewPlatformRetained) { - // TODO: don't support multiple viewPlatforms per scheduler + // XXXX: don't support multiple viewPlatforms per scheduler /* // useful for resetting VP ?? addViewPlatform((ViewPlatformRetained) node); @@ -753,7 +753,7 @@ class SoundScheduler extends J3dStructure { debugPrint(".deactivate()"); // - // TODO: The following code is clearly erroneous. + // XXXX: The following code is clearly erroneous. // The indendation, along with the 2nd test of // "if (debugFlag)" in the else clause, suggests that // the intent was to make the else clause apply to @@ -858,7 +858,7 @@ class SoundScheduler extends J3dStructure { return; } - // TODO: Does not support multiple canvases per view, thus + // XXXX: Does not support multiple canvases per view, thus // multiple GraphicsContext3Ds // QUESTION: what does that mean for sound - // being applied to only ONE graphics context? @@ -929,7 +929,7 @@ class SoundScheduler extends J3dStructure { int numActiveSounds = 0; if (debugFlag) debugPrint(" renderChanges begun"); - // TODO: BUG?? should wait if audioDevice is NULL or nSounds = 0 + // XXXX: BUG?? should wait if audioDevice is NULL or nSounds = 0 // when a new sound is added or deleted from list, or // when the audioDevice is set into PhysicalEnvironment @@ -955,7 +955,7 @@ class SoundScheduler extends J3dStructure { if (debugFlag) debugPrint(" "+ nIntersected + " active SoundScapes found"); - // TODO: (Performance) calling clone everytime, even + // XXXX: (Performance) calling clone everytime, even // though closest AA has NOT changed, is expensive aaRetained = (AuralAttributesRetained) (findClosestAAttribs(nIntersected)).clone(); @@ -1007,7 +1007,7 @@ class SoundScheduler extends J3dStructure { if (!prioritizedSounds.isEmpty()) { prioritizedSounds.clear(); } - // TODO: sync soundStructure sound list + // XXXX: sync soundStructure sound list UnorderList retainedSounds = universe.soundStructure.getSoundList(view); // QUESTION: what is in this sound list?? // mirror node or actual node??? @@ -1020,7 +1020,7 @@ class SoundScheduler extends J3dStructure { addPrioritizedSound((SoundRetained)retainedSounds.get(i)); nRetainedSounds++; } - // TODO: sync canvases + // XXXX: sync canvases Enumeration canvases = view.getAllCanvas3Ds(); while (canvases.hasMoreElements()) { Canvas3D canvas = (Canvas3D)canvases.nextElement(); @@ -1300,7 +1300,7 @@ class SoundScheduler extends J3dStructure { if (attribs != null) { synchronized (attribs) { /* - // TODO: remove use of aaDirty from AuralAttrib node + // XXXX: remove use of aaDirty from AuralAttrib node if ((attribs != lastAA) || attribs.aaDirty) */ if (debugFlag) { @@ -1476,7 +1476,7 @@ class SoundScheduler extends J3dStructure { // Sounds that have finished playing are not put into list if ((soundAtom.status == SoundSchedulerAtom.SOUND_COMPLETE) && (soundAtom.enabled != SoundSchedulerAtom.PENDING_ON )) { - // TODO:/QUESTION test for immediate mode (?) + // XXXX:/QUESTION test for immediate mode (?) // Unless the sound has been re-started, there's no need // to process sound the finished playing the last time thru @@ -2050,7 +2050,7 @@ class SoundScheduler extends J3dStructure { synchronized (prioritizedSounds) { nAtoms = prioritizedSounds.size(); for (int i=0; i<nAtoms; i++) { - // TODO: (Enhancement) Get all sound node fields here + // XXXX: (Enhancement) Get all sound node fields here // and store locally for performance soundAtom = (SoundSchedulerAtom)prioritizedSounds.get(i); mirSound = soundAtom.sound; @@ -2070,7 +2070,7 @@ class SoundScheduler extends J3dStructure { // check to see if aural attributes changed and have to be updated // must be done before list of sound processed so that Aural Attributes // that affect Sound fields can be set in AudioDevice - // TODO: this is not effient if auralAttribs always the same + // XXXX: this is not effient if auralAttribs always the same if (sound.getInImmCtx()) { if (graphicsCtx !=null && graphicsCtx.auralAttributes !=null) { aaImmed = (AuralAttributesRetained) @@ -2154,7 +2154,7 @@ class SoundScheduler extends J3dStructure { case SoundSchedulerAtom.MAKE_SILENT: // change status to silent AFTER calling render so // that a currently audible sound will be muted. - // TODO: why set status AFTER?? + // XXXX: why set status AFTER?? render(false, soundAtom, attribs); soundAtom.status = SoundSchedulerAtom.SOUND_SILENT; numActiveSounds++; @@ -2373,7 +2373,7 @@ class SoundScheduler extends J3dStructure { if (debugFlag) debugPrint("silenceAll " + nAtoms + " Sounds"); for (int i=0; i<nAtoms; i++) { - // TODO: (Enhancement) Get all sound node fields here + // XXXX: (Enhancement) Get all sound node fields here // and store locally for performance soundAtom = (SoundSchedulerAtom)prioritizedSounds.get(i); mirSound = soundAtom.sound; @@ -2430,7 +2430,7 @@ class SoundScheduler extends J3dStructure { if (debugFlag) debugPrint(":pauseAll " + nAtoms + " Sounds"); for (int i=0; i<nAtoms; i++) { - // TODO: (Enhancement) Get all sound node fields here + // XXXX: (Enhancement) Get all sound node fields here // and store locally for performance SoundSchedulerAtom soundAtom = (SoundSchedulerAtom)prioritizedSounds.get(i); @@ -2475,7 +2475,7 @@ class SoundScheduler extends J3dStructure { debugPrint(": resumeAll " + nAtoms + " Sounds "); for (int i=0; i<nAtoms; i++) { - // TODO: (Enhancement) Get all sound node fields here + // XXXX: (Enhancement) Get all sound node fields here // and store locally for performance SoundSchedulerAtom soundAtom = (SoundSchedulerAtom)prioritizedSounds.get(i); @@ -2528,7 +2528,7 @@ class SoundScheduler extends J3dStructure { debugPrint(": stopAll " + nAtoms + " Sounds "); for (int i=0; i<nAtoms; i++) { - // TODO: (Enhancement) Get all sound node fields here + // XXXX: (Enhancement) Get all sound node fields here // and store locally for performance SoundSchedulerAtom soundAtom = (SoundSchedulerAtom)prioritizedSounds.get(i); @@ -2547,7 +2547,7 @@ class SoundScheduler extends J3dStructure { debugPrint(".stopAllSounds exited"); } - // TODO: Mute All Sounds, complementary to Stop All Sounds + // XXXX: Mute All Sounds, complementary to Stop All Sounds // "should return from run loop - but simply WAIT until sounds // are unmuted. " ??? @@ -2618,7 +2618,7 @@ class SoundScheduler extends J3dStructure { // Set Transform /* - // TODO: per sound tranforms can now be passed to AudioDevice + // XXXX: per sound tranforms can now be passed to AudioDevice // modify and execute the code below // MoveAppBoundingLeaf > ~/Current/MoveAppBoundingLeaf.outted, @@ -2652,7 +2652,7 @@ class SoundScheduler extends J3dStructure { } audioDevice3D.setVworldXfrm(index, xform); soundAtom.clearStateDirtyFlag( SoundRetained.XFORM_DIRTY_BIT); - // TODO: make sure position and direction are already transformed and stored + // XXXX: make sure position and direction are already transformed and stored // into xformXxxxxxx fields. } // ^^^^^^^^^^^^^^^^^^^^^ @@ -2679,7 +2679,7 @@ class SoundScheduler extends J3dStructure { ConeSoundRetained cn = (ConeSoundRetained)mirrorPtSound; ConeSoundRetained cnSound = (ConeSoundRetained)mirrorPtSound.sgSound; if (updateAll || - // TODO: test for XFORM_DIRTY only in for 1.2 + // XXXX: test for XFORM_DIRTY only in for 1.2 soundAtom.testDirtyFlag(soundAtom.attribsDirty, (SoundRetained.DIRECTION_DIRTY_BIT | SoundRetained.XFORM_DIRTY_BIT) ) ) { @@ -2992,7 +2992,7 @@ class SoundScheduler extends J3dStructure { soundAtom.sampleLength = duration; soundAtom.loopLength = soundAtom.sampleLength; - // TODO: for most this will be 0 but not all + // XXXX: for most this will be 0 but not all soundAtom.loopStartOffset = 0; soundAtom.attackLength = 0; // portion of sample before loop section soundAtom.releaseLength = 0; // portion of sample after loop section @@ -3027,7 +3027,7 @@ class SoundScheduler extends J3dStructure { atomFound++; // orginal app node pass into method // QUESTION: is mirror node still correct? - // TODO: ensure only mirror nodes passed into method + // XXXX: ensure only mirror nodes passed into method if (atomFound == nthInstance) { returnAtom = soundAtom; break; diff --git a/src/classes/share/javax/media/j3d/SoundSchedulerAtom.java b/src/classes/share/javax/media/j3d/SoundSchedulerAtom.java index 1ebf628..a4dcccc 100644 --- a/src/classes/share/javax/media/j3d/SoundSchedulerAtom.java +++ b/src/classes/share/javax/media/j3d/SoundSchedulerAtom.java @@ -241,7 +241,7 @@ class SoundSchedulerAtom extends Object { } -// TODO: remove this +// XXXX: remove this // just set the state after debug no longer needed void setEnableState(int state) { enabled = state; @@ -269,7 +269,7 @@ class SoundSchedulerAtom extends Object { } } -// TODO: remove this +// XXXX: remove this // just set the state after debug no longer needed void setMuteState(int state) { muted = state; @@ -297,7 +297,7 @@ class SoundSchedulerAtom extends Object { } } -// TODO: remove this +// XXXX: remove this // just set the state after debug no longer needed void setPauseState(int state) { paused = state; @@ -603,8 +603,8 @@ class SoundSchedulerAtom extends Object { return (action); } // end of calcInactiveSchedAction -// TODO isPLaying -// TODO setLoadingState +// XXXX: isPLaying +// XXXX: setLoadingState // Debug print mechanism for Sound nodes static final boolean debugFlag = false; diff --git a/src/classes/share/javax/media/j3d/SoundStructure.java b/src/classes/share/javax/media/j3d/SoundStructure.java index 90fdba5..e2407b6 100644 --- a/src/classes/share/javax/media/j3d/SoundStructure.java +++ b/src/classes/share/javax/media/j3d/SoundStructure.java @@ -99,7 +99,7 @@ class SoundStructure extends J3dStructure { break; case J3dMessage.SOUNDSCAPE_CHANGED: case J3dMessage.AURALATTRIBUTES_CHANGED: - // TODO: this needs to be changed + // XXXX: this needs to be changed changeNodeAttrib(m); break; case J3dMessage.TRANSFORM_CHANGED: @@ -115,7 +115,7 @@ class SoundStructure extends J3dStructure { case J3dMessage.VIEWSPECIFICGROUP_CHANGED: updateViewSpecificGroupChanged(m); break; - // TODO: case J3dMessage.BOUNDINGLEAF_CHANGED + // XXXX: case J3dMessage.BOUNDINGLEAF_CHANGED } /* @@ -187,7 +187,7 @@ class SoundStructure extends J3dStructure { } } /* - // TODO: + // XXXX: if (node instanceof AuralAttributesRetained) { } else if (node instanceof ViewPlatformRetained) { @@ -326,7 +326,7 @@ class SoundStructure extends J3dStructure { if (debugFlag) debugPrint(" Sound node dirty bit = " + attribDirty); if ((attribDirty & SoundRetained.PRIORITY_DIRTY_BIT) > 0) { - // TODO: shuffle in SoundScheduler + // XXXX: shuffle in SoundScheduler /* shuffleSound((SoundRetained) node); */ @@ -346,7 +346,7 @@ class SoundStructure extends J3dStructure { /* } */ -// TODO: have no dirty flag for soundscape, just auralAttributes... +// XXXX: have no dirty flag for soundscape, just auralAttributes... // what if reference to AA changes in soundscape??? } @@ -400,7 +400,7 @@ class SoundStructure extends J3dStructure { View[] views = vpLists[i].getViewList(); for (int j=(views.length-1); j>=0; j--) { View v = (View)(views[j]); -// TODO: Shouldn't this be done with messages?? +// XXXX: Shouldn't this be done with messages?? v.soundScheduler.loadSound(sound, forceLoad); } } @@ -501,7 +501,7 @@ class SoundStructure extends J3dStructure { /* -// TODO: how is immediate mode handled? below code taken from SoundSchedule +// XXXX: how is immediate mode handled? below code taken from SoundSchedule // Don't know how we'll process immediate mode sounds; // Append immediate mode sounds to live sounds list if (graphicsCtx != null) { diff --git a/src/classes/share/javax/media/j3d/Soundscape.java b/src/classes/share/javax/media/j3d/Soundscape.java index b995bc9..2e61e42 100644 --- a/src/classes/share/javax/media/j3d/Soundscape.java +++ b/src/classes/share/javax/media/j3d/Soundscape.java @@ -72,7 +72,12 @@ public class Soundscape extends Leaf { public static final int ALLOW_ATTRIBUTES_WRITE = CapabilityBits.SOUNDSCAPE_ALLOW_ATTRIBUTES_WRITE; - /** + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_APPLICATION_BOUNDS_READ, + ALLOW_ATTRIBUTES_READ + }; + /** * Constructs and initializes a new Sound node using following * defaults: *<UL> application region: null (no active region)</UL> @@ -80,6 +85,8 @@ public class Soundscape extends Leaf { */ public Soundscape() { // Just use default values + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -90,6 +97,9 @@ public class Soundscape extends Leaf { */ public Soundscape(Bounds region, AuralAttributes attributes) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((SoundscapeRetained)this.retained).setApplicationBounds(region); ((SoundscapeRetained)this.retained).setAuralAttributes(attributes); } diff --git a/src/classes/share/javax/media/j3d/SourceCodeShader.java b/src/classes/share/javax/media/j3d/SourceCodeShader.java new file mode 100644 index 0000000..b940255 --- /dev/null +++ b/src/classes/share/javax/media/j3d/SourceCodeShader.java @@ -0,0 +1,121 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The SourceCodeShader object is a shader that is defined using + * text-based source code. It is used to define the source code for + * both vertex and fragment shaders. The currently supported shading + * languages are Cg and GLSL. + * + * @see ShaderProgram + * + * @since Java 3D 1.4 + */ + +public class SourceCodeShader extends Shader { + + /** + * Not a public constructor, for internal use + */ + SourceCodeShader() { + } + + /** + * Constructs a new shader object of the specified shading + * language and shader type from the specified source string. + * + * @param shadingLanguage the specified shading language, one of: + * <code>SHADING_LANGUAGE_GLSL</code> or + * <code>SHADING_LANGUAGE_CG</code>. + * + * @param shaderType the shader type, one of: + * <code>SHADER_TYPE_VERTEX</code> or + * <code>SHADER_TYPE_FRAGMENT</code>. + * + * @param shaderSource the shader source code + * + * @exception NullPointerException if shaderSource is null. + */ + + public SourceCodeShader(int shadingLanguage, int shaderType, String shaderSource) { + super(shadingLanguage, shaderType); + if (shaderSource == null) { + throw new NullPointerException(); + } + ((SourceCodeShaderRetained)this.retained).initShaderSource(shaderSource); + } + + /** + * Retrieves the shader source string from this shader object. + * + * @return the shader source string. + */ + public String getShaderSource() { + return ((SourceCodeShaderRetained)this.retained).getShaderSource(); + } + + + /** + * Creates a retained mode SourceCodeShaderRetained object that this + * SourceCodeShader component object will point to. + */ + void createRetained() { + this.retained = new SourceCodeShaderRetained(); + this.retained.setSource(this); + // System.out.println("SourceCodeShader.createRetained()"); + } + + /** + * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) + */ + public NodeComponent cloneNodeComponent() { + SourceCodeShaderRetained scsRetained = (SourceCodeShaderRetained) retained; + + SourceCodeShader scs = new SourceCodeShader(scsRetained.getShadingLanguage(), + scsRetained.getShaderType(), + scsRetained.getShaderSource()); + scs.duplicateNodeComponent(this); + return scs; + } + + + /** + * Copies all node information from <code>originalNodeComponent</code> + * into the current node. This method is called from the + * <code>duplicateNode</code> method. This routine does + * the actual duplication of all "local data" (any data defined in + * this object). + * + * @param originalNodeComponent the original node to duplicate + * @param forceDuplicate when set to <code>true</code>, causes the + * <code>duplicateOnCloneTree</code> flag to be ignored. When + * <code>false</code>, the value of each node's + * <code>duplicateOnCloneTree</code> variable determines whether + * NodeComponent data is duplicated or copied. + * + * @see Node#cloneTree + * @see NodeComponent#setDuplicateOnCloneTree + */ + void duplicateAttributes(NodeComponent originalNodeComponent, + boolean forceDuplicate) { + super.duplicateAttributes(originalNodeComponent, forceDuplicate); + + String sc = ((SourceCodeShaderRetained) originalNodeComponent.retained).getShaderSource(); + + if (sc != null) { + ((SourceCodeShaderRetained) retained).setShaderSource(sc); + } + } + +} diff --git a/src/classes/share/javax/media/j3d/SourceCodeShaderRetained.java b/src/classes/share/javax/media/j3d/SourceCodeShaderRetained.java new file mode 100644 index 0000000..d415ae8 --- /dev/null +++ b/src/classes/share/javax/media/j3d/SourceCodeShaderRetained.java @@ -0,0 +1,85 @@ +/* + * $RCSfile$ + * + * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. + * + * Use is subject to license terms. + * + * $Revision$ + * $Date$ + * $State$ + */ + +package javax.media.j3d; + +/** + * The SourceCodeShaderRetained object is a shader that is defined using + * text-based source code. It is used to define the source code for + * both vertex and fragment shaders. The currently supported shading + * languages are Cg and GLSL. + */ + +class SourceCodeShaderRetained extends ShaderRetained { + + private String shaderSource = null; + + /** + * Constructs a new shader retained object of the specified shading + * language and shader type from the specified source string. + */ + + SourceCodeShaderRetained() { + } + + // This method is similar to setShaderSource(). + // To conform to j3d frame in retained creation, we will stick with method + // with init name. + final void initShaderSource(String shaderSource) { + this.shaderSource = shaderSource; + } + + final void set(int shadingLanguage, int shaderType, String shaderSource) { + this.shadingLanguage = shadingLanguage; + this.shaderType = shaderType; + this.shaderSource = shaderSource; + } + + /** + * Retrieves the shader source string from this shader object. + * + * @return the shader source string. + */ + final String getShaderSource() { + return shaderSource; + } + + final void setShaderSource(String shaderSource) { + this.shaderSource = shaderSource; + } + + synchronized void createMirrorObject() { + // System.out.println("SourceCodeShaderRetained : createMirrorObject"); + + if (mirror == null) { + SourceCodeShaderRetained mirrorSCS = new SourceCodeShaderRetained(); + mirror = mirrorSCS; + } + + initMirrorObject(); + } + + /** + * Initializes a mirror object. + */ + synchronized void initMirrorObject() { + mirror.source = source; + + ((SourceCodeShaderRetained) mirror).set(shadingLanguage, shaderType, shaderSource); + ((SourceCodeShaderRetained) mirror).shaderIds = null; + } + + synchronized void updateMirrorObject(int component, Object value) { + System.out.println("SourceCodeShader.updateMirrorObject not implemented yet!"); + } + +} diff --git a/src/classes/share/javax/media/j3d/SpotLight.java b/src/classes/share/javax/media/j3d/SpotLight.java index b8fc2fc..9f2900d 100644 --- a/src/classes/share/javax/media/j3d/SpotLight.java +++ b/src/classes/share/javax/media/j3d/SpotLight.java @@ -94,6 +94,13 @@ public class SpotLight extends PointLight { public static final int ALLOW_DIRECTION_READ = CapabilityBits.SPOT_LIGHT_ALLOW_DIRECTION_READ; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SPREAD_ANGLE_READ, + ALLOW_CONCENTRATION_READ, + ALLOW_DIRECTION_READ + }; + /** * Constructs a SpotLight node with default parameters. * The default values are as follows: @@ -104,6 +111,8 @@ public class SpotLight extends PointLight { * </ul> */ public SpotLight() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -124,6 +133,10 @@ public class SpotLight extends PointLight { float spreadAngle, float concentration) { super(color, position, attenuation); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((SpotLightRetained)this.retained).initDirection(direction); ((SpotLightRetained)this.retained).initSpreadAngle(spreadAngle); ((SpotLightRetained)this.retained).initConcentration(concentration); @@ -148,6 +161,10 @@ public class SpotLight extends PointLight { float spreadAngle, float concentration) { super(lightOn, color, position, attenuation); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((SpotLightRetained)this.retained).initDirection(direction); ((SpotLightRetained)this.retained).initSpreadAngle(spreadAngle); ((SpotLightRetained)this.retained).initConcentration(concentration); diff --git a/src/classes/share/javax/media/j3d/Switch.java b/src/classes/share/javax/media/j3d/Switch.java index 28acc2a..359e365 100644 --- a/src/classes/share/javax/media/j3d/Switch.java +++ b/src/classes/share/javax/media/j3d/Switch.java @@ -64,6 +64,11 @@ public class Switch extends Group { */ public static final int CHILD_MASK = -3; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_SWITCH_READ + }; + /** * Constructs a Switch node with default parameters. * The default values are as follows: @@ -73,6 +78,8 @@ public class Switch extends Group { * </ul> */ public Switch() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -81,7 +88,10 @@ public class Switch extends Group { * @param whichChild the initial child selection index */ public Switch(int whichChild) { - ((SwitchRetained)this.retained).setWhichChild(whichChild, true); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((SwitchRetained)this.retained).setWhichChild(whichChild, true); } /** @@ -91,7 +101,10 @@ public class Switch extends Group { * @param childMask the initial child selection mask */ public Switch(int whichChild, BitSet childMask){ - ((SwitchRetained)this.retained).setWhichChild(whichChild, true); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((SwitchRetained)this.retained).setWhichChild(whichChild, true); ((SwitchRetained)this.retained).setChildMask(childMask); } diff --git a/src/classes/share/javax/media/j3d/TexCoordGeneration.java b/src/classes/share/javax/media/j3d/TexCoordGeneration.java index 2915a27..f19c34c 100644 --- a/src/classes/share/javax/media/j3d/TexCoordGeneration.java +++ b/src/classes/share/javax/media/j3d/TexCoordGeneration.java @@ -230,6 +230,14 @@ public class TexCoordGeneration extends NodeComponent { */ public static final int TEXTURE_COORDINATE_4 = 2; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_ENABLE_READ, + ALLOW_FORMAT_READ, + ALLOW_MODE_READ, + ALLOW_PLANE_READ + }; + /** * Constructs a TexCoordGeneration object with default parameters. * The default values are as follows: @@ -245,6 +253,8 @@ public class TexCoordGeneration extends NodeComponent { */ public TexCoordGeneration() { // Just use the defaults + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -259,7 +269,10 @@ public class TexCoordGeneration extends NodeComponent { * @see Canvas3D#queryProperties */ public TexCoordGeneration(int genMode, int format) { - ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); ((TexCoordGenerationRetained)this.retained).initFormat(format); } @@ -276,7 +289,10 @@ public class TexCoordGeneration extends NodeComponent { * @see Canvas3D#queryProperties */ public TexCoordGeneration(int genMode, int format, Vector4f planeS) { - ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); ((TexCoordGenerationRetained)this.retained).initFormat(format); ((TexCoordGenerationRetained)this.retained).initPlaneS(planeS); } @@ -296,7 +312,10 @@ public class TexCoordGeneration extends NodeComponent { */ public TexCoordGeneration(int genMode, int format, Vector4f planeS, Vector4f planeT) { - ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); ((TexCoordGenerationRetained)this.retained).initFormat(format); ((TexCoordGenerationRetained)this.retained).initPlaneS(planeS); ((TexCoordGenerationRetained)this.retained).initPlaneT(planeT); @@ -317,7 +336,10 @@ public class TexCoordGeneration extends NodeComponent { */ public TexCoordGeneration(int genMode, int format, Vector4f planeS, Vector4f planeT, Vector4f planeR) { - ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); ((TexCoordGenerationRetained)this.retained).initFormat(format); ((TexCoordGenerationRetained)this.retained).initPlaneS(planeS); ((TexCoordGenerationRetained)this.retained).initPlaneT(planeT); @@ -343,7 +365,10 @@ public class TexCoordGeneration extends NodeComponent { public TexCoordGeneration(int genMode, int format, Vector4f planeS, Vector4f planeT, Vector4f planeR, Vector4f planeQ) { - ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((TexCoordGenerationRetained)this.retained).initGenMode(genMode); ((TexCoordGenerationRetained)this.retained).initFormat(format); ((TexCoordGenerationRetained)this.retained).initPlaneS(planeS); ((TexCoordGenerationRetained)this.retained).initPlaneT(planeT); diff --git a/src/classes/share/javax/media/j3d/Text3D.java b/src/classes/share/javax/media/j3d/Text3D.java index af9e81d..c62fee4 100644 --- a/src/classes/share/javax/media/j3d/Text3D.java +++ b/src/classes/share/javax/media/j3d/Text3D.java @@ -206,6 +206,17 @@ public class Text3D extends Geometry { */ public static final int PATH_DOWN = 3; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_FONT3D_READ, + ALLOW_STRING_READ, + ALLOW_POSITION_READ, + ALLOW_ALIGNMENT_READ, + ALLOW_PATH_READ, + ALLOW_CHARACTER_SPACING_READ, + ALLOW_BOUNDING_BOX_READ + }; + /** * Constructs a Text3D object with default parameters. * The default values are as follows: @@ -219,6 +230,8 @@ public class Text3D extends Geometry { * </ul> */ public Text3D() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -227,6 +240,9 @@ public class Text3D extends Geometry { * @see Font3D */ public Text3D(Font3D font3D) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((Text3DRetained)this.retained).setFont3D(font3D); } @@ -239,6 +255,9 @@ public class Text3D extends Geometry { * @see Font3D */ public Text3D(Font3D font3D, String string) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((Text3DRetained)this.retained).setFont3D(font3D); ((Text3DRetained)this.retained).setString(string); } @@ -252,6 +271,9 @@ public class Text3D extends Geometry { * @see Font3D */ public Text3D(Font3D font3D, String string, Point3f position) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((Text3DRetained)this.retained).setFont3D(font3D); ((Text3DRetained)this.retained).setString(string); ((Text3DRetained)this.retained).setPosition(position); @@ -268,6 +290,9 @@ public class Text3D extends Geometry { */ public Text3D(Font3D font3D, String string, Point3f position, int alignment, int path) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((Text3DRetained)this.retained).setFont3D(font3D); ((Text3DRetained)this.retained).setString(string); ((Text3DRetained)this.retained).setPosition(position); diff --git a/src/classes/share/javax/media/j3d/Text3DRetained.java b/src/classes/share/javax/media/j3d/Text3DRetained.java index f446850..23c2ae6 100644 --- a/src/classes/share/javax/media/j3d/Text3DRetained.java +++ b/src/classes/share/javax/media/j3d/Text3DRetained.java @@ -472,7 +472,7 @@ class Text3DRetained extends GeometryRetained { // use its bounds and not localBounds. // bounds is actually a reference to // mirrorShape3D.source.localBounds. - // TODO : Should only need to update distinct localBounds. + // XXXX : Should only need to update distinct localBounds. s.getCombineBounds((BoundingBox)s.bounds); } @@ -838,45 +838,39 @@ class Text3DRetained extends GeometryRetained { super.markAsLive(); } - - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { - Transform3D tempT3D = VirtualUniverse.mc.getTransform3D(null); + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { + Transform3D tempT3D = new Transform3D(); GeometryArrayRetained geo = null; int sIndex = -1; PickShape newPS; - double x = 0, y = 0, z = 0; double minDist = Double.MAX_VALUE; - + double distance =0.0; + Point3d closestIPnt = new Point3d(); + for (int i=0; i < numChars; i++) { geo= geometryList[i]; if (geo != null) { tempT3D.invert(charTransforms[i]); newPS = pickShape.transform(tempT3D); - if (geo.intersect(newPS, dist, iPnt)) { - if (dist == null) { + if (geo.intersect(newPS, iInfo, flags, iPnt)) { + if (flags == 0) { return true; } - if (dist[0] < minDist) { + distance = newPS.distance(iPnt); + if (distance < minDist) { sIndex = i; - minDist = dist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minDist = distance; + closestIPnt.set(iPnt); } } } } - FreeListManager.freeObject(FreeListManager.TRANSFORM3D, tempT3D); - if (sIndex >= 0) { // We need to transform iPnt to the vworld to compute the actual distance. // In this method we'll transform iPnt by its char. offset. Shape3D will // do the localToVworld transform. - iPnt.x = x; - iPnt.y = y; - iPnt.z = z; - dist[0] = minDist; + iPnt.set(closestIPnt); charTransforms[sIndex].transform(iPnt); return true; } diff --git a/src/classes/share/javax/media/j3d/Texture.java b/src/classes/share/javax/media/j3d/Texture.java index 4eaae1e..7e28ef8 100644 --- a/src/classes/share/javax/media/j3d/Texture.java +++ b/src/classes/share/javax/media/j3d/Texture.java @@ -534,6 +534,22 @@ public abstract class Texture extends NodeComponent { */ public static final int ANISOTROPIC_SINGLE_VALUE = 1; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_ANISOTROPIC_FILTER_READ, + ALLOW_BOUNDARY_COLOR_READ, + ALLOW_BOUNDARY_MODE_READ, + ALLOW_ENABLE_READ, + ALLOW_FILTER4_READ, + ALLOW_FILTER_READ, + ALLOW_FORMAT_READ, + ALLOW_IMAGE_READ, + ALLOW_LOD_RANGE_READ, + ALLOW_MIPMAP_MODE_READ, + ALLOW_SHARPEN_TEXTURE_READ, + ALLOW_SIZE_READ + }; + /** * Constructs a Texture object with default parameters. * The default values are as follows: @@ -566,6 +582,8 @@ public abstract class Texture extends NodeComponent { */ public Texture() { // Just use default values + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -600,6 +618,9 @@ public abstract class Texture extends NodeComponent { (format != RGB) && (format != RGBA)) { throw new IllegalArgumentException(J3dI18N.getString("Texture1")); } + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); int widPower = getPowerOf2(width); if (widPower == -1) @@ -654,6 +675,9 @@ public abstract class Texture extends NodeComponent { throw new IllegalArgumentException(J3dI18N.getString("Texture1")); } + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + int widPower = getPowerOf2(width); if (widPower == -1) throw new IllegalArgumentException(J3dI18N.getString("Texture2")); @@ -1722,7 +1746,8 @@ public abstract class Texture extends NodeComponent { rt.initImage(i, image); } } - // TODO: clone new v1.2 attributes + // XXXX: clone new v1.2 attributes? + // NOTE: This sppears to have already been done } /** diff --git a/src/classes/share/javax/media/j3d/Texture2D.java b/src/classes/share/javax/media/j3d/Texture2D.java index 5fa7be7..dc5be50 100644 --- a/src/classes/share/javax/media/j3d/Texture2D.java +++ b/src/classes/share/javax/media/j3d/Texture2D.java @@ -131,7 +131,10 @@ public class Texture2D extends Texture { */ public static final int DETAIL_MODULATE = 1; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_DETAIL_TEXTURE_READ + }; /** * Constructs a texture object using default values. @@ -149,6 +152,9 @@ public class Texture2D extends Texture { */ public Texture2D() { super(); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + } /** @@ -173,6 +179,9 @@ public class Texture2D extends Texture { int height){ super(mipMapMode, format, width, height); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } @@ -209,6 +218,9 @@ public class Texture2D extends Texture { int boundaryWidth) { super(mipMapMode, format, width, height, boundaryWidth); + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** diff --git a/src/classes/share/javax/media/j3d/TextureAttributes.java b/src/classes/share/javax/media/j3d/TextureAttributes.java index d302e50..cb2f002 100644 --- a/src/classes/share/javax/media/j3d/TextureAttributes.java +++ b/src/classes/share/javax/media/j3d/TextureAttributes.java @@ -411,6 +411,15 @@ public class TextureAttributes extends NodeComponent { */ public static final int COMBINE_ONE_MINUS_SRC_ALPHA = 3; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_BLEND_COLOR_READ, + ALLOW_COLOR_TABLE_READ, + ALLOW_COMBINE_READ, + ALLOW_MODE_READ, + ALLOW_TRANSFORM_READ + }; + /** * Constructs a TextureAttributes object with default parameters. * The default values are as follows: @@ -441,6 +450,8 @@ public class TextureAttributes extends NodeComponent { * </ul> */ public TextureAttributes() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -474,7 +485,10 @@ public class TextureAttributes extends NodeComponent { throw new IllegalArgumentException(J3dI18N.getString("TextureAttributes9")); } - ((TextureAttributesRetained)this.retained).initTextureMode(textureMode); + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + + ((TextureAttributesRetained)this.retained).initTextureMode(textureMode); ((TextureAttributesRetained)this.retained).initTextureBlendColor(textureBlendColor); ((TextureAttributesRetained)this.retained).initTextureTransform(transform); ((TextureAttributesRetained)this.retained).initPerspectiveCorrectionMode(perspCorrectionMode); diff --git a/src/classes/share/javax/media/j3d/TextureAttributesRetained.java b/src/classes/share/javax/media/j3d/TextureAttributesRetained.java index c77e743..d4b0993 100644 --- a/src/classes/share/javax/media/j3d/TextureAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/TextureAttributesRetained.java @@ -525,9 +525,11 @@ class TextureAttributesRetained extends NodeComponentRetained { int[] combineRgbFcn, int[] combineAlphaFcn, int combineRgbScale, int combineAlphaScale); - native void restoreBlend1Pass(long ctx); - native void updateBlend2Pass(long ctx); - + // NOTE: the following native methods are not used any more, since + // we no longer do simulated multi-pass by default + // (and with shaders, this won't work anyway) +// native void restoreBlend1Pass(long ctx); +// native void updateBlend2Pass(long ctx); void updateNative(Canvas3D cv, boolean simulate, int textureFormat) { @@ -653,31 +655,31 @@ class TextureAttributesRetained extends NodeComponentRetained { case TextureAttributes.COMBINE: case TextureAttributes.REPLACE: cv.setBlendFunc(cv.ctx, - TransparencyAttributesRetained.BLEND_ONE, - TransparencyAttributesRetained.BLEND_ZERO); + TransparencyAttributes.BLEND_ONE, + TransparencyAttributes.BLEND_ZERO); break; case TextureAttributes.MODULATE: cv.setBlendFunc(cv.ctx, - TransparencyAttributesRetained.BLEND_DST_COLOR, - TransparencyAttributesRetained.BLEND_ZERO); + TransparencyAttributes.BLEND_DST_COLOR, + TransparencyAttributes.BLEND_ZERO); break; case TextureAttributes.DECAL: if (textureFormat == Texture.RGBA) { cv.setBlendFunc(cv.ctx, - TransparencyAttributesRetained.BLEND_SRC_ALPHA, - TransparencyAttributesRetained.BLEND_ONE_MINUS_SRC_ALPHA); + TransparencyAttributes.BLEND_SRC_ALPHA, + TransparencyAttributes.BLEND_ONE_MINUS_SRC_ALPHA); } else { cv.setBlendFunc(cv.ctx, - TransparencyAttributesRetained.BLEND_ONE, - TransparencyAttributesRetained.BLEND_ZERO); + TransparencyAttributes.BLEND_ONE, + TransparencyAttributes.BLEND_ZERO); } break; case TextureAttributes.BLEND: cv.setBlendColor(cv.ctx, textureBlendColor.x, textureBlendColor.y, textureBlendColor.z, textureBlendColor.w); cv.setBlendFunc(cv.ctx, - TransparencyAttributesRetained.BLEND_CONSTANT_COLOR, - TransparencyAttributesRetained.BLEND_ONE_MINUS_SRC_COLOR); + TransparencyAttributes.BLEND_CONSTANT_COLOR, + TransparencyAttributes.BLEND_ONE_MINUS_SRC_COLOR); break; } } diff --git a/src/classes/share/javax/media/j3d/TextureBin.java b/src/classes/share/javax/media/j3d/TextureBin.java index 7145adf..3e1c91f 100644 --- a/src/classes/share/javax/media/j3d/TextureBin.java +++ b/src/classes/share/javax/media/j3d/TextureBin.java @@ -27,10 +27,10 @@ class TextureBin extends Object implements ObjectUpdate { TextureUnitStateRetained [] texUnitState = null; // last active texture unit - int lastActiveTexUnitIndex; + private int lastActiveTexUnitIndex; // number of active texture unit - int numActiveTexUnit; + private int numActiveTexUnit; /** * The RenderBin for this object @@ -38,11 +38,21 @@ class TextureBin extends Object implements ObjectUpdate { RenderBin renderBin = null; /** - * The AttribureBin that this TextureBin resides + * The EnvironmentSet that this TextureBin resides + */ + EnvironmentSet environmentSet = null; + + /** + * The AttributeBin that this TextureBin resides */ AttributeBin attributeBin = null; /** + * The ShaderBin that this TextureBin resides + */ + ShaderBin shaderBin = null; + + /** * The references to the next and previous TextureBins in the * list. */ @@ -172,7 +182,6 @@ class TextureBin extends Object implements ObjectUpdate { int i, j; boolean foundDisableUnit = false; numActiveTexUnit = 0; - boolean d3dBlendMode = false; lastActiveTexUnitIndex = 0; boolean soleUser = ((tbFlag & TextureBin.SOLE_USER) != 0); TextureRetained prevFirstTexture = null; @@ -321,11 +330,13 @@ class TextureBin extends Object implements ObjectUpdate { } - // track the last active texture unit - // and the total number of active texture unit + // Track the last active texture unit and the total number + // of active texture units. Note that this total number + // now includes disabled units so that there is always + // a one-to-one mapping. We no longer remap texture units. if (texUnitState[i].isTextureEnabled()) { - numActiveTexUnit++; lastActiveTexUnitIndex = i; + numActiveTexUnit = i + 1; if (foundDisableUnit) { @@ -337,7 +348,7 @@ class TextureBin extends Object implements ObjectUpdate { foundDisableUnit = true; } } - } + } // check to see if the TextureBin sorting criteria is // modified for this textureBin; if yes, mark that @@ -698,12 +709,14 @@ class TextureBin extends Object implements ObjectUpdate { tbFlag |= TextureBin.CONTIGUOUS_ACTIVE_UNITS; for (int i = 0; i < texUnitState.length; i++) { - // track the last active texture unit - // and the total number of active texture unit + // Track the last active texture unit and the total number + // of active texture units. Note that this total number + // now includes disabled units so that there is always + // a one-to-one mapping. We no longer remap texture units. if (texUnitState[i] != null && texUnitState[i].isTextureEnabled()) { - numActiveTexUnit++; lastActiveTexUnitIndex = i; + numActiveTexUnit = i + 1; if (foundDisableUnit) { @@ -754,7 +767,7 @@ class TextureBin extends Object implements ObjectUpdate { // sorted transparency if (transparentRMList == null && (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE || - attributeBin.environmentSet.lightBin.geometryBackground != null)) { + environmentSet.lightBin.geometryBackground != null)) { // System.out.println("========> addTransparentTextureBin "+this); transparentRMList = addAll(transparentRenderMoleculeMap, addTransparentRMs, transparentRMList, false); @@ -895,7 +908,7 @@ class TextureBin extends Object implements ObjectUpdate { } - // TODO: Could the analysis be done during insertRenderMolecule? + // XXXX: Could the analysis be done during insertRenderMolecule? // Return the head of the list, // if the insertion occurred at beginning of the list RenderMolecule insertRenderMolecule(RenderMolecule r, @@ -1046,7 +1059,7 @@ class TextureBin extends Object implements ObjectUpdate { } // If the renderMolecule removed is not opaque then .. if (!r.isOpaqueOrInOG && transparentRMList == null && (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE || - attributeBin.environmentSet.lightBin.geometryBackground != null)) { + environmentSet.lightBin.geometryBackground != null)) { renderBin.removeTransparentObject(this); } // If the rm removed is the one that is referenced in the tinfo @@ -1065,12 +1078,11 @@ class TextureBin extends Object implements ObjectUpdate { renderBin.removeTextureBin(this); } - attributeBin.removeTextureBin(this); + shaderBin.removeTextureBin(this); texUnitState = null; } } - /** * This method is called to update the state for this * TextureBin. This is only applicable in the single-pass case. @@ -1078,28 +1090,48 @@ class TextureBin extends Object implements ObjectUpdate { * state update. */ void updateAttributes(Canvas3D cv, int pass) { - + boolean dirty = ((cv.canvasDirty & (Canvas3D.TEXTUREBIN_DIRTY| Canvas3D.TEXTUREATTRIBUTES_DIRTY)) != 0); - if (cv.textureBin == this && !dirty) { return; } cv.textureBin = this; - + // save the current number of active texture unit so as // to be able to reset the one that is not enabled in this bin int lastActiveTexUnitIdx = -1; - // set the number active texture unit in Canvas3D - cv.setNumActiveTexUnit(numActiveTexUnit); + // Get the number of available texture units; this depends on + // whether or not shaders are being used. + boolean useShaders = (shaderBin.shaderProgram != null); + int availableTextureUnits = + useShaders ? cv.maxTextureImageUnits : cv.maxTextureUnits; + + // If the number of active texture units is greater than the number of + // supported units, and we don't allow simulated multi-texture, then we + // need to set a flag indicating that the texture units are invalid. + boolean disableTexture = false; + + if (pass < 0 && numActiveTexUnit > availableTextureUnits) { + disableTexture = true; +// System.err.println("*** TextureBin : number of texture units exceeded"); + } + + // set the number active texture unit in Canvas3D + if (disableTexture) { + cv.setNumActiveTexUnit(0); + } + else { + cv.setNumActiveTexUnit(numActiveTexUnit); + } // state update - if (numActiveTexUnit <= 0) { - if (cv.getLastActiveTexUnit() >= 0) { + if (numActiveTexUnit <= 0 || disableTexture) { + if (cv.getLastActiveTexUnit() >= 0) { // no texture units enabled // when the canvas supports multi texture units, @@ -1117,20 +1149,8 @@ class TextureBin extends Object implements ObjectUpdate { cv.setLastActiveTexUnit(-1); } } else if (pass < 0) { - int j = 0; - boolean oneToOneMapping; - - if ((pass == USE_VERTEXARRAY) || VirtualUniverse.mc.isD3D()) { - // d3d or when the texUnitStateMap requires more texture - // units than what is supported by the canvas, then - // we'll need a compact texture unit mapping, that is, - // only the enabled texUnitStates will be mapped to - // texture units. And as a matter of fact, the - // render atoms will be rendered as vertex array. - oneToOneMapping = false; - } else { - oneToOneMapping = true; - } + + int j = 0; for (int i = 0; i < texUnitState.length; i++) { @@ -1156,24 +1176,13 @@ class TextureBin extends Object implements ObjectUpdate { // unit to a texture unit state lastActiveTexUnitIdx = j; - cv.setTexUnitStateMap(i, j++); - - - } else if (oneToOneMapping) { - // one to one mapping is needed when display list - // is used to render multi-textured geometries, - // since when display list is created, the texture - // unit state to texture unit mapping is based on - // the geometry texCoordMap only. At render time, - // the texture unit state enable flags could have - // been changed. In keeping a one to one mapping, - // we'll not need to rebuild the display list + } else { if (j <= cv.getLastActiveTexUnit()) { cv.resetTexture(cv.ctx, j); } - - cv.setTexUnitStateMap(i, j++); } + + j++; } // make sure to disable the remaining texture units @@ -1196,7 +1205,7 @@ class TextureBin extends Object implements ObjectUpdate { cv.activeTextureUnit(cv.ctx, 0); } else { - // update the last active texture unit state + // update the last active texture unit state if (dirty || cv.texUnitState[0].mirror == null || cv.texUnitState[0].mirror != texUnitState[lastActiveTexUnitIndex].mirror) { @@ -1205,7 +1214,6 @@ class TextureBin extends Object implements ObjectUpdate { cv.texUnitState[0].mirror = texUnitState[lastActiveTexUnitIndex].mirror; - cv.setTexUnitStateMap(0, 0); cv.setLastActiveTexUnit(0); } } @@ -1222,46 +1230,43 @@ class TextureBin extends Object implements ObjectUpdate { void render(Canvas3D cv, Object rlist) { - boolean d3dBlendMode = false; cv.texLinearMode = false; /* System.out.println("TextureBin/render " + this + " numActiveTexUnit= " + numActiveTexUnit + - " numTexUnitSupported= " + cv.numTexUnitSupported); + " maxTextureUnits= " + cv.maxTextureUnits); */ // include this TextureBin to the to-be-updated state set in canvas cv.setStateToUpdate(Canvas3D.TEXTUREBIN_BIT, this); - - if ((texUnitState != null) && - VirtualUniverse.mc.isD3D()) { + + // For D3D - set the texLinearMode flag in the canvas if texcoord + // generation is enabled in object_linear mode for any texture unit. + if ((texUnitState != null) && VirtualUniverse.mc.isD3D()) { TextureUnitStateRetained tus; - // use multi-pass if one of the stage use blend mode for (int i = 0; i < texUnitState.length; i++) { tus = texUnitState[i]; - if ((tus != null) && - tus.isTextureEnabled()) { - if (tus.needBlend2Pass(cv)) { - d3dBlendMode = true; - } + if ((tus != null) && tus.isTextureEnabled()) { if ((tus.texGen != null) && - (tus.texGen.genMode == - TexCoordGeneration.OBJECT_LINEAR)) { + (tus.texGen.genMode == TexCoordGeneration.OBJECT_LINEAR)) { cv.texLinearMode = true; } } } - } + } + + // If shaders are not being used, and if allowSimulatedMultiTexture + // property is set, then we will use simulated (multi-pass) + // multi-texture when the requested number of texture units exceeds + // the available number of texture units + boolean useShaders = (shaderBin.shaderProgram != null); + int availableTextureUnits = + useShaders ? cv.maxTextureImageUnits : cv.maxTextureUnits; - if ((numActiveTexUnit > cv.numTexUnitSupported) || - d3dBlendMode) { + if (!useShaders && (numActiveTexUnit > availableTextureUnits) && + VirtualUniverse.mc.allowSimulatedMultiTexture) { multiPassRender(cv, rlist); - } else if ((numActiveTexUnit > 0) && - !VirtualUniverse.mc.isD3D() && - (texUnitState.length > cv.numTexUnitSupported) && - ((tbFlag & TextureBin.CONTIGUOUS_ACTIVE_UNITS) == 0)) { - renderList(cv, USE_VERTEXARRAY, rlist); } else { renderList(cv, USE_DISPLAYLIST, rlist); } @@ -1286,7 +1291,7 @@ class TextureBin extends Object implements ObjectUpdate { */ void renderList(Canvas3D cv, int pass, RenderMolecule rlist) { - // bit mask of all attr fields that are equivalent across + // bit mask of all attr fields that are equivalent across // renderMolecules thro. ORing of invisible RMs. int combinedDirtyBits = 0; boolean rmVisible = true; @@ -1330,9 +1335,11 @@ class TextureBin extends Object implements ObjectUpdate { /** * multi rendering pass to simulate multiple texture units */ - void multiPassRender(Canvas3D cv, Object rlist) { + private void multiPassRender(Canvas3D cv, Object rlist) { + + assert VirtualUniverse.mc.allowSimulatedMultiTexture; - boolean startToSimulate = false; + boolean startToSimulate = false; boolean isFogEnabled = false; // No lazy download of texture for multi-pass, @@ -1366,7 +1373,7 @@ class TextureBin extends Object implements ObjectUpdate { // first check if there is fog in the path // if there is, then turn off fog now and turn it back on // for the last pass only - isFogEnabled = (attributeBin.environmentSet.fog != null); + isFogEnabled = (environmentSet.fog != null); TextureUnitStateRetained tus; @@ -1388,31 +1395,12 @@ class TextureBin extends Object implements ObjectUpdate { } } - if (!tus.needBlend2Pass(cv)) { - // turn on fog again in the last pass + // turn on fog again in the last pass - if (i == lastActiveTexUnitIndex && isFogEnabled) { - cv.setFogEnableFlag(cv.ctx, true); - } - renderList(cv, i, rlist); - - } else { - // D3d needs two passes to simulate Texture.Blend mode - tus.texAttrs.updateNative(cv, false, tus.texture.format); - renderList(cv, i, rlist); - - tus.texAttrs.updateBlend2Pass(cv.ctx); - - // turn on fog again in the last pass - - if (i == lastActiveTexUnitIndex && isFogEnabled) { - cv.setFogEnableFlag(cv.ctx, true); - } - renderList(cv, i, rlist); - - // restore original blend mode in case - tus.texAttrs.restoreBlend1Pass(cv.ctx); - } + if (i == lastActiveTexUnitIndex && isFogEnabled) { + cv.setFogEnableFlag(cv.ctx, true); + } + renderList(cv, i, rlist); } } @@ -1465,16 +1453,22 @@ class TextureBin extends Object implements ObjectUpdate { transparentRMList = head; if (transparentRMList == null && (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE || - attributeBin.environmentSet.lightBin.geometryBackground != null)) { + environmentSet.lightBin.geometryBackground != null)) { renderBin.removeTransparentObject(this); } + // Issue 129: remove the RM's render atoms from the + // list of transparent render atoms + if ((renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) && + (environmentSet.lightBin.geometryBackground == null)) { + r.addRemoveTransparentObject(renderBin, false); + } } } HashMap renderMoleculeMap; RenderMolecule startList; // Now insert in the other bin - r.evalAlphaUsage(attributeBin.definingRenderingAttributes, texUnitState); + r.evalAlphaUsage(shaderBin.attributeBin.definingRenderingAttributes, texUnitState); r.isOpaqueOrInOG = r.isOpaque() ||r.inOrderedGroup; if (r.isOpaqueOrInOG) { startList = opaqueRMList; @@ -1565,14 +1559,20 @@ class TextureBin extends Object implements ObjectUpdate { // If transparent and not in bg geometry and inodepth sorted transparency if (transparentRMList == null&& (renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE || - attributeBin.environmentSet.lightBin.geometryBackground != null)) { + environmentSet.lightBin.geometryBackground != null)) { transparentRMList = startList; renderBin.addTransparentObject(this); } else { transparentRMList = startList; } - + // Issue 129: add the RM's render atoms to the list of + // transparent render atoms + // XXXX: do we need to resort the list after the add??? + if ((renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) && + (environmentSet.lightBin.geometryBackground == null)) { + r.addRemoveTransparentObject(renderBin, true); + } } } @@ -1659,10 +1659,10 @@ class TextureBin extends Object implements ObjectUpdate { if (numEditingRenderMolecules == 0) { // if number of editing renderMolecules goes to 0, - // inform the attributeBin that this textureBin goes to + // inform the shaderBin that this textureBin goes to // zombie state - attributeBin.decrActiveTextureBin(); + shaderBin.decrActiveTextureBin(); } } @@ -1671,9 +1671,9 @@ class TextureBin extends Object implements ObjectUpdate { if (numEditingRenderMolecules == 0) { // if this textureBin is in zombie state, inform - // the attributeBin that this textureBin is activated again. + // the shaderBin that this textureBin is activated again. - attributeBin.incrActiveTextureBin(); + shaderBin.incrActiveTextureBin(); } numEditingRenderMolecules++; diff --git a/src/classes/share/javax/media/j3d/TextureRetained.java b/src/classes/share/javax/media/j3d/TextureRetained.java index 190c43b..545ad3a 100644 --- a/src/classes/share/javax/media/j3d/TextureRetained.java +++ b/src/classes/share/javax/media/j3d/TextureRetained.java @@ -12,9 +12,9 @@ package javax.media.j3d; +import java.awt.image.BufferedImage; import java.util.*; import javax.vecmath.*; -import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; /** @@ -949,7 +949,7 @@ abstract class TextureRetained extends NodeComponentRetained { super.doSetLive(backgroundGroup, refCount); - // TODO: for now, do setLive for all the defined images. + // XXXX: for now, do setLive for all the defined images. // But in theory, we only need to setLive those within the // baseLevel and maximumLevel range. But then we'll need // setLive and clearLive image when the range changes. @@ -1366,8 +1366,9 @@ abstract class TextureRetained extends NodeComponentRetained { yoffset = image.height - yoffset - height; } else { + // Fix issue 132 imageData = ((DataBufferByte) - image.bImage[0].getData().getDataBuffer()).getData(); + ((BufferedImage)image.bImage[0]).getRaster().getDataBuffer()).getData(); // based on the yUp flag in the associated ImageComponent, // adjust the yoffset @@ -2031,12 +2032,12 @@ abstract class TextureRetained extends NodeComponentRetained { if (arg == null) { // no subimage info, so the entire image is to be updated info.entireImage = true; - - } else if ((arg.width >= width/2) && (arg.height >= height/2)) { - - // if the subimage dimension is close to the complete dimension, - // use the full update (it's more efficient) - info.entireImage = true; + // Fix issue 117 using ogl subimage always +// } else if ((arg.width >= width/2) && (arg.height >= height/2)) { +// +// // if the subimage dimension is close to the complete dimension, +// // use the full update (it's more efficient) +// info.entireImage = true; } else { info.entireImage = false; } @@ -2137,30 +2138,30 @@ abstract class TextureRetained extends NodeComponentRetained { mirrorTexture.addImageUpdateInfo(level, face, null); } else if ((component & IMAGES_CHANGED) != 0) { - + Object [] arg = (Object []) value; ImageComponent [] images = (ImageComponent[])arg[0]; - int face = ((Integer)arg[1]).intValue(); - + int face = ((Integer)arg[1]).intValue(); + for (int i = 0; i < images.length; i++) { - + // first remove texture from the userList of the current - // referencing image - if (mirrorTexture.images[face][i] != null) { - mirrorTexture.images[face][i].removeUser(mirror); - } - - // assign the new image and add texture to the userList - if (images[i] == null) { - mirrorTexture.images[face][i] = null; - } else { - mirrorTexture.images[face][i] = - (ImageComponentRetained)images[i].retained; - mirrorTexture.images[face][i].addUser(mirror); - } + // referencing image + if (mirrorTexture.images[face][i] != null) { + mirrorTexture.images[face][i].removeUser(mirror); + } + + // assign the new image and add texture to the userList + if (images[i] == null) { + mirrorTexture.images[face][i] = null; + } else { + mirrorTexture.images[face][i] = + (ImageComponentRetained)images[i].retained; + mirrorTexture.images[face][i].addUser(mirror); + } } mirrorTexture.updateResourceCreationMask(); - + // NOTE: the old images have to be removed from the // renderBins' NodeComponentList and new image have to be // added to the lists. This will be taken care of @@ -2169,7 +2170,7 @@ abstract class TextureRetained extends NodeComponentRetained { } else if ((component & BASE_LEVEL_CHANGED) != 0) { int level = ((Integer)value).intValue(); - + if (level < mirrorTexture.baseLevel) { // add texture to the userList of those new levels of diff --git a/src/classes/share/javax/media/j3d/TextureUnitState.java b/src/classes/share/javax/media/j3d/TextureUnitState.java index 635a499..fa9949c 100644 --- a/src/classes/share/javax/media/j3d/TextureUnitState.java +++ b/src/classes/share/javax/media/j3d/TextureUnitState.java @@ -66,7 +66,11 @@ public class TextureUnitState extends NodeComponent { public static final int ALLOW_STATE_WRITE = CapabilityBits.TEXTURE_UNIT_STATE_ALLOW_STATE_WRITE; - + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_STATE_READ + }; + /** * Constructs a TextureUnitState component object using defaults for all * state variables. All component object references are initialized @@ -74,6 +78,8 @@ public class TextureUnitState extends NodeComponent { */ public TextureUnitState() { // Just use default values + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -90,6 +96,8 @@ public class TextureUnitState extends NodeComponent { public TextureUnitState(Texture texture, TextureAttributes textureAttributes, TexCoordGeneration texCoordGeneration) { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); ((TextureUnitStateRetained)this.retained).initTexture(texture); ((TextureUnitStateRetained)this.retained).initTextureAttributes( diff --git a/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java b/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java index 86dce99..266ef12 100644 --- a/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java +++ b/src/classes/share/javax/media/j3d/TextureUnitStateRetained.java @@ -592,17 +592,6 @@ class TextureUnitStateRetained extends NodeComponentRetained { return (texture != null && texture.enable); } - // use by D3D to simulate OGL blend mode using multi-pass - final boolean needBlend2Pass(Canvas3D cv) { - return ((texAttrs != null) && - VirtualUniverse.mc.isD3D() && - ((cv.textureExtendedFeatures & - Canvas3D.TEXTURE_LERP) == 0) && - (texAttrs.textureMode == TextureAttributes.BLEND) && - (texture.format != Texture.ALPHA) && - (texture.format != Texture.INTENSITY)); - } - void handleFrequencyChange(int bit) { switch (bit) { case TextureUnitState.ALLOW_STATE_WRITE: { diff --git a/src/classes/share/javax/media/j3d/TimerThread.java b/src/classes/share/javax/media/j3d/TimerThread.java index ae34fc6..a5f8878 100644 --- a/src/classes/share/javax/media/j3d/TimerThread.java +++ b/src/classes/share/javax/media/j3d/TimerThread.java @@ -33,7 +33,7 @@ class TimerThread extends Thread { // Wakeup {all?} Sound Scheduler{s} for every sample time reach // QUESTION: this sampling time is set to a very large value so Sound // Schedulers are not pinged often unless explicitly requested - // TODO: need a way to remove/null this condition when all + // XXXX: need a way to remove/null this condition when all // soundschedulers are halted private WakeupOnElapsedTime soundSchedCond = new WakeupOnElapsedTime(120000); // every 2 minutes @@ -61,7 +61,7 @@ class TimerThread extends Thread { } void addSoundSchedCond(long wakeupTime) { - // TODO: there are potentially multiple sound schedulers. + // XXXX: there are potentially multiple sound schedulers. // this code will force a wait up on ALL sound schedulers // even though only one needs to process the sound that // this wakeup condition is triggered by. diff --git a/src/classes/share/javax/media/j3d/Transform3D.java b/src/classes/share/javax/media/j3d/Transform3D.java index 69e5c62..99920d4 100644 --- a/src/classes/share/javax/media/j3d/Transform3D.java +++ b/src/classes/share/javax/media/j3d/Transform3D.java @@ -4588,7 +4588,7 @@ public class Transform3D { double[] svdScales = new double[3]; - // TODO: initialize to 0's if alread allocd? Should not have to, since + // XXXX: initialize to 0's if alread allocd? Should not have to, since // no operations depend on these being init'd to zero. int converged, negCnt=0; @@ -4833,7 +4833,7 @@ public class Transform3D { } } - // TODO: could eliminate use of t1 and t1 by making a new method which + // XXXX: could eliminate use of t1 and t1 by making a new method which // transposes and multiplies two matricies transpose_mat(u1, t1); transpose_mat(v1, t2); diff --git a/src/classes/share/javax/media/j3d/TransformGroup.java b/src/classes/share/javax/media/j3d/TransformGroup.java index 5aae8d2..a4b3f19 100644 --- a/src/classes/share/javax/media/j3d/TransformGroup.java +++ b/src/classes/share/javax/media/j3d/TransformGroup.java @@ -61,11 +61,18 @@ public class TransformGroup extends Group { public static final int ALLOW_TRANSFORM_WRITE = CapabilityBits.TRANSFORM_GROUP_ALLOW_TRANSFORM_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_TRANSFORM_READ + }; + /** * Constructs and initializes a TransformGroup using an * identity transform. */ public TransformGroup() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -74,11 +81,14 @@ public class TransformGroup extends Group { * @param t1 the transform3D object * @exception BadTransformException if the transform is not affine. */ - public TransformGroup(Transform3D t1) { + public TransformGroup(Transform3D t1) { if (!t1.isAffine()) { throw new BadTransformException(J3dI18N.getString("TransformGroup0")); } - + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); + ((TransformGroupRetained)this.retained).setTransform(t1); } diff --git a/src/classes/share/javax/media/j3d/TransformGroupData.java b/src/classes/share/javax/media/j3d/TransformGroupData.java index e41a086..e14d3c3 100644 --- a/src/classes/share/javax/media/j3d/TransformGroupData.java +++ b/src/classes/share/javax/media/j3d/TransformGroupData.java @@ -14,8 +14,8 @@ package javax.media.j3d; class TransformGroupData extends NodeData { // per path node data - // TODO: replace per path mirror objects with node data - // TODO: move other TransfromGroup related data here + // XXXX: replace per path mirror objects with node data + // XXXX: move other TransfromGroup related data here boolean switchDirty = false; // use for eliminate multiple updates and generate unique targets diff --git a/src/classes/share/javax/media/j3d/TransformGroupRetained.java b/src/classes/share/javax/media/j3d/TransformGroupRetained.java index 734a6b3..0672359 100644 --- a/src/classes/share/javax/media/j3d/TransformGroupRetained.java +++ b/src/classes/share/javax/media/j3d/TransformGroupRetained.java @@ -92,7 +92,7 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface // User copy. CachedTargets[] cachedTargets = null; - // Contains per path data, TODO: move to NodeRetained + // Contains per path data, XXXX: move to NodeRetained TransformGroupData[] perPathData = null; @@ -512,7 +512,7 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface int len; Object obj; - // TODO - optimization for targetThreads computation, require + // XXXX - optimization for targetThreads computation, require // cleanup in GroupRetained.doSetLive() //int savedTargetThreads = 0; //savedTargetThreads = s.transformTargetThreads; @@ -765,7 +765,7 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface } } } - // TODO: recontruct targetThreads + // XXXX: recontruct targetThreads } @@ -1155,7 +1155,7 @@ class TransformGroupRetained extends GroupRetained implements TargetsInterface // type is ignored here, only need for SharedGroup if (type == TargetsInterface.TRANSFORM_TARGETS) { - // TODO : For now we'll OR more than exact. + // XXXX : For now we'll OR more than exact. //targetThreads = localTargetThreads | childTargetThreads; targetThreads = targetThreads | childTargetThreads; if (parentTransformLink != null) { diff --git a/src/classes/share/javax/media/j3d/TransformStructure.java b/src/classes/share/javax/media/j3d/TransformStructure.java index 0232f98..0edc91c 100644 --- a/src/classes/share/javax/media/j3d/TransformStructure.java +++ b/src/classes/share/javax/media/j3d/TransformStructure.java @@ -182,7 +182,7 @@ class TransformStructure extends J3dStructure implements ObjectUpdate { } processCurrentLocalToVworld(); - // TODO: temporary -- processVwcBounds will be + // XXXX: temporary -- processVwcBounds will be // done in GeometryStructure if (objectList.size() > 0) { processGeometryAtomVwcBounds(); @@ -393,7 +393,7 @@ class TransformStructure extends J3dStructure implements ObjectUpdate { tg = (TransformGroupRetained)dirtyTransformGroups.get(i); // Check if the transformGroup is still alive - // TODO: This is a hack, should be fixed after EA + // XXXX: This is a hack, should be fixed after EA // Null pointer checking should be removed! // should call trans = tg.getCurrentChildLocalToVworld(key); synchronized(tg) { diff --git a/src/classes/share/javax/media/j3d/TransparencyAttributes.java b/src/classes/share/javax/media/j3d/TransparencyAttributes.java index 9e88f62..d5be231 100644 --- a/src/classes/share/javax/media/j3d/TransparencyAttributes.java +++ b/src/classes/share/javax/media/j3d/TransparencyAttributes.java @@ -14,18 +14,18 @@ package javax.media.j3d; /** * The TransparencyAttributes object defines all attributes affecting - * transparency of the object. The transparency attributes are:<P> - * <UL> - * <LI>Transparency mode - defines how transparency is applied to - * this Appearance component object:</LI><P> - * <UL> - * <LI>FASTEST - uses the fastest available method for transparency.</LI><P> - * <LI>NICEST - uses the nicest available method for transparency.</LI><P> - * <LI>SCREEN_DOOR - uses screen-door transparency. This is done using + * transparency of the object. The transparency attributes are:<p> + * <ul> + * <li>Transparency mode - defines how transparency is applied to + * this Appearance component object:</li><p> + * <ul> + * <li>FASTEST - uses the fastest available method for transparency.</li><p> + * <li>NICEST - uses the nicest available method for transparency.</li><p> + * <li>SCREEN_DOOR - uses screen-door transparency. This is done using * an on/off stipple pattern in which the percentage of transparent pixels * is approximately equal to the value specified by the transparency - * parameter.</LI><P> - * <LI>BLENDED - uses alpha blended transparency. The blend equation is + * parameter.</li><p> + * <li>BLENDED - uses alpha blended transparency. The blend equation is * specified by the srcBlendFunction and dstBlendFunction attributes. * The default equation is: * <ul> @@ -45,27 +45,36 @@ package javax.media.j3d; * alpha<sub><font size=-1>pix</font></sub> * * (1-transparency)</code>. * </ul> - * </LI><P> - * <LI>NONE - no transparency; opaque object.</LI><P> - * </UL> - * <LI>Blend function - used in blended transparency and antialiasing + * </li><p> + * <li>NONE - no transparency; opaque object.</li><p> + * </ul> + * <li>Transparency value - the amount of transparency to be applied to this + * Appearance component object. The transparency values are in the + * range [0.0, 1.0], with 0.0 being fully opaque and 1.0 being + * fully transparent.</li><p> + * <li>Blend function - used in blended transparency and antialiasing * operations. The source function specifies the factor that is * multiplied by the source color. This value is added to the product * of the destination factor and the destination color. The default * source blend function is BLEND_SRC_ALPHA. The source blend function - * is one of the following:</LI><P> - * <UL> - * <LI>BLEND_ZERO - the blend function is <code>f = 0</code>.</LI> - * <LI>BLEND_ONE - the blend function is <code>f = 1</code>.</LI> - * <LI>BLEND_SRC_ALPHA - the blend function is <code>f = - * alpha<sub><font size=-1>src</font></sub></code>.</LI> - * <LI>BLEND_ONE_MINUS_SRC_ALPHA - the blend function is <code>f = - * 1 - alpha<sub><font size=-1>src</font></sub></code>.</LI></UL><P> - * <LI>Blend value - the amount of transparency to be applied to this - * Appearance component object. The transparency values are in the - * range [0.0, 1.0], with 0.0 being fully opaque and 1.0 being - * fully transparent.</LI><P> - * </UL> + * is one of the following:</li><p> + * <ul> + * <li>BLEND_ZERO - the blend function is <code>f = 0</code></li> + * <li>BLEND_ONE - the blend function is <code>f = 1</code></li> + * <li>BLEND_SRC_ALPHA - the blend function is <code>f = + * alpha<sub><font size=-1>src</font></sub></code></li> + * <li>BLEND_ONE_MINUS_SRC_ALPHA - the blend function is <code>f = + * 1 - alpha<sub><font size=-1>src</font></sub></code></li> + * <li>BLEND_DST_COLOR - the blend function is <code>f = + * color<sub><font size=-1>dst</font></sub></code></li> + * <li>BLEND_ONE_MINUS_DST_COLOR - the blend function is <code>f = + * 1 - color<sub><font size=-1>dst</font></sub></code></li> + * <li>BLEND_SRC_COLOR - the blend function is <code>f = + * color<sub><font size=-1>src</font></sub></code></li> + * <li>BLEND_ONE_MINUS_SRC_COLOR - the blend function is <code>f = + * 1 - color<sub><font size=-1>src</font></sub></code></li> + * </ul> + * </ul> */ public class TransparencyAttributes extends NodeComponent { /** @@ -173,6 +182,7 @@ public class TransparencyAttributes extends NodeComponent { * Blend function: <code>f = 0</code>. * @see #setSrcBlendFunction * @see #setDstBlendFunction + * * @since Java 3D 1.2 */ public static final int BLEND_ZERO = 0; @@ -181,6 +191,7 @@ public class TransparencyAttributes extends NodeComponent { * Blend function: <code>f = 1</code>. * @see #setSrcBlendFunction * @see #setDstBlendFunction + * * @since Java 3D 1.2 */ public static final int BLEND_ONE = 1; @@ -190,6 +201,7 @@ public class TransparencyAttributes extends NodeComponent { * <code>f = alpha<sub><font size=-1>src</font></sub></code>. * @see #setSrcBlendFunction * @see #setDstBlendFunction + * * @since Java 3D 1.2 */ public static final int BLEND_SRC_ALPHA = 2; @@ -199,12 +211,67 @@ public class TransparencyAttributes extends NodeComponent { * <code>f = 1-alpha<sub><font size=-1>src</font></sub></code>. * @see #setSrcBlendFunction * @see #setDstBlendFunction + * * @since Java 3D 1.2 */ public static final int BLEND_ONE_MINUS_SRC_ALPHA = 3; + /** + * Blend function: + * <code>f = color<sub><font size=-1>dst</font></sub></code>. + * <p>Note that this function may <i>only</i> be used as a source + * blend function.</p> + * @see #setSrcBlendFunction + * + * @since Java 3D 1.4 + */ + public static final int BLEND_DST_COLOR = 4; + + /** + * Blend function: + * <code>f = 1-color<sub><font size=-1>dst</font></sub></code>. + * <p>Note that this function may <i>only</i> be used as a source + * blend function.</p> + * @see #setSrcBlendFunction + * + * @since Java 3D 1.4 + */ + public static final int BLEND_ONE_MINUS_DST_COLOR = 5; /** + * Blend function: + * <code>f = color<sub><font size=-1>src</font></sub></code>. + * <p>Note that this function may <i>only</i> be used as a destination + * blend function.</p> + * @see #setDstBlendFunction + * + * @since Java 3D 1.4 + */ + public static final int BLEND_SRC_COLOR = 6; + + /** + * Blend function: + * <code>f = 1-color<sub><font size=-1>src</font></sub></code>. + * <p>Note that this function may <i>only</i> be used as a destination + * blend function.</p> + * @see #setDstBlendFunction + * + * @since Java 3D 1.4 + */ + public static final int BLEND_ONE_MINUS_SRC_COLOR = 7; + + static final int BLEND_CONSTANT_COLOR = 8; + + static final int MAX_BLEND_FUNC_TABLE_SIZE = 9; + + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_BLEND_FUNCTION_READ, + ALLOW_MODE_READ, + ALLOW_VALUE_READ + }; + + /** * Constructs a TransparencyAttributes object with default parameters. * The default values are as follows: * <ul> @@ -216,6 +283,8 @@ public class TransparencyAttributes extends NodeComponent { */ public TransparencyAttributes() { // Just use the default for all attributes + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** @@ -238,20 +307,20 @@ public class TransparencyAttributes extends NodeComponent { * @param tVal the transparency value * @param srcBlendFunction the blend function to be used for the source * color, one of <code>BLEND_ZERO</code>, <code>BLEND_ONE</code>, - * <code>BLEND_SRC_ALPHA</code>, or <code>BLEND_ONE_MINUS_SRC_ALPHA</code>. + * <code>BLEND_SRC_ALPHA</code>, <code>BLEND_ONE_MINUS_SRC_ALPHA</code>, + * <code>BLEND_DST_COLOR</code>, or <code>BLEND_ONE_MINUS_DST_COLOR</code>. * @param dstBlendFunction the blend function to be used for the * destination * color, one of <code>BLEND_ZERO</code>, <code>BLEND_ONE</code>, - * <code>BLEND_SRC_ALPHA</code>, or <code>BLEND_ONE_MINUS_SRC_ALPHA</code>. + * <code>BLEND_SRC_ALPHA</code>, <code>BLEND_ONE_MINUS_SRC_ALPHA</code>, + * <code>BLEND_SRC_COLOR</code>, or <code>BLEND_ONE_MINUS_SRC_COLOR</code>. * @exception IllegalArgumentException if * <code>tMode</code> is a value other than * <code>NONE</code>, <code>FASTEST</code>, <code>NICEST</code>, * <code>SCREEN_DOOR</code>, or <code>BLENDED</code> * @exception IllegalArgumentException if * <code>srcBlendFunction</code> or <code>dstBlendFunction</code> - * is a value other than <code>BLEND_ZERO</code>, <code>BLEND_ONE</code>, - * <code>BLEND_SRC_ALPHA</code>, or - * <code>BLEND_ONE_MINUS_SRC_ALPHA</code>. + * is a value other than one of the supported functions listed above. * * @since Java 3D 1.2 */ @@ -263,15 +332,32 @@ public class TransparencyAttributes extends NodeComponent { throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes6")); } - if ((srcBlendFunction < BLEND_ZERO) || - (srcBlendFunction > BLEND_ONE_MINUS_SRC_ALPHA)) { - throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes7")); - } - - if ((dstBlendFunction < BLEND_ZERO) || - (dstBlendFunction > BLEND_ONE_MINUS_SRC_ALPHA)) { - throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes8")); - } + switch (srcBlendFunction) { + case BLEND_ZERO: + case BLEND_ONE: + case BLEND_SRC_ALPHA: + case BLEND_ONE_MINUS_SRC_ALPHA: + case BLEND_DST_COLOR: + case BLEND_ONE_MINUS_DST_COLOR: + break; + default: + throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes7")); + } + + switch (dstBlendFunction) { + case BLEND_ZERO: + case BLEND_ONE: + case BLEND_SRC_ALPHA: + case BLEND_ONE_MINUS_SRC_ALPHA: + case BLEND_SRC_COLOR: + case BLEND_ONE_MINUS_SRC_COLOR: + break; + default: + throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes8")); + } + + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); ((TransparencyAttributesRetained)this.retained).initTransparencyMode(tMode); ((TransparencyAttributesRetained)this.retained).initTransparency(tVal); @@ -370,15 +456,13 @@ public class TransparencyAttributes extends NodeComponent { * * @param blendFunction the blend function to be used for the source * color, one of <code>BLEND_ZERO</code>, <code>BLEND_ONE</code>, - * <code>BLEND_SRC_ALPHA</code>, or <code>BLEND_ONE_MINUS_SRC_ALPHA</code>. + * <code>BLEND_SRC_ALPHA</code>, <code>BLEND_ONE_MINUS_SRC_ALPHA</code>, + * <code>BLEND_DST_COLOR</code>, or <code>BLEND_ONE_MINUS_DST_COLOR</code>. + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph - * @exception IllegalArgumentException if - * <code>blendFunction</code> - * is a value other than <code>BLEND_ZERO</code>, - * <code>BLEND_ONE</code>, - * <code>BLEND_SRC_ALPHA</code>, or - * <code>BLEND_ONE_MINUS_SRC_ALPHA</code>. + * @exception IllegalArgumentException if <code>blendFunction</code> + * is a value other than one of the supported functions listed above. * * @since Java 3D 1.2 */ @@ -388,11 +472,17 @@ public class TransparencyAttributes extends NodeComponent { throw new CapabilityNotSetException(J3dI18N.getString("TransparencyAttributes4")); - if ((blendFunction < BLEND_ZERO) || - (blendFunction > BLEND_ONE_MINUS_SRC_ALPHA)) { - throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes7")); - } - + switch (blendFunction) { + case BLEND_ZERO: + case BLEND_ONE: + case BLEND_SRC_ALPHA: + case BLEND_ONE_MINUS_SRC_ALPHA: + case BLEND_DST_COLOR: + case BLEND_ONE_MINUS_DST_COLOR: + break; + default: + throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes7")); + } if (isLive()) ((TransparencyAttributesRetained)this.retained).setSrcBlendFunction(blendFunction); @@ -428,15 +518,13 @@ public class TransparencyAttributes extends NodeComponent { * * @param blendFunction the blend function to be used for the destination * color, one of <code>BLEND_ZERO</code>, <code>BLEND_ONE</code>, - * <code>BLEND_SRC_ALPHA</code>, or <code>BLEND_ONE_MINUS_SRC_ALPHA</code>. + * <code>BLEND_SRC_ALPHA</code>, <code>BLEND_ONE_MINUS_SRC_ALPHA</code>, + * <code>BLEND_SRC_COLOR</code>, or <code>BLEND_ONE_MINUS_SRC_COLOR</code>. + * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph - * @exception IllegalArgumentException if - * <code>blendFunction</code> - * is a value other than <code>BLEND_ZERO</code>, - * <code>BLEND_ONE</code>, - * <code>BLEND_SRC_ALPHA</code>, or - * <code>BLEND_ONE_MINUS_SRC_ALPHA</code>. + * @exception IllegalArgumentException if <code>blendFunction</code> + * is a value other than one of the supported functions listed above. * * @since Java 3D 1.2 */ @@ -445,10 +533,17 @@ public class TransparencyAttributes extends NodeComponent { if (!this.getCapability(ALLOW_BLEND_FUNCTION_WRITE)) throw new CapabilityNotSetException(J3dI18N.getString("TransparencyAttributes4")); - if ((blendFunction < BLEND_ZERO) || - (blendFunction > BLEND_ONE_MINUS_SRC_ALPHA)) { - throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes8")); - } + switch (blendFunction) { + case BLEND_ZERO: + case BLEND_ONE: + case BLEND_SRC_ALPHA: + case BLEND_ONE_MINUS_SRC_ALPHA: + case BLEND_SRC_COLOR: + case BLEND_ONE_MINUS_SRC_COLOR: + break; + default: + throw new IllegalArgumentException(J3dI18N.getString("TransparencyAttributes8")); + } if (isLive()) ((TransparencyAttributesRetained)this.retained).setDstBlendFunction(blendFunction); diff --git a/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java b/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java index 0123fc2..defbb44 100644 --- a/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java +++ b/src/classes/share/javax/media/j3d/TransparencyAttributesRetained.java @@ -38,16 +38,6 @@ class TransparencyAttributesRetained extends NodeComponentRetained { int srcBlendFunction = TransparencyAttributes.BLEND_SRC_ALPHA; int dstBlendFunction = TransparencyAttributes.BLEND_ONE_MINUS_SRC_ALPHA; - // Here are some blend functions that are used in multi-pass only - static final int BLEND_ZERO = 0; - static final int BLEND_ONE = 1; - static final int BLEND_SRC_ALPHA = 2; - static final int BLEND_ONE_MINUS_SRC_ALPHA = 3; - static final int BLEND_DST_COLOR = 4; - static final int BLEND_SRC_COLOR = 5; - static final int BLEND_ONE_MINUS_SRC_COLOR = 6; - static final int BLEND_CONSTANT_COLOR = 7; - /** * Sets the transparency mode for this * appearance component object. diff --git a/src/classes/share/javax/media/j3d/TransparentRenderingInfo.java b/src/classes/share/javax/media/j3d/TransparentRenderingInfo.java index bca1018..27c4e7d 100644 --- a/src/classes/share/javax/media/j3d/TransparentRenderingInfo.java +++ b/src/classes/share/javax/media/j3d/TransparentRenderingInfo.java @@ -11,10 +11,9 @@ */ package javax.media.j3d; -import javax.vecmath.*; -import java.util.*; -class TransparentRenderingInfo extends Object { + +class TransparentRenderingInfo extends Object implements com.sun.j3d.utils.scenegraph.transparency.TransparencySortGeom { // For DepthSortedTransparency, rm is the rendermolecule // that this rInfo is part of // For non depth sorted transparency, rm is one of the rendermolecules @@ -24,8 +23,9 @@ class TransparentRenderingInfo extends Object { RenderAtomListInfo rInfo; TransparentRenderingInfo prev; TransparentRenderingInfo next; + GeometryAtom geometryAtom; double zVal; // Used in DepthSorted Transparency - // TODO: Add Dirty info + // XXXX: Add Dirty info /** * update state before rendering transparent objects @@ -34,7 +34,8 @@ class TransparentRenderingInfo extends Object { TextureBin textureBin = rm.textureBin; AttributeBin attributeBin = textureBin.attributeBin; - + ShaderBin shaderBin = textureBin.shaderBin; + // Get a collection to check if switch is on RenderMolecule rm = textureBin.transparentRMList ; @@ -57,40 +58,44 @@ class TransparentRenderingInfo extends Object { return false; } - if (cv.environmentSet != attributeBin.environmentSet) { - - boolean visible = (attributeBin.definingRenderingAttributes == null || - attributeBin.definingRenderingAttributes.visible); + // XXXX : Code cleanup needed : The following code segment should simply test + // each bin independently and update it if necessary. + if (cv.environmentSet != attributeBin.environmentSet) { + + boolean visible = (attributeBin.definingRenderingAttributes == null || + attributeBin.definingRenderingAttributes.visible); + + if ( (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy + == View.VISIBILITY_DRAW_VISIBLE && !visible) || + (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy + == View.VISIBILITY_DRAW_INVISIBLE && visible)) { + return false; + } + attributeBin.environmentSet.lightBin.updateAttributes(cv); + attributeBin.environmentSet.updateAttributes(cv); + attributeBin.updateAttributes(cv); + shaderBin.updateTransparentAttributes(cv); + } else if (cv.attributeBin != attributeBin) { + boolean visible = (attributeBin.definingRenderingAttributes == null || + attributeBin.definingRenderingAttributes.visible); + + if ( (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy + == View.VISIBILITY_DRAW_VISIBLE && !visible) || + (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy + == View.VISIBILITY_DRAW_INVISIBLE && visible)) { + return false; + } + attributeBin.updateAttributes(cv); + shaderBin.updateTransparentAttributes(cv); + } else if (cv.shaderBin != shaderBin) { + shaderBin.updateTransparentAttributes(cv); + } - if ( (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy - == View.VISIBILITY_DRAW_VISIBLE && !visible) || - (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy - == View.VISIBILITY_DRAW_INVISIBLE && visible)) { - return false; - } - attributeBin.environmentSet.lightBin.updateAttributes(cv); - attributeBin.environmentSet.updateAttributes(cv); - attributeBin.updateAttributes(cv); - } - else { - if (cv.attributeBin != attributeBin) { - boolean visible = (attributeBin.definingRenderingAttributes == null || - attributeBin.definingRenderingAttributes.visible); - - if ( (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy - == View.VISIBILITY_DRAW_VISIBLE && !visible) || - (attributeBin.environmentSet.renderBin.view.viewCache.visibilityPolicy - == View.VISIBILITY_DRAW_INVISIBLE && visible)) { - return false; - } - attributeBin.updateAttributes(cv); - } - } - return true; + return true; } void render(Canvas3D cv) { - if (updateState(cv)) { + if (updateState(cv)) { rm.textureBin.render(cv, rm.textureBin.transparentRMList); } } @@ -101,4 +106,25 @@ class TransparentRenderingInfo extends Object { rm.textureBin.render(cv, this); } } + + public double getDistanceSquared() { + return zVal; + } + + public Geometry getGeometry() { + // XXXX: verify 0 is always the correct index. Assumption is that for + // Shape3D with multiple geometry each geometry is put in it's + // own geometryAtom. + if (geometryAtom.geometryArray[0]==null) + return null; + return (Geometry)geometryAtom.geometryArray[0].source; + } + + public void getLocalToVWorld(Transform3D localToVW) { + localToVW.set(rm.localToVworld[NodeRetained.LAST_LOCAL_TO_VWORLD]); + } + + public Shape3D getShape3D() { + return (Shape3D)geometryAtom.source.source; + } } diff --git a/src/classes/share/javax/media/j3d/TriangleArray.java b/src/classes/share/javax/media/j3d/TriangleArray.java index 32bb57b..8487007 100644 --- a/src/classes/share/javax/media/j3d/TriangleArray.java +++ b/src/classes/share/javax/media/j3d/TriangleArray.java @@ -24,23 +24,22 @@ public class TriangleArray extends GeometryArray { TriangleArray() {} /** - * Constructs an empty TriangleArray object with the specified - * number of vertices, and vertex format. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. + * Constructs an empty TriangleArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * * @exception IllegalArgumentException if vertexCount is less than 3 * or vertexCount is <i>not</i> a multiple of 3 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int)} + * for more exceptions that can be thrown */ public TriangleArray(int vertexCount, int vertexFormat) { super(vertexCount,vertexFormat); @@ -50,60 +49,30 @@ public class TriangleArray extends GeometryArray { } /** - * Constructs an empty TriangleArray object with the specified - * number of vertices, and vertex format, number of texture coordinate - * sets, and texture coordinate mapping array. - * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used. + * Constructs an empty TriangleArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 3 * or vertexCount is <i>not</i> a multiple of 3 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -120,6 +89,54 @@ public class TriangleArray extends GeometryArray { } /** + * Constructs an empty TriangleArray object using the specified + * parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 3 + * or vertexCount is <i>not</i> a multiple of 3 + * ;<br> + * See {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public TriangleArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes); + + if (vertexCount < 3 || ((vertexCount%3) != 0)) + throw new IllegalArgumentException(J3dI18N.getString("TriangleArray0")); + } + + + /** * Creates the retained mode TriangleArrayRetained object that this * TriangleArray object will point to. */ @@ -133,22 +150,26 @@ public class TriangleArray extends GeometryArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - TriangleArrayRetained rt = (TriangleArrayRetained) retained; - int texSetCount = rt.getTexCoordSetCount(); - TriangleArray t; - - if (texSetCount == 0) { - t = new TriangleArray(rt.getVertexCount(), - rt.getVertexFormat()); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - t = new TriangleArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap); - } - t.duplicateNodeComponent(this); + TriangleArrayRetained rt = (TriangleArrayRetained) retained; + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + TriangleArray t = new TriangleArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes); + t.duplicateNodeComponent(this); return t; } } diff --git a/src/classes/share/javax/media/j3d/TriangleArrayRetained.java b/src/classes/share/javax/media/j3d/TriangleArrayRetained.java index 6332bad..577495f 100644 --- a/src/classes/share/javax/media/j3d/TriangleArrayRetained.java +++ b/src/classes/share/javax/media/j3d/TriangleArrayRetained.java @@ -27,14 +27,15 @@ class TriangleArrayRetained extends GeometryArrayRetained { this.geoType = GEO_TYPE_TRI_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[3]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int i = ((vertexFormat & GeometryArray.BY_REFERENCE) == 0 ? initialVertexIndex : initialCoordIndex); - + int count = 0; + int minICount = 0; pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); @@ -47,12 +48,14 @@ class TriangleArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); + count += 3; if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { - minDist = sdist[0]; + minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -62,22 +65,24 @@ class TriangleArrayRetained extends GeometryArrayRetained { break; case PickShape.PICKSEGMENT: PickSegment pickSegment = (PickSegment) pickShape; - while (i < validVertexCount) { + + while (i < validVertexCount) { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); + count += 3; if (intersectSegment(pnts, pickSegment.start, - pickSegment.end, sdist, iPnt) - && (sdist[0] <= 1.0)) { - if (dist == null) { + pickSegment.end, sdist, iPnt)) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } } break; @@ -89,15 +94,17 @@ class TriangleArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); + count += 3; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; - z = iPnt.z; + z = iPnt.z; } } } @@ -110,12 +117,14 @@ class TriangleArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); + count += 3; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -131,13 +140,15 @@ class TriangleArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); + count += 3; if (intersectBoundingPolytope(pnts, bpolytope, sdist,iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -151,13 +162,15 @@ class TriangleArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); + count += 3; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -172,12 +185,14 @@ class TriangleArrayRetained extends GeometryArrayRetained { getVertexData(i++, pnts[0]); getVertexData(i++, pnts[1]); getVertexData(i++, pnts[2]); + count += 3; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -194,7 +209,15 @@ class TriangleArrayRetained extends GeometryArrayRetained { if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=3); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[3]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 3; + vertexIndices[1] = minICount - 2; + vertexIndices[2] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; @@ -263,8 +286,7 @@ class TriangleArrayRetained extends GeometryArrayRetained { break; } return false; - } - + } boolean intersect(Transform3D thisToOtherVworld, GeometryRetained geom) { diff --git a/src/classes/share/javax/media/j3d/TriangleFanArray.java b/src/classes/share/javax/media/j3d/TriangleFanArray.java index d8a9539..e536158 100644 --- a/src/classes/share/javax/media/j3d/TriangleFanArray.java +++ b/src/classes/share/javax/media/j3d/TriangleFanArray.java @@ -30,28 +30,26 @@ public class TriangleFanArray extends GeometryStripArray { TriangleFanArray() {} /** - * Constructs an empty TriangleFanArray object with the specified - * number of vertices, vertex format, and - * array of per-strip vertex counts. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param stripVertexCounts array that specifies - * the count of the number of vertices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty TriangleFanArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 3 * or any element in the stripVertexCounts array is less than 3 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int[])} + * for more exceptions that can be thrown */ public TriangleFanArray(int vertexCount, int vertexFormat, @@ -64,65 +62,34 @@ public class TriangleFanArray extends GeometryStripArray { } /** - * Constructs an empty TriangleFanArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, and - * array of per-strip vertex counts. - * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param stripVertexCounts array that specifies - * the count of the number of vertices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty TriangleFanArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 3 * or any element in the stripVertexCounts array is less than 3 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -141,6 +108,59 @@ public class TriangleFanArray extends GeometryStripArray { } /** + * Constructs an empty TriangleFanArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int,int[],int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 3 + * or any element in the stripVertexCounts array is less than 3 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int,int[],int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public TriangleFanArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int[] stripVertexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, + stripVertexCounts); + + if (vertexCount < 3 ) + throw new IllegalArgumentException(J3dI18N.getString("TriangleFanArray0")); + } + + /** * Creates the retained mode TriangleFanArrayRetained object that this * TriangleFanArray object will point to. */ @@ -154,25 +174,29 @@ public class TriangleFanArray extends GeometryStripArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - TriangleFanArrayRetained rt = (TriangleFanArrayRetained) retained; - int stripcounts[] = new int[rt.getNumStrips()]; - rt.getStripVertexCounts(stripcounts); - int texSetCount = rt.getTexCoordSetCount(); - TriangleFanArray t; - if (texSetCount == 0) { - t = new TriangleFanArray(rt.getVertexCount(), - rt.getVertexFormat(), - stripcounts); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - t = new TriangleFanArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - stripcounts); - } - t.duplicateNodeComponent(this); + TriangleFanArrayRetained rt = (TriangleFanArrayRetained) retained; + int stripcounts[] = new int[rt.getNumStrips()]; + rt.getStripVertexCounts(stripcounts); + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + TriangleFanArray t = new TriangleFanArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + stripcounts); + t.duplicateNodeComponent(this); return t; } diff --git a/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java b/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java index ba29127..1c77d6c 100644 --- a/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java +++ b/src/classes/share/javax/media/j3d/TriangleFanArrayRetained.java @@ -32,14 +32,16 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { this.geoType = GEO_TYPE_TRI_FAN_SET; } - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[3]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int i = 0; int j, end; - + int count = 0, fSCount; + int minICount = 0; + int minFSCount = 0; pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); @@ -51,19 +53,24 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { while (i < stripVertexCounts.length) { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; + fSCount = count; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); - if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + count++; + if (intersectRay(pnts, pickRay, sdist, iPnt)) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = count; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -76,20 +83,25 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { while (i < stripVertexCounts.length) { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; + fSCount = count; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); - if (intersectSegment(pnts, pickSegment.start, + count++; + if (intersectSegment(pnts, pickSegment.start, pickSegment.end, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -103,19 +115,24 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { while (i < stripVertexCounts.length) { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; + fSCount = count; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -129,20 +146,25 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { while (i < stripVertexCounts.length) { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; - getVertexData(j++, pnts[0]); + fSCount = count; + getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); - while (j < end) { + count += 2; + while (j < end) { getVertexData(j++, pnts[2]); - if (intersectBoundingSphere(pnts, bsphere, sdist, + count++; + if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -156,20 +178,25 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { while (i < stripVertexCounts.length) { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; + fSCount = count; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); - if (intersectBoundingPolytope(pnts, bpolytope, + count++; + if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -184,17 +211,22 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + fSCount = count; + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -207,19 +239,24 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { while (i < stripVertexCounts.length) { j = stripStartVertexIndices[i]; end = j + stripVertexCounts[i++]; - getVertexData(j++, pnts[0]); + fSCount = count; + getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; - x = iPnt.x; - y = iPnt.y; - z = iPnt.z; + minFSCount = fSCount; + minICount = count; + x = iPnt.x; + y = iPnt.y; + z = iPnt.z; } } pnts[1].set(pnts[2]); @@ -234,14 +271,22 @@ class TriangleFanArrayRetained extends GeometryStripArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >= 3); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[3]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minFSCount; + vertexIndices[1] = minICount - 2; + vertexIndices[2] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; - return true; + return true; } return false; - } + } // intersect pnts[] with every triangle in this object boolean intersect(Point3d[] pnts) { diff --git a/src/classes/share/javax/media/j3d/TriangleStripArray.java b/src/classes/share/javax/media/j3d/TriangleStripArray.java index 9c6c324..e6c9ed8 100644 --- a/src/classes/share/javax/media/j3d/TriangleStripArray.java +++ b/src/classes/share/javax/media/j3d/TriangleStripArray.java @@ -29,28 +29,26 @@ public class TriangleStripArray extends GeometryStripArray { TriangleStripArray() {} /** - * Constructs an empty TriangleStripArray object with the specified - * number of vertices, vertex format, and - * array of per-strip vertex counts. - * @param vertexCount the number of vertex elements in this array - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D. - * @param stripVertexCounts array that specifies - * the count of the number of vertices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty TriangleStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int)} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 3 * or any element in the stripVertexCounts array is less than 3 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int[])} + * for more exceptions that can be thrown */ public TriangleStripArray(int vertexCount, int vertexFormat, @@ -63,65 +61,34 @@ public class TriangleStripArray extends GeometryStripArray { } /** - * Constructs an empty TriangleStripArray object with the specified - * number of vertices, vertex format, number of texture coordinate - * sets, texture coordinate mapping array, and - * array of per-strip vertex counts. - * - * @param vertexCount the number of vertex elements in this array<p> - * - * @param vertexFormat a mask indicating which components are - * present in each vertex. This is specified as one or more - * individual flags that are bitwise "OR"ed together to describe - * the per-vertex data. - * The flags include: COORDINATES, to signal the inclusion of - * vertex positions--always present; NORMALS, to signal - * the inclusion of per vertex normals; one of COLOR_3, - * COLOR_4, to signal the inclusion of per vertex - * colors (without or with color information); and one of - * TEXTURE_COORDINATE_2, TEXTURE_COORDINATE_3 or TEXTURE_COORDINATE_4, - * to signal the - * inclusion of per-vertex texture coordinates 2D, 3D or 4D.<p> - * - * @param texCoordSetCount the number of texture coordinate sets - * in this GeometryArray object. If <code>vertexFormat</code> - * does not include one of <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3 or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetCount</code> parameter is not used.<p> - * - * @param texCoordSetMap an array that maps texture coordinate - * sets to texture units. The array is indexed by texture unit - * number for each texture unit in the associated Appearance - * object. The values in the array specify the texture coordinate - * set within this GeometryArray object that maps to the - * corresponding texture - * unit. All elements within the array must be less than - * <code>texCoordSetCount</code>. A negative value specifies that - * no texture coordinate set maps to the texture unit - * corresponding to the index. If there are more texture units in - * any associated Appearance object than elements in the mapping - * array, the extra elements are assumed to be -1. The same - * texture coordinate set may be used for more than one texture - * unit. Each texture unit in every associated Appearance must - * have a valid source of texture coordinates: either a - * non-negative texture coordinate set must be specified in the - * mapping array or texture coordinate generation must be enabled. - * Texture coordinate generation will take precedence for those - * texture units for which a texture coordinate set is specified - * and texture coordinate generation is enabled. If - * <code>vertexFormat</code> does not include one of - * <code>TEXTURE_COORDINATE_2</code>, - * <code>TEXTURE_COORDINATE_3</code> or - * <code>TEXTURE_COORDINATE_4</code>, the - * <code>texCoordSetMap</code> array is not used.<p> - * - * @param stripVertexCounts array that specifies - * the count of the number of vertices for each separate strip. - * The length of this array is the number of separate strips. + * Constructs an empty TriangleStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[])} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int[])} + * for a description of this parameter. * * @exception IllegalArgumentException if vertexCount is less than 3 * or any element in the stripVertexCounts array is less than 3 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int[])} + * for more exceptions that can be thrown * * @since Java 3D 1.2 */ @@ -140,6 +107,59 @@ public class TriangleStripArray extends GeometryStripArray { } /** + * Constructs an empty TriangleStripArray object using the + * specified parameters. + * + * @param vertexCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexFormat + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param texCoordSetMap + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrCount + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param vertexAttrSizes + * see {@link GeometryArray#GeometryArray(int,int,int,int[],int,int[])} + * for a description of this parameter. + * + * @param stripVertexCounts + * see {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int,int[],int[])} + * for a description of this parameter. + * + * @exception IllegalArgumentException if vertexCount is less than 3 + * or any element in the stripVertexCounts array is less than 3 + * ;<br> + * See {@link GeometryStripArray#GeometryStripArray(int,int,int,int[],int,int[],int[])} + * for more exceptions that can be thrown + * + * @since Java 3D 1.4 + */ + public TriangleStripArray(int vertexCount, + int vertexFormat, + int texCoordSetCount, + int[] texCoordSetMap, + int vertexAttrCount, + int[] vertexAttrSizes, + int[] stripVertexCounts) { + + super(vertexCount, vertexFormat, + texCoordSetCount, texCoordSetMap, + vertexAttrCount, vertexAttrSizes, + stripVertexCounts); + + if (vertexCount < 3 ) + throw new IllegalArgumentException(J3dI18N.getString("TriangleStripArray0")); + } + + /** * Creates the retained mode TriangleStripArrayRetained object that this * TriangleStripArray object will point to. */ @@ -153,26 +173,29 @@ public class TriangleStripArray extends GeometryStripArray { * @deprecated replaced with cloneNodeComponent(boolean forceDuplicate) */ public NodeComponent cloneNodeComponent() { - TriangleStripArrayRetained rt = (TriangleStripArrayRetained) retained; + TriangleStripArrayRetained rt = (TriangleStripArrayRetained) retained; int stripcounts[] = new int[rt.getNumStrips()]; - rt.getStripVertexCounts(stripcounts); - int texSetCount = rt.getTexCoordSetCount(); - TriangleStripArray t; - if (texSetCount == 0) { - t = new TriangleStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - stripcounts); - } else { - int texMap[] = new int[rt.getTexCoordSetMapLength()]; - rt.getTexCoordSetMap(texMap); - t = new TriangleStripArray(rt.getVertexCount(), - rt.getVertexFormat(), - texSetCount, - texMap, - stripcounts); - - } - t.duplicateNodeComponent(this); + rt.getStripVertexCounts(stripcounts); + int texSetCount = rt.getTexCoordSetCount(); + int[] texMap = null; + int vertexAttrCount = rt.getVertexAttrCount(); + int[] vertexAttrSizes = null; + if (texSetCount > 0) { + texMap = new int[rt.getTexCoordSetMapLength()]; + rt.getTexCoordSetMap(texMap); + } + if (vertexAttrCount > 0) { + vertexAttrSizes = new int[vertexAttrCount]; + rt.getVertexAttrSizes(vertexAttrSizes); + } + TriangleStripArray t = new TriangleStripArray(rt.getVertexCount(), + rt.getVertexFormat(), + texSetCount, + texMap, + vertexAttrCount, + vertexAttrSizes, + stripcounts); + t.duplicateNodeComponent(this); return t; } } diff --git a/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java b/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java index db4b8ba..14c177a 100644 --- a/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java +++ b/src/classes/share/javax/media/j3d/TriangleStripArrayRetained.java @@ -30,15 +30,16 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { TriangleStripArrayRetained() { this.geoType = GEO_TYPE_TRI_STRIP_SET; } - - boolean intersect(PickShape pickShape, double dist[], Point3d iPnt) { + + boolean intersect(PickShape pickShape, PickInfo.IntersectionInfo iInfo, int flags, Point3d iPnt) { Point3d pnts[] = new Point3d[3]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; + int count = 0; + int minICount = 0; int i = 0; int j, end; - pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); @@ -52,18 +53,21 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectRay(pnts, pickRay, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; - } + } } pnts[0].set(pnts[1]); pnts[1].set(pnts[2]); @@ -78,15 +82,18 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectSegment(pnts, pickSegment.start, pickSegment.end, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -106,14 +113,17 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -133,15 +143,18 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -161,15 +174,18 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); - if (intersectBoundingPolytope(pnts, bpolytope, + count++; + if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -188,14 +204,17 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); - if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { - if (dist == null) { + count++; + if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -214,14 +233,17 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { end = j + stripVertexCounts[i++]; getVertexData(j++, pnts[0]); getVertexData(j++, pnts[1]); + count += 2; while (j < end) { getVertexData(j++, pnts[2]); + count++; if (intersectCone(pnts, pickCone, sdist, iPnt)) { - if (dist == null) { + if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; + minICount = count; x = iPnt.x; y = iPnt.y; z = iPnt.z; @@ -240,7 +262,15 @@ class TriangleStripArrayRetained extends GeometryStripArrayRetained { } if (minDist < Double.MAX_VALUE) { - dist[0] = minDist; + assert(minICount >=3); + int[] vertexIndices = iInfo.getVertexIndices(); + if (vertexIndices == null) { + vertexIndices = new int[3]; + iInfo.setVertexIndices(vertexIndices); + } + vertexIndices[0] = minICount - 3; + vertexIndices[1] = minICount - 2; + vertexIndices[2] = minICount - 1; iPnt.x = x; iPnt.y = y; iPnt.z = z; diff --git a/src/classes/share/javax/media/j3d/View.java b/src/classes/share/javax/media/j3d/View.java index 2b54b6a..daf6cd4 100644 --- a/src/classes/share/javax/media/j3d/View.java +++ b/src/classes/share/javax/media/j3d/View.java @@ -3305,7 +3305,7 @@ public class View extends Object { } // This is a temporary fix for bug 4267395 - // TODO:cleanup in RenderBin after View detach + // XXXX:cleanup in RenderBin after View detach // universe.addViewIdToFreeList(viewId); // using new property -Dj3d.forceReleaseView to disable bug fix 4267395 diff --git a/src/classes/share/javax/media/j3d/ViewCache.java b/src/classes/share/javax/media/j3d/ViewCache.java index 5aeec71..b506793 100644 --- a/src/classes/share/javax/media/j3d/ViewCache.java +++ b/src/classes/share/javax/media/j3d/ViewCache.java @@ -312,8 +312,7 @@ class ViewCache extends Object { trackerBaseToHeadTracker.setIdentity(); } - // TODO: implement head to vworld tracking if userHeadToVworldEnable - // is set + // XXXX: implement head to vworld tracking if userHeadToVworldEnable is set userHeadToVworld.setIdentity(); } diff --git a/src/classes/share/javax/media/j3d/ViewPlatform.java b/src/classes/share/javax/media/j3d/ViewPlatform.java index 59ebf66..bd518f2 100644 --- a/src/classes/share/javax/media/j3d/ViewPlatform.java +++ b/src/classes/share/javax/media/j3d/ViewPlatform.java @@ -108,6 +108,11 @@ public class ViewPlatform extends Leaf { public static final int ALLOW_POLICY_WRITE = CapabilityBits.VIEW_PLATFORM_ALLOW_POLICY_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_POLICY_READ + }; + /** * Constructs a ViewPlatform object with default parameters. * The default values are as follows: @@ -117,6 +122,8 @@ public class ViewPlatform extends Leaf { * </ul> */ public ViewPlatform() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } /** diff --git a/src/classes/share/javax/media/j3d/ViewPlatformRetained.java b/src/classes/share/javax/media/j3d/ViewPlatformRetained.java index 230235a..c523108 100644 --- a/src/classes/share/javax/media/j3d/ViewPlatformRetained.java +++ b/src/classes/share/javax/media/j3d/ViewPlatformRetained.java @@ -164,7 +164,6 @@ class ViewPlatformRetained extends LeafRetained { /** * This sets the view that is associated with this view platform. */ - // TODO: This must be changed to a list of views! void setView(View v) { synchronized (viewList) { if (!viewList.contains(v)) { diff --git a/src/classes/share/javax/media/j3d/ViewSpecificGroup.java b/src/classes/share/javax/media/j3d/ViewSpecificGroup.java index 8203551..bd87d04 100644 --- a/src/classes/share/javax/media/j3d/ViewSpecificGroup.java +++ b/src/classes/share/javax/media/j3d/ViewSpecificGroup.java @@ -71,11 +71,17 @@ public class ViewSpecificGroup extends Group { public static final int ALLOW_VIEW_WRITE = CapabilityBits.VIEW_SPECIFIC_GROUP_ALLOW_VIEW_WRITE; + // Array for setting default read capabilities + private static final int[] readCapabilities = { + ALLOW_VIEW_READ + }; /** * Constructs and initializes a new ViewSpecificGroup node object. */ public ViewSpecificGroup() { + // set default read capabilities + setDefaultReadCapabilities(readCapabilities); } @@ -324,7 +330,7 @@ public class ViewSpecificGroup extends Group { */ void duplicateAttributes(Node originalNode, boolean forceDuplicate) { - // TODO: implement this + // XXXX: implement this? super.duplicateAttributes(originalNode, forceDuplicate); ViewSpecificGroupRetained attr = (ViewSpecificGroupRetained) originalNode.retained; diff --git a/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java b/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java index 58cc08f..f60d052 100644 --- a/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java +++ b/src/classes/share/javax/media/j3d/ViewSpecificGroupRetained.java @@ -517,7 +517,7 @@ class ViewSpecificGroupRetained extends GroupRetained { // don't remove this group node mergeFlag = SceneGraphObjectRetained.DONT_MERGE; - // TODO: complete this + // XXXX: complete this } void setLive(SetLiveState s) { @@ -549,7 +549,7 @@ class ViewSpecificGroupRetained extends GroupRetained { s.viewScopedNodeList = new ArrayList(); s.scopedNodesViewList = new ArrayList(); } - // TODO: This is a hack since removeNodeData is called before + // XXXX: This is a hack since removeNodeData is called before // children are clearLives int[] tempIndex = null; // Don't keep the indices if everything will be cleared diff --git a/src/classes/share/javax/media/j3d/VirtualUniverse.java b/src/classes/share/javax/media/j3d/VirtualUniverse.java index bb9b14d..20c783b 100644 --- a/src/classes/share/javax/media/j3d/VirtualUniverse.java +++ b/src/classes/share/javax/media/j3d/VirtualUniverse.java @@ -15,6 +15,8 @@ package javax.media.j3d; import java.util.Vector; import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; import java.util.Map; /** @@ -155,6 +157,12 @@ public class VirtualUniverse extends Object { boolean isSceneGraphLock = false; private Object waitLock = new Object(); + + private HashSet structureChangeListenerSet = null; + + private HashSet shaderErrorListenerSet = null; + private ShaderErrorListener defaultShaderErrorListener = + ShaderProgram.getDefaultErrorListener(); /** * Constructs a new VirtualUniverse. @@ -549,7 +557,7 @@ public class VirtualUniverse extends Object { /** * This returns the next available nodeId as a string. */ - // TODO: reuse of id's imply a slight collision problem in the + // XXXX: reuse of id's imply a slight collision problem in the // render queue's. // BUG 4181362 String getNodeId() { @@ -990,4 +998,184 @@ public class VirtualUniverse extends Object { isSceneGraphLock = false; } } + + /** + * Adds the specified GraphStructureChangeListener to the set of listeners + * that will be notified when the graph structure is changed on a live + * scene graph. If the specifed listener is null no action is taken and no + * exception is thrown. + * + * @param listener the listener to add to the set. + * + * @since Java 3D 1.4 + */ + public void addGraphStructureChangeListener(GraphStructureChangeListener listener) { + if (listener == null) { + return; + } + + if (structureChangeListenerSet == null) { + structureChangeListenerSet = new HashSet(); + } + + synchronized(structureChangeListenerSet) { + structureChangeListenerSet.add(listener); + } + } + + /** + * Removes the specified GraphStructureChangeListener from the set of listeners. This + * method performs no function, nor does it throw an exception if the specified listener + * is not currently in the set or is null. + * + * @param listener the listener to remove from the set. + * + * @since Java 3D 1.4 + */ + public void removeGraphStructureChangeListener(GraphStructureChangeListener listener) { + if (structureChangeListenerSet == null) { + return; + } + + synchronized(structureChangeListenerSet) { + structureChangeListenerSet.remove(listener); + } + } + + /** + * Processes all live BranchGroup add and removes and notifies + * any registered listeners. Used for add and remove + */ + void notifyStructureChangeListeners(boolean add, Object parent, BranchGroup child) { + if (structureChangeListenerSet == null) { + return; + } + + synchronized(structureChangeListenerSet) { + Iterator it = structureChangeListenerSet.iterator(); + while(it.hasNext()) { + GraphStructureChangeListener listener = (GraphStructureChangeListener)it.next(); + try { + if (add) { + listener.branchGroupAdded(parent, child); + } else { + listener.branchGroupRemoved(parent, child); + } + } + catch (RuntimeException e) { + System.err.println("Exception occurred in GraphStructureChangeListener:"); + e.printStackTrace(); + } + } + } + } + + /** + * Processes all live BranchGroup moves and notifies + * any registered listeners. Used for moveTo + */ + void notifyStructureChangeListeners(Object oldParent, Object newParent, BranchGroup child) { + if (structureChangeListenerSet == null) { + return; + } + + synchronized(structureChangeListenerSet) { + Iterator it = structureChangeListenerSet.iterator(); + while(it.hasNext()) { + GraphStructureChangeListener listener = (GraphStructureChangeListener)it.next(); + try { + listener.branchGroupMoved(oldParent, newParent, child); + } + catch (RuntimeException e) { + System.err.println("Exception occurred in GraphStructureChangeListener:"); + e.printStackTrace(); + } + } + } + } + + + /** + * Adds the specified ShaderErrorListener to the set of listeners + * that will be notified when a programmable shader error is + * detected on a live scene graph. If the specifed listener is + * null no action is taken and no exception is thrown. + * If a shader error occurs, the listeners will be called + * asynchronously from a separate notification thread. The Java 3D + * renderer and behavior scheduler will continue to run as if the + * error had not occurred, except that shading will be disabled + * for the objects in error. If applications desire to detach or + * modify the scene graph as a result of the error, they should + * use a behavior post if they want that change to be + * synchronous with the renderer. + * + * @param listener the listener to add to the set. + * + * @since Java 3D 1.4 + */ + public void addShaderErrorListener(ShaderErrorListener listener) { + if (listener == null) { + return; + } + + if (shaderErrorListenerSet == null) { + shaderErrorListenerSet = new HashSet(); + } + + synchronized(shaderErrorListenerSet) { + shaderErrorListenerSet.add(listener); + } + } + + /** + * Removes the specified ShaderErrorListener from the set of + * listeners. This method performs no function, nor does it throw + * an exception if the specified listener is not currently in the + * set or is null. + * + * @param listener the listener to remove from the set. + * + * @since Java 3D 1.4 + */ + public void removeShaderErrorListener(ShaderErrorListener listener) { + if (shaderErrorListenerSet == null) { + return; + } + + synchronized(shaderErrorListenerSet) { + shaderErrorListenerSet.remove(listener); + } + } + + /** + * Notifies all listeners of a shader error. If no listeners exist, a default + * listener is notified. + */ + void notifyShaderErrorListeners(ShaderError error) { + boolean errorReported = false; + + // Notify all error listeners in the set + if (shaderErrorListenerSet != null) { + synchronized(shaderErrorListenerSet) { + Iterator it = shaderErrorListenerSet.iterator(); + while(it.hasNext()) { + ShaderErrorListener listener = (ShaderErrorListener)it.next(); + try { + listener.errorOccurred(error); + } + catch (RuntimeException e) { + System.err.println("Exception occurred in ShaderErrorListener:"); + e.printStackTrace(); + } + errorReported = true; + } + } + } + + // Notify the default error listener if the set is null or empty + if (!errorReported) { + defaultShaderErrorListener.errorOccurred(error); + } + } + } diff --git a/src/classes/share/javax/media/j3d/WakeupIndexedList.java b/src/classes/share/javax/media/j3d/WakeupIndexedList.java index c0a52ec..4a20594 100644 --- a/src/classes/share/javax/media/j3d/WakeupIndexedList.java +++ b/src/classes/share/javax/media/j3d/WakeupIndexedList.java @@ -59,7 +59,7 @@ package javax.media.j3d; class WakeupIndexedList implements Cloneable, java.io.Serializable { - // TODO: set to false when release + // XXXX: set to false when release final static boolean debug = false; /** |