diff options
author | Harvey Harrison <[email protected]> | 2015-04-19 21:02:06 -0700 |
---|---|---|
committer | Harvey Harrison <[email protected]> | 2015-04-19 21:02:06 -0700 |
commit | 7a2e20caac9db6f789a7b3fab344b9758af45335 (patch) | |
tree | b5236ff2570178de356eab569225108948eb4d30 /src/javax/media/j3d/RenderMolecule.java | |
parent | f76ce302c4bb2a9f03bbee571ec5d05c29633023 (diff) |
j3dcore: flatten the directory structure a bit
Signed-off-by: Harvey Harrison <[email protected]>
Diffstat (limited to 'src/javax/media/j3d/RenderMolecule.java')
-rw-r--r-- | src/javax/media/j3d/RenderMolecule.java | 3039 |
1 files changed, 3039 insertions, 0 deletions
diff --git a/src/javax/media/j3d/RenderMolecule.java b/src/javax/media/j3d/RenderMolecule.java new file mode 100644 index 0000000..269c1a0 --- /dev/null +++ b/src/javax/media/j3d/RenderMolecule.java @@ -0,0 +1,3039 @@ +/* + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package javax.media.j3d; + +import javax.vecmath.Vector3d; + +/** + * The RenderMolecule manages a collection of RenderAtoms. + */ + +class RenderMolecule extends IndexedObject implements ObjectUpdate, NodeComponentUpdate { + + + // different types of IndexedUnorderedSet that store RenderMolecule + static final int REMOVE_RENDER_ATOM_IN_RM_LIST = 0; + static final int RENDER_MOLECULE_LIST = 1; + + // total number of different IndexedUnorderedSet types + static final int TOTAL_INDEXED_UNORDER_SET_TYPES = 2; + + /** + * Values for the geometryType field + */ + static final int POINT = 0x01; + static final int LINE = 0x02; + static final int SURFACE = 0x04; + static final int RASTER = 0x08; + static final int COMPRESSED = 0x10; + + static int RM_COMPONENTS = (AppearanceRetained.POLYGON | + AppearanceRetained.LINE | + AppearanceRetained.POINT | + AppearanceRetained.MATERIAL | + AppearanceRetained.TRANSPARENCY| + AppearanceRetained.COLOR); + + // XXXX: use definingMaterial etc. instead of these + // when sole user is completely implement + PolygonAttributesRetained polygonAttributes = null; + LineAttributesRetained lineAttributes = null; + PointAttributesRetained pointAttributes = null; + MaterialRetained material = null; + ColoringAttributesRetained coloringAttributes = null; + TransparencyAttributesRetained transparency = null; + + // Use Object instead of AppearanceRetained class for + // state caching optimation memory performance + + boolean normalPresent = true; + + + // Equivalent bits + static final int POINTATTRS_DIRTY = AppearanceRetained.POINT; + static final int LINEATTRS_DIRTY = AppearanceRetained.LINE; + static final int POLYGONATTRS_DIRTY = AppearanceRetained.POLYGON; + static final int MATERIAL_DIRTY = AppearanceRetained.MATERIAL; + static final int TRANSPARENCY_DIRTY = AppearanceRetained.TRANSPARENCY; + static final int COLORINGATTRS_DIRTY = AppearanceRetained.COLOR; + + static final int ALL_DIRTY_BITS = POINTATTRS_DIRTY | LINEATTRS_DIRTY | POLYGONATTRS_DIRTY | MATERIAL_DIRTY | TRANSPARENCY_DIRTY | COLORINGATTRS_DIRTY; + + /** + * bit mask of all attr fields that are equivalent across + * renderMolecules + */ + int dirtyAttrsAcrossRms = ALL_DIRTY_BITS; + + + // Mask set to true is any of the component have changed + int soleUserCompDirty = 0; + + /** + * The PolygonAttributes for this RenderMolecule + */ + PolygonAttributesRetained definingPolygonAttributes = null; + + /** + * The LineAttributes for this RenderMolecule + */ + LineAttributesRetained definingLineAttributes = null; + + /** + * The PointAttributes for this RenderMolecule + */ + PointAttributesRetained definingPointAttributes = null; + + /** + * The TextureBin that this RenderMolecule resides + */ + TextureBin textureBin = null; + + /** + * The localToVworld for this RenderMolecule + */ + Transform3D[] localToVworld = null; + int[] localToVworldIndex = null; + + /** + * The Material reference for this RenderMolecule + */ + MaterialRetained definingMaterial = null; + + + /** + * The ColoringAttribute reference for this RenderMolecule + */ + ColoringAttributesRetained definingColoringAttributes = null; + + + /** + * The Transparency reference for this RenderMolecule + */ + TransparencyAttributesRetained definingTransparency = null; + + /** + * Transform3D - point to the right one based on bg or not + */ + Transform3D[] trans = null; + + + /** + * specify whether scale is nonuniform + */ + boolean isNonUniformScale = false; + + /** + * number of renderAtoms to be rendered in this RenderMolecule + */ + int numRenderAtoms = 0; + + /** + * number of render atoms, used during the renderBin update time + */ + int numEditingRenderAtoms = 0; + + RenderAtom addRAs = null; + RenderAtom removeRAs = null; + + /** + * The cached ColoringAttributes color value. It is + * 1.0, 1.0, 1.0 if there is no ColoringAttributes. + */ + float red = 1.0f; + float green = 1.0f; + float blue = 1.0f; + + + /** + * Cached diffuse color value + */ + float dRed = 1.0f; + float dGreen = 1.0f; + float dBlue = 1.0f; + + + + /** + * The cached TransparencyAttributes transparency value. It is + * 0.0 if there is no TransparencyAttributes. + */ + float alpha = 0.0f; + + /** + * The geometry type for this RenderMolecule + */ + int geometryType = -1; + + /** + * A boolean indicating whether or not lighting should be on. + */ + boolean enableLighting = false; + + /** + * A boolean indicating whether or not this molecule rendered Text3D + */ + + int primaryMoleculeType = 0; + static int COMPRESSED_MOLECULE = 0x1; + static int TEXT3D_MOLECULE = 0x2; + static int DLIST_MOLECULE = 0x4; + static int RASTER_MOLECULE = 0x8; + static int ORIENTEDSHAPE3D_MOLECULE = 0x10; + static int SEPARATE_DLIST_PER_RINFO_MOLECULE = 0x20; + + + /** + * Cached values for polygonMode, line antialiasing, and point antialiasing + */ + int polygonMode = PolygonAttributes.POLYGON_FILL; + boolean lineAA = false; + boolean pointAA = false; + + /** + * The vertex format for this RenderMolecule. Only looked + * at for GeometryArray and CompressedGeometry objects. + */ + int vertexFormat = -1; + + /** + * The texCoordSetMap length for this RenderMolecule. + */ + int texCoordSetMapLen = 0; + + /** + * The primary renderMethod object for this RenderMolecule + * this is either a Text3D, display list, or compressed geometry renderer. + */ + RenderMethod primaryRenderMethod = null; + + /** + * The secondary renderMethod object for this RenderMolecule + * this is used for geometry that is shared + */ + RenderMethod secondaryRenderMethod = null; + + /** + * The RenderBino for this molecule + */ + RenderBin renderBin = null; + + /** + * The references to the next and previous RenderMolecule in the + * list. + */ + RenderMolecule next = null; + RenderMolecule prev = null; + + + /** + * The list of RenderAtoms in this RenderMolecule that are not using + * vertex arrays. + */ + RenderAtomListInfo primaryRenderAtomList = null; + + + /** + * The list of RenderAtoms in this RenderMolecule that are using + * separte dlist . + */ + RenderAtomListInfo separateDlistRenderAtomList = null; + + + /** + * The list of RenderAtoms in this RenderMolecule that are using vertex + * arrays. + */ + RenderAtomListInfo vertexArrayRenderAtomList = null; + + /** + * This BoundingBox is used for View Frustum culling on the primary + * list + */ + BoundingBox vwcBounds = null; + + + /** + * If this is end of the linked list for this xform, then + * this field is non-null, if there is a map after this + */ + RenderMolecule nextMap = null; + RenderMolecule prevMap = null; + + /** + * If the any of the node component of the appearance in RM will be changed + * frequently, then confine it to a separate bin + */ + boolean soleUser = false; + Object appHandle = null; + + + VertexArrayRenderMethod cachedVertexArrayRenderMethod = + (VertexArrayRenderMethod) + VirtualUniverse.mc.getVertexArrayRenderMethod(); + + // In D3D separate Quad/Triangle Geometry with others in RenderMolecule + // Since we need to dynamically switch whether to use DisplayList + // or not in render() as a group. + boolean isQuadGeometryArray = false; + boolean isTriGeometryArray = false; + + // display list id, valid id starts from 1 + int displayListId = 0; + Integer displayListIdObj = null; + + int onUpdateList = 0; + static int NEW_RENDERATOMS_UPDATE = 0x1; + static int BOUNDS_RECOMPUTE_UPDATE = 0x2; + static int LOCALE_TRANSLATION = 0x4; + static int UPDATE_BACKGROUND_TRANSFORM = 0x8; + static int IN_DIRTY_RENDERMOLECULE_LIST = 0x10; + static int LOCALE_CHANGED = 0x20; + static int ON_UPDATE_CHECK_LIST = 0x40; + + + // background geometry rendering + boolean doInfinite; + Transform3D[] infLocalToVworld; + + // Whether alpha is used in this renderMolecule + boolean useAlpha = false; + + // Support for multiple locales + Locale locale = null; + + // Transform when locale is different from the view's locale + Transform3D[] localeLocalToVworld = null; + + // Vector used for locale translation + Vector3d localeTranslation = null; + + boolean primaryChanged = false; + + boolean isOpaqueOrInOG = true; + boolean inOrderedGroup = false; + + + // closest switch parent + SwitchRetained closestSwitchParent = null; + + // the child index from the closest switch parent + int closestSwitchIndex = -1; + + + RenderMolecule(GeometryAtom ga, + PolygonAttributesRetained polygonAttributes, + LineAttributesRetained lineAttributes, + PointAttributesRetained pointAttributes, + MaterialRetained material, + ColoringAttributesRetained coloringAttributes, + TransparencyAttributesRetained transparency, + RenderingAttributesRetained renderAttrs, + TextureUnitStateRetained[] texUnits, + Transform3D[] transform, int[] transformIndex, + RenderBin rb) { + renderBin = rb; + IndexedUnorderSet.init(this, TOTAL_INDEXED_UNORDER_SET_TYPES); + + reset(ga, polygonAttributes, lineAttributes, pointAttributes, + material, coloringAttributes, transparency, renderAttrs, + texUnits, transform, + transformIndex); + } + + void reset(GeometryAtom ga, + PolygonAttributesRetained polygonAttributes, + LineAttributesRetained lineAttributes, + PointAttributesRetained pointAttributes, + MaterialRetained material, + ColoringAttributesRetained coloringAttributes, + TransparencyAttributesRetained transparency, + RenderingAttributesRetained renderAttrs, + TextureUnitStateRetained[] texUnits, + Transform3D[] transform, int[] transformIndex) { + primaryMoleculeType = 0; + numRenderAtoms = 0; + numEditingRenderAtoms = 0; + onUpdateList = 0; + dirtyAttrsAcrossRms = ALL_DIRTY_BITS; + primaryRenderMethod = null; + isNonUniformScale = false; + primaryChanged = false; + this.material = material; + this.polygonAttributes = polygonAttributes; + this.lineAttributes = lineAttributes; + this.pointAttributes = pointAttributes; + this.coloringAttributes = coloringAttributes; + this.transparency = transparency; + + closestSwitchParent = ga.source.closestSwitchParent; + closestSwitchIndex = ga.source.closestSwitchIndex; + + // Find the first non-null geometey + GeometryRetained geo = null; + int k = 0; + isOpaqueOrInOG = true; + inOrderedGroup = false; + while (geo == null && (k < ga.geometryArray.length)) { + geo = ga.geometryArray[k]; + k++; + } + + // Issue 249 - check for sole user only if property is set + soleUser = false; + if (VirtualUniverse.mc.allowSoleUser) { + if (ga.source.appearance != null) { + soleUser = ((ga.source.appearance.changedFrequent & RM_COMPONENTS) != 0); + } + } + + // Set the appearance only for soleUser case + if (soleUser) + appHandle = ga.source.appearance; + else + appHandle = this; + + // If its of type GeometryArrayRetained + if (ga.geoType <= GeometryRetained.GEO_TYPE_GEOMETRYARRAY || + ga.geoType == GeometryRetained.GEO_TYPE_TEXT3D) { + + if (ga.source instanceof OrientedShape3DRetained) { + primaryRenderMethod = + VirtualUniverse.mc.getOrientedShape3DRenderMethod(); + primaryMoleculeType = ORIENTEDSHAPE3D_MOLECULE; + } else if (ga.geoType == GeometryRetained.GEO_TYPE_TEXT3D) { + primaryRenderMethod = + VirtualUniverse.mc.getText3DRenderMethod(); + primaryMoleculeType = TEXT3D_MOLECULE; + } else { + // Make determination of dlist or not during addRenderAtom + secondaryRenderMethod = cachedVertexArrayRenderMethod; + } + } + else { + if (ga.geoType == GeometryRetained.GEO_TYPE_COMPRESSED) { + primaryRenderMethod = + VirtualUniverse.mc.getCompressedGeometryRenderMethod(); + primaryMoleculeType = COMPRESSED_MOLECULE; + } + else if (geo instanceof RasterRetained) { + primaryRenderMethod = + VirtualUniverse.mc.getDefaultRenderMethod(); + primaryMoleculeType = RASTER_MOLECULE; + } + } + + prev = null; + next = null; + prevMap = null; + nextMap = null; + + primaryRenderAtomList = null; + vertexArrayRenderAtomList = null; + + + + switch (ga.geoType) { + case GeometryRetained.GEO_TYPE_POINT_SET: + case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET: + this.geometryType = POINT; + break; + case GeometryRetained.GEO_TYPE_LINE_SET: + case GeometryRetained.GEO_TYPE_LINE_STRIP_SET: + case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET: + case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET: + this.geometryType = LINE; + break; + case GeometryRetained.GEO_TYPE_RASTER: + this.geometryType = RASTER; + break; + case GeometryRetained.GEO_TYPE_COMPRESSED: + this.geometryType = COMPRESSED; + + switch (((CompressedGeometryRetained)geo).getBufferType()) { + case CompressedGeometryHeader.POINT_BUFFER: + this.geometryType |= POINT ; + break ; + case CompressedGeometryHeader.LINE_BUFFER: + this.geometryType |= LINE ; + break ; + default: + case CompressedGeometryHeader.TRIANGLE_BUFFER: + this.geometryType |= SURFACE ; + if (polygonAttributes != null) { + if (polygonAttributes.polygonMode == + PolygonAttributes.POLYGON_POINT) { + this.geometryType |= POINT; + } else if (polygonAttributes.polygonMode == + PolygonAttributes.POLYGON_LINE) { + this.geometryType |= LINE; + } + } + break ; + } + break; + default: + this.geometryType = SURFACE; + if (polygonAttributes != null) { + if (polygonAttributes.polygonMode == + PolygonAttributes.POLYGON_POINT) { + this.geometryType |= POINT; + } else if (polygonAttributes.polygonMode == + PolygonAttributes.POLYGON_LINE) { + this.geometryType |= LINE; + } + } + break; + } + + isQuadGeometryArray = (geo.getClassType() == + GeometryRetained.QUAD_TYPE); + isTriGeometryArray = (geo.getClassType() == + GeometryRetained.TRIANGLE_TYPE); + + this.localToVworld = transform; + this.localToVworldIndex = transformIndex; + doInfinite = ga.source.inBackgroundGroup; + if (doInfinite) { + if (infLocalToVworld == null) { + infLocalToVworld = new Transform3D[2]; + infLocalToVworld[0] = infLocalToVworld[1] = new Transform3D(); + } + localToVworld[0].getRotation(infLocalToVworld[0]); + } + int mask = 0; + if (polygonAttributes != null) { + if (polygonAttributes.changedFrequent != 0) { + definingPolygonAttributes = polygonAttributes; + + mask |= POLYGONATTRS_DIRTY; + } + else { + if (definingPolygonAttributes != null) { + definingPolygonAttributes.set(polygonAttributes); + } + else { + definingPolygonAttributes = (PolygonAttributesRetained)polygonAttributes.clone(); + } + } + polygonMode = definingPolygonAttributes.polygonMode; + } else { + polygonMode = PolygonAttributes.POLYGON_FILL; + definingPolygonAttributes = null; + } + + if (lineAttributes != null) { + if (lineAttributes.changedFrequent != 0) { + definingLineAttributes = lineAttributes; + mask |= LINEATTRS_DIRTY; + } + else { + if (definingLineAttributes != null) { + definingLineAttributes.set(lineAttributes); + } + else { + definingLineAttributes = (LineAttributesRetained)lineAttributes.clone(); + } + } + lineAA = definingLineAttributes.lineAntialiasing; + } else { + lineAA = false; + definingLineAttributes = null; + } + + if (pointAttributes != null) { + if (pointAttributes.changedFrequent != 0) { + definingPointAttributes = pointAttributes; + mask |= POINTATTRS_DIRTY; + + } + else { + if (definingPointAttributes != null) { + definingPointAttributes.set(pointAttributes); + } + else { + definingPointAttributes = (PointAttributesRetained)pointAttributes.clone(); + } + } + pointAA = definingPointAttributes.pointAntialiasing; + } else { + pointAA = false; + definingPointAttributes = null; + } + + normalPresent = true; + if (geo instanceof GeometryArrayRetained) { + GeometryArrayRetained gr = (GeometryArrayRetained)geo; + this.vertexFormat = gr.vertexFormat; + + if (gr.texCoordSetMap != null) { + this.texCoordSetMapLen = gr.texCoordSetMap.length; + } else { + this.texCoordSetMapLen = 0; + } + + // Throw an exception if lighting is enabled, but no normals defined + if ((vertexFormat & GeometryArray.NORMALS) == 0) { + // Force lighting to false + normalPresent = false; + } + + } + else if (geo instanceof CompressedGeometryRetained) { + this.vertexFormat = + ((CompressedGeometryRetained)geo).getVertexFormat(); + // Throw an exception if lighting is enabled, but no normals defined + if ((vertexFormat & GeometryArray.NORMALS) == 0) { + // Force lighting to false + normalPresent = false; + } + + this.texCoordSetMapLen = 0; + + } else { + this.vertexFormat = -1; + this.texCoordSetMapLen = 0; + } + + if (material != null) { + if (material.changedFrequent != 0) { + definingMaterial = material; + mask |= MATERIAL_DIRTY; + } + else { + if (definingMaterial != null) + definingMaterial.set(material); + else { + definingMaterial = (MaterialRetained)material.clone(); + } + } + + } + else { + definingMaterial = null; + } + evalMaterialCachedState(); + if (coloringAttributes != null) { + if (coloringAttributes.changedFrequent != 0) { + definingColoringAttributes = coloringAttributes; + mask |= COLORINGATTRS_DIRTY; + } + else { + if (definingColoringAttributes != null) { + definingColoringAttributes.set(coloringAttributes); + } + else { + definingColoringAttributes = (ColoringAttributesRetained)coloringAttributes.clone(); + } + } + red = coloringAttributes.color.x; + green = coloringAttributes.color.y; + blue = coloringAttributes.color.z; + } else { + red = 1.0f; + green = 1.0f; + blue = 1.0f; + definingColoringAttributes = null; + } + + if (transparency != null) { + + if (transparency.changedFrequent != 0) { + definingTransparency = transparency; + mask |= TRANSPARENCY_DIRTY; + } + else { + if (definingTransparency != null) { + definingTransparency.set(transparency); + } + else { + definingTransparency = + (TransparencyAttributesRetained)transparency.clone(); + } + } + alpha = 1.0f - transparency.transparency; + + } else { + alpha = 1.0f; + definingTransparency = null; + + } + + locale = ga.source.locale; + if (locale != renderBin.locale) { + if (localeLocalToVworld == null) { + localeLocalToVworld = new Transform3D[2]; + } + localeLocalToVworld[0] = new Transform3D(); + localeLocalToVworld[1] = new Transform3D(); + localeTranslation = new Vector3d(); + ga.locale.hiRes.difference(renderBin.locale.hiRes, localeTranslation); + translate(); + } + else { + localeLocalToVworld = localToVworld; + } + + if (doInfinite) { + trans = infLocalToVworld; + } + else { + trans = localeLocalToVworld; + } + + evalAlphaUsage(renderAttrs, texUnits); + isOpaqueOrInOG = isOpaque() || (ga.source.orderedPath != null); + inOrderedGroup = (ga.source.orderedPath != null); + // System.err.println("isOpaque = "+isOpaque() +" OrInOG = "+isOpaqueOrInOG); + if (mask != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= mask; + } + } + + + /** + * This tests if the given attributes matches this TextureBin + */ + boolean equals(RenderAtom ra, + PolygonAttributesRetained polygonAttributes, + LineAttributesRetained lineAttributes, + PointAttributesRetained pointAttributes, + MaterialRetained material, + ColoringAttributesRetained coloringAttributes, + TransparencyAttributesRetained transparency, + Transform3D[] transform) { + int geoType = 0; + GeometryAtom ga = ra.geometryAtom; + + if (this.localToVworld != transform) { + return (false); + } + + if (locale != ra.geometryAtom.source.locale) { + return (false); + } + + if (ra.geometryAtom.source.closestSwitchParent != closestSwitchParent || + ra.geometryAtom.source.closestSwitchIndex != closestSwitchIndex) { + return (false); + } + + // Find the first non-null geometey + GeometryRetained geo = null; + int k = 0; + while (geo == null && (k < ga.geometryArray.length)) { + geo = ga.geometryArray[k]; + k++; + } + + // XXXX: Add tags + switch (ga.geoType) { + case GeometryRetained.GEO_TYPE_POINT_SET: + case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET: + geoType = POINT; + break; + case GeometryRetained.GEO_TYPE_LINE_SET: + case GeometryRetained.GEO_TYPE_LINE_STRIP_SET: + case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET: + case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET: + geoType = LINE; + break; + case GeometryRetained.GEO_TYPE_RASTER: + geoType = RASTER; + break; + case GeometryRetained.GEO_TYPE_COMPRESSED: + geoType = COMPRESSED; + switch (((CompressedGeometryRetained)geo).getBufferType()) { + case CompressedGeometryHeader.POINT_BUFFER: + geoType |= POINT ; + break ; + case CompressedGeometryHeader.LINE_BUFFER: + geoType |= LINE ; + break ; + default: + case CompressedGeometryHeader.TRIANGLE_BUFFER: + geoType |= SURFACE ; + break ; + } + break; + default: + geoType = SURFACE; + if (polygonAttributes != null) { + if (polygonAttributes.polygonMode == + PolygonAttributes.POLYGON_POINT) { + geoType |= POINT; + } else if (polygonAttributes.polygonMode == + PolygonAttributes.POLYGON_LINE) { + geoType |= LINE; + } + } + break; + } + + if (this.geometryType != geoType) { + return (false); + } + /* + // XXXX : Check this + if (useDisplayList && + (ga.geometry.isEditable || + ga.geometry.refCount > 1 || + ((GroupRetained)ga.source.parent).switchLevel >= 0 || + ga.alphaEditable)) { + return (false); + } + */ + if (ga.geoType == GeometryRetained.GEO_TYPE_TEXT3D && + primaryMoleculeType != 0 && + ((primaryMoleculeType & TEXT3D_MOLECULE) == 0)) { + return (false); + } + + + if(!(ra.geometryAtom.source instanceof OrientedShape3DRetained) + && ((primaryMoleculeType & ORIENTEDSHAPE3D_MOLECULE) != 0)) { + //System.err.println("RA's NOT a OrientedShape3DRetained and RM is a ORIENTEDSHAPE3D_MOLECULE "); + + return (false); + } + + // 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; + if (this.vertexFormat != gr.vertexFormat) { + return (false); + } + + + // we are requiring that texCoordSetMap length to be the same + // so that we can either put all multi-tex ga to a display list, + // or punt all to vertex array. And we don't need to worry + // about some of the ga can be in display list for this canvas, + // and some other can be in display list for the other canvas. + if (((gr.texCoordSetMap != null) && + (this.texCoordSetMapLen != gr.texCoordSetMap.length)) || + ((gr.texCoordSetMap == null) && (this.texCoordSetMapLen != 0))) { + return (false); + } + + } else if (geo instanceof CompressedGeometryRetained) { + if (this.vertexFormat != + ((CompressedGeometryRetained)geo).getVertexFormat()) { + return (false); + } + } else { + //XXXX: compare isEditable + if (this.vertexFormat != -1) { + return (false); + } + } + + // 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 & RM_COMPONENTS) != 0))) { + if (appHandle == ra.geometryAtom.source.appearance) { + + // if this RenderMolecule is currently on a zombie state, + // we'll need to put it on the update list to reevaluate + // the state, because while it is on a zombie state, + // state could have been changed. Example, + // application could have detached an appearance, + // made changes to the appearance state, and then + // reattached the appearance. In this case, the + // changes would not have reflected to the RenderMolecule + + if (numEditingRenderAtoms == 0) { + + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= ALL_DIRTY_BITS; + } + return true; + } + else { + return false; + } + + } + // Assign the cloned value as the original value + + // Either a changedFrequent or a null case + // and the incoming one is not equal or null + // then return; + // This check also handles null == null case + if (definingPolygonAttributes != null) { + if ((this.definingPolygonAttributes.changedFrequent != 0) || + (polygonAttributes !=null && polygonAttributes.changedFrequent != 0)) + if (definingPolygonAttributes == polygonAttributes) { + if (definingPolygonAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= POLYGONATTRS_DIRTY; + } + } + else { + return false; + } + else if (!definingPolygonAttributes.equivalent(polygonAttributes)) { + return false; + } + } + else if (polygonAttributes != null) { + return false; + } + + if (definingLineAttributes != null) { + if ((this.definingLineAttributes.changedFrequent != 0) || + (lineAttributes !=null && lineAttributes.changedFrequent != 0)) + if (definingLineAttributes == lineAttributes) { + if (definingLineAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= LINEATTRS_DIRTY; + } + } + else { + return false; + } + else if (!definingLineAttributes.equivalent(lineAttributes)) { + return false; + } + } + else if (lineAttributes != null) { + return false; + } + + + if (definingPointAttributes != null) { + if ((this.definingPointAttributes.changedFrequent != 0) || + (pointAttributes !=null && pointAttributes.changedFrequent != 0)) + if (definingPointAttributes == pointAttributes) { + if (definingPointAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= POINTATTRS_DIRTY; + } + } + else { + return false; + } + else if (!definingPointAttributes.equivalent(pointAttributes)) { + return false; + } + } + else if (pointAttributes != null) { + return false; + } + + + + + if (definingMaterial != null) { + if ((this.definingMaterial.changedFrequent != 0) || + (material !=null && material.changedFrequent != 0)) + if (definingMaterial == material) { + if (definingMaterial.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= MATERIAL_DIRTY; + } + } + else { + return false; + } + else if (!definingMaterial.equivalent(material)) { + return false; + } + } + else if (material != null) { + return false; + } + + + + if (definingColoringAttributes != null) { + if ((this.definingColoringAttributes.changedFrequent != 0) || + (coloringAttributes !=null && coloringAttributes.changedFrequent != 0)) + if (definingColoringAttributes == coloringAttributes) { + if (definingColoringAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= COLORINGATTRS_DIRTY; + } + } + else { + return false; + } + else if (!definingColoringAttributes.equivalent(coloringAttributes)) { + return false; + } + } + else if (coloringAttributes != null) { + return false; + } + + // if the definingTransparency is a non cloned values and the incoming + // one is equivalent, then check if the component is dirty + // this happens when all the RAs from this RM have been removed + // but new ones are not added yet (rbin visibility) not run yet + // and when there is a change in nc based on the new RA, we wil; + // miss the change, doing this check will catch the change durin + // new RAs insertRenderAtom + if (definingTransparency != null) { + if ((this.definingTransparency.changedFrequent != 0) || + (transparency !=null && transparency.changedFrequent != 0)) + if (definingTransparency == transparency) { + if (definingTransparency.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= TRANSPARENCY_DIRTY; + } + } + else { + return false; + } + else if (!definingTransparency.equivalent(transparency)) { + return false; + } + } + else if (transparency != null) { + return false; + } + + return (true); + } + + public void updateRemoveRenderAtoms() { + RenderAtom r; + RenderAtomListInfo rinfo; + + // Check if this renderMolecule was created and destroyed this frame. + // so, no display list was created + if (numRenderAtoms == 0 && removeRAs == null && addRAs == null) { + textureBin.removeRenderMolecule(this); + return; + } + + while (removeRAs != null) { + r = removeRAs; + r.removed = null; + numRenderAtoms--; + + // Loop thru all geometries in the renderAtom, they could + // potentially be in different buckets in the rendermoleulce + for (int index = 0; index < r.rListInfo.length; index++) { + rinfo = r.rListInfo[index]; + // Don't remove null geo + if (rinfo.geometry() == null) + continue; + + if ((rinfo.groupType & RenderAtom.PRIMARY) != 0) { + primaryChanged = true; + if (rinfo.prev == null) { // At the head of the list + primaryRenderAtomList = rinfo.next; + if (rinfo.next != null) { + rinfo.next.prev = null; + } + } else { // In the middle or at the end. + rinfo.prev.next = rinfo.next; + if (rinfo.next != null) { + rinfo.next.prev = rinfo.prev; + } + } + + // If the molecule type is Raster, then add it to the lock list + if (primaryMoleculeType == RASTER) { + RasterRetained geo = (RasterRetained)rinfo.geometry(); + renderBin.removeGeometryFromLockList(geo); + if (geo.image != null) + renderBin.removeNodeComponent(geo.image); + + } + else if ((rinfo.groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0) { + if (!rinfo.renderAtom.inRenderBin()) { + renderBin.removeDlistPerRinfo.add(rinfo); + } + } + } + else if ((rinfo.groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0) { + if (rinfo.prev == null) { // At the head of the list + separateDlistRenderAtomList = rinfo.next; + if (rinfo.next != null) { + rinfo.next.prev = null; + } + } else { // In the middle or at the end. + rinfo.prev.next = rinfo.next; + if (rinfo.next != null) { + rinfo.next.prev = rinfo.prev; + } + } + renderBin.removeGeometryDlist(rinfo); + + } + else { + if (rinfo.prev == null) { // At the head of the list + vertexArrayRenderAtomList = rinfo.next; + if (rinfo.next != null) { + rinfo.next.prev = null; + } + } else { // In the middle or at the end. + rinfo.prev.next = rinfo.next; + if (rinfo.next != null) { + rinfo.next.prev = rinfo.prev; + } + } + // For indexed geometry there is no need to lock since + // the mirror is changed only when the renderer is not + // running + // For indexed geometry, if use_coord is set, then either we + // are using the index geometry as is or we will be unindexifying + // on the fly, so its better to lock + GeometryArrayRetained geo = (GeometryArrayRetained)rinfo.geometry(); + if (!(geo instanceof IndexedGeometryArrayRetained) || + ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) { + renderBin.removeGeometryFromLockList(geo); + } + } + rinfo.prev = null; + rinfo.next = null; + } + removeRAs = removeRAs.nextRemove; + r.nextRemove = null; + r.prevRemove = null; + if (r.isOriented()) { + renderBin.orientedRAs.remove(r); + } + + if ((textureBin.environmentSet.lightBin.geometryBackground == null) && + !isOpaqueOrInOG && renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) { + renderBin.removeTransparentObject(r); + } + } + // If this renderMolecule will not be touched for adding new RenderAtoms + // then .. + if (addRAs == null) { + // If there are no more renderAtoms and there will be no more + // renderatoms added to this renderMolecule , then remove + if (numRenderAtoms == 0) { + // If both lists are empty remove this renderMolecule + if ((primaryMoleculeType &DLIST_MOLECULE) != 0) { + renderBin.addDisplayListResourceFreeList(this); + vwcBounds.set(null); + displayListId = 0; + displayListIdObj = null; + } + if (locale != renderBin.locale) { + localeLocalToVworld = null; + } + textureBin.removeRenderMolecule(this); + } else { + if ((primaryMoleculeType &DLIST_MOLECULE) != 0 && primaryChanged) { + + // If a renderAtom is added to the display list + // structure then add this to the dirty list of rm + // for which the display list needs to be recreated + renderBin.addDirtyRenderMolecule(this); + vwcBounds.set(null); + rinfo = primaryRenderAtomList; + while (rinfo != null) { + vwcBounds.combine(rinfo.renderAtom.localeVwcBounds); + rinfo = rinfo.next; + } + primaryChanged = false; + } + } + } + numEditingRenderAtoms = numRenderAtoms; + } + + @Override + public void updateObject() { + int i; + RenderAtom renderAtom; + RenderAtomListInfo r; + if (textureBin == null) { + return; + } + + if (addRAs != null) { + while (addRAs != null) { + + numRenderAtoms++; + renderAtom = addRAs; + renderAtom.renderMolecule = this; + renderAtom.added = null; + for (int j = 0; j < renderAtom.rListInfo.length; j++) { + r = renderAtom.rListInfo[j]; + // Don't add null geo + if (r.geometry() == null) + continue; + r.groupType = evalRinfoGroupType(r); + if ((r.groupType & RenderAtom.PRIMARY) != 0) { + if ((r.groupType & RenderAtom.DLIST) != 0 && primaryRenderMethod == null) { + primaryMoleculeType = DLIST_MOLECULE; + renderBin.renderMoleculeList.add(this); + + if (vwcBounds == null) + vwcBounds = new BoundingBox((BoundingBox)null); + primaryRenderMethod = + VirtualUniverse.mc.getDisplayListRenderMethod(); + // Assign a displayListId for this renderMolecule + if (displayListId == 0) { + displayListIdObj = VirtualUniverse.mc.getDisplayListId(); + displayListId = displayListIdObj.intValue(); + } + } + else if ((r.groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0 && + primaryRenderMethod == null) { + primaryMoleculeType = SEPARATE_DLIST_PER_RINFO_MOLECULE; + renderBin.renderMoleculeList.add(this); + primaryRenderMethod = + VirtualUniverse.mc.getDisplayListRenderMethod(); + + } + primaryChanged = true; + if (primaryRenderAtomList == null) { + primaryRenderAtomList = r; + } + else { + r.next = primaryRenderAtomList; + primaryRenderAtomList.prev = r; + primaryRenderAtomList = r; + } + if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) { + if (r.renderAtom.dlistIds == null) { + r.renderAtom.dlistIds = new int[r.renderAtom.rListInfo.length]; + + for (int k = 0; k < r.renderAtom.dlistIds.length; k++) { + r.renderAtom.dlistIds[k] = -1; + } + } + if (r.renderAtom.dlistIds[r.index] == -1) { + r.renderAtom.dlistIds[r.index] = VirtualUniverse.mc.getDisplayListId().intValue(); + renderBin.addDlistPerRinfo.add(r); + } + } + + // If the molecule type is Raster, then add it to the lock list + if (primaryMoleculeType == RASTER) { + RasterRetained geo = (RasterRetained)r.geometry(); + renderBin.addGeometryToLockList(geo); + if (geo.image != null) + renderBin.addNodeComponent(geo.image); + } + } + else if ((r.groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0) { + if (separateDlistRenderAtomList == null) { + separateDlistRenderAtomList = r; + } + else { + r.next = separateDlistRenderAtomList; + separateDlistRenderAtomList.prev = r; + separateDlistRenderAtomList = r; + } + ((GeometryArrayRetained)r.geometry()).assignDlistId(); + renderBin.addGeometryDlist(r); + } + else { + if (secondaryRenderMethod == null) + secondaryRenderMethod = cachedVertexArrayRenderMethod; + if (vertexArrayRenderAtomList == null) { + vertexArrayRenderAtomList = r; + } + else { + r.next = vertexArrayRenderAtomList; + vertexArrayRenderAtomList.prev = r; + vertexArrayRenderAtomList = r; + } + // For indexed geometry there is no need to lock since + // the mirror is changed only when the renderer is not + // running + // For indexed geometry, if use_coord is set, then either we + // are using the index geometry as is or we will be unindexifying + // on the fly, so its better to loc + GeometryArrayRetained geo = (GeometryArrayRetained)r.geometry(); + if (!(geo instanceof IndexedGeometryArrayRetained) || + ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) { + renderBin.addGeometryToLockList(geo); + // Add the geometry to the dirty list only if the geometry is by + // refernce and there is color and we need to use alpha + // Issue 113 - ignore multiScreen + if ((( geo.vertexFormat & GeometryArray.BY_REFERENCE)!=0) && + (geo.c4fAllocated == 0) && + ((geo.vertexFormat & GeometryArray.COLOR) != 0) && + useAlpha) { + renderBin.addDirtyReferenceGeometry(geo); + } + } + } + } + addRAs = addRAs.nextAdd; + renderAtom.nextAdd = null; + renderAtom.prevAdd = null; + if (renderAtom.isOriented()) { + renderBin.orientedRAs.add(renderAtom); + + } + // If transparent and not in bg geometry and is depth sorted transparency + if (!isOpaqueOrInOG && (textureBin.environmentSet.lightBin.geometryBackground == null)&& + (renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY)) { + GeometryRetained geo = null; + int k = 0; + while (geo == null && k < renderAtom.rListInfo.length) { + geo = renderAtom.rListInfo[k].geometry(); + k++; + } + if (geo != null) { + if (renderAtom.parentTInfo != null && renderAtom.parentTInfo[k-1] != null) { + renderBin.updateTransparentInfo(renderAtom); + } + // Newly added renderAtom + else { + renderBin.addTransparentObject(renderAtom); + } + } + // Moving within the renderBin + + } + } + + if ((primaryMoleculeType &DLIST_MOLECULE) != 0 && primaryChanged) { + + // If a renderAtom is added to the display list + // structure then add this to the dirty list of rm + // for which the display list needs to be recreated + renderBin.addDirtyRenderMolecule(this); + vwcBounds.set(null); + r = primaryRenderAtomList; + while (r != null) { + vwcBounds.combine(r.renderAtom.localeVwcBounds); + r = r.next; + } + primaryChanged = false; + } + + + if ((onUpdateList & LOCALE_CHANGED) != 0) { + handleLocaleChange(); + } + + if (locale != renderBin.locale) { + translate(); + } + } + else { + // The flag LOCALE_CHANGED only gets sets when there is a new additon + // There are cases when RM updateObject() get called (due to addition + // in renderBin - see processTransformChanged()), we need to + // evaluate locale change for this case as well + if (renderBin.localeChanged) { + handleLocaleChange(); + } + + if (locale != renderBin.locale) { + translate(); + } + + if ((onUpdateList & UPDATE_BACKGROUND_TRANSFORM) != 0) { + i = localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]; + localeLocalToVworld[i].getRotation(infLocalToVworld[i]); + } + + // No new renderAtoms were added, but need to + // recompute vwcBounds in response to xform change + if ((onUpdateList & BOUNDS_RECOMPUTE_UPDATE) != 0) { + vwcBounds.set(null); + r = primaryRenderAtomList; + while (r != null) { + vwcBounds.combine(r.renderAtom.localeVwcBounds); + r = r.next; + } + } + } + + // Clear all bits except the IN_DIRTY_LIST + onUpdateList &= IN_DIRTY_RENDERMOLECULE_LIST; + + numEditingRenderAtoms = numRenderAtoms; + } + + boolean canBeInDisplayList(GeometryRetained geo, GeometryAtom ga) { + 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 + // put in a separate dlist that can be shared ... + final boolean geoNotAltered(GeometryArrayRetained geo) { + return !(((geo.vertexFormat & GeometryArray.COLOR) != 0) && + (textureBin.attributeBin.ignoreVertexColors || useAlpha)); + } + + int evalRinfoGroupType(RenderAtomListInfo r) { + int groupType = 0; + + GeometryRetained geo = r.geometry(); + if (geo == null) + return groupType; + + if ((primaryMoleculeType & (COMPRESSED_MOLECULE | + RASTER_MOLECULE | + TEXT3D_MOLECULE | + ORIENTEDSHAPE3D_MOLECULE)) != 0) { + groupType = RenderAtom.OTHER; + } + else if (canBeInDisplayList(geo, r.renderAtom.geometryAtom)) { + // if geometry is under share group we immediate set the + // dlistID to something other than -1 + if ( !((GeometryArrayRetained)geo).isShared || + // if we do a compiled and push the transform down to + // Geometry, we can't share the displayList + (r.renderAtom.geometryAtom.source.staticTransform != null)) { + // If the molecule is already defined to be SEPARATE_DLIST_PER_RINFO_MOLECULE + // continue adding in that mode even if it was switched back to + // no depth sorted mode + // System.err.println("isOpaqueOrInOG ="+isOpaqueOrInOG+" primaryMoleculeType ="+primaryMoleculeType+" renderBin.transpSortMode ="+renderBin.transpSortMode); + if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) { + groupType = RenderAtom.SEPARATE_DLIST_PER_RINFO; + } + else { + if (isOpaqueOrInOG || + renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE) { + groupType = RenderAtom.DLIST; + } + else { + groupType = RenderAtom.SEPARATE_DLIST_PER_RINFO; + } + } + + } else if (geoNotAltered((GeometryArrayRetained)r.geometry()) ) { + groupType = RenderAtom.SEPARATE_DLIST_PER_GEO; + } + else { + groupType = RenderAtom.VARRAY; + } + } + else { + groupType = RenderAtom.VARRAY; + } + return groupType; + } + + /** + * Adds the given RenderAtom to this RenderMolecule. + */ + void addRenderAtom(RenderAtom renderAtom, RenderBin rb) { + int i; + + renderAtom.envSet = textureBin.environmentSet; + renderAtom.renderMolecule = this; + renderAtom.dirtyMask &= ~RenderAtom.NEED_SEPARATE_LOCALE_VWC_BOUNDS; + + AppearanceRetained raApp = renderAtom.geometryAtom.source.appearance; + + MaterialRetained mat = (raApp == null)? null : raApp.material; + if (!soleUser && material != mat) { + // no longer sole user + material = definingMaterial; + } + + if ((geometryType & SURFACE) != 0) { + PolygonAttributesRetained pgAttrs = + (raApp == null)? null : raApp.polygonAttributes; + if (!soleUser && polygonAttributes != pgAttrs) { + // no longer sole user + polygonAttributes = definingPolygonAttributes; + } + + } + if ((geometryType & LINE) != 0) { + LineAttributesRetained lnAttrs = + (raApp == null)? null : raApp.lineAttributes; + if (!soleUser && lineAttributes != lnAttrs) { + // no longer sole user + lineAttributes = definingLineAttributes; + } + + } + if ((geometryType & POINT) != 0) { + PointAttributesRetained pnAttrs = + (raApp == null)? null : raApp.pointAttributes; + if (!soleUser && pointAttributes != pnAttrs) { + // no longer sole user + pointAttributes = definingPointAttributes; + } + } + + ColoringAttributesRetained coAttrs = + (raApp == null)? null : raApp.coloringAttributes; + if (!soleUser && coloringAttributes != coAttrs) { + // no longer sole user + coloringAttributes = definingColoringAttributes; + } + + TransparencyAttributesRetained trAttrs = + (raApp == null)? null : raApp.transparencyAttributes; + if (!soleUser && transparency != trAttrs) { + // no longer sole user + transparency = definingTransparency; + } + + + + // If the renderAtom is being inserted first time, then evaluate + // the groupType to determine if need separate localeVwcBounds + if (!renderAtom.inRenderBin()) { + for (i = 0; i < renderAtom.rListInfo.length; i++) { + if (renderAtom.rListInfo[i].geometry() == null) + continue; + int groupType = evalRinfoGroupType(renderAtom.rListInfo[i]); + if (groupType != RenderAtom.DLIST) { + renderAtom.dirtyMask |= RenderAtom.NEED_SEPARATE_LOCALE_VWC_BOUNDS; + } + } + } + if (renderAtom.removed == this) { + // Remove the renderAtom from the list of removeRAs + // If this is at the head of the list + if (renderAtom == removeRAs) { + removeRAs = renderAtom.nextRemove; + if (removeRAs != null) + removeRAs.prevRemove = null; + renderAtom.nextRemove = null; + renderAtom.prevRemove = null; + } + // Somewhere in the middle + else { + renderAtom.prevRemove.nextRemove = renderAtom.nextRemove; + if (renderAtom.nextRemove != null) + renderAtom.nextRemove.prevRemove = renderAtom.prevRemove; + renderAtom.nextRemove = null; + renderAtom.prevRemove = null; + } + + renderAtom.removed = null; + // Redo any dlist etc, because it has been added + for ( i = 0; i < renderAtom.rListInfo.length; i++) { + if (renderAtom.rListInfo[i].geometry() == null) + continue; + if ((renderAtom.rListInfo[i].groupType & RenderAtom.DLIST) != 0) + renderBin.addDirtyRenderMolecule(this); + else if ((renderAtom.rListInfo[i].groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0) { + renderBin.addDlistPerRinfo.add(renderAtom.rListInfo[i]); + } + else if ((renderAtom.rListInfo[i].groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0) + renderBin.addGeometryDlist(renderAtom.rListInfo[i]); + + } + if (removeRAs == null) + rb.removeRenderAtomInRMList.remove(this); + } + else { + // Add this renderAtom to the addList + if (addRAs == null) { + addRAs = renderAtom; + renderAtom.nextAdd = null; + renderAtom.prevAdd = null; + } + else { + renderAtom.nextAdd = addRAs; + renderAtom.prevAdd = null; + addRAs.prevAdd = renderAtom; + addRAs = renderAtom; + } + renderAtom.added = this; + if (onUpdateList == 0) + rb.objUpdateList.add(this); + onUpdateList |= NEW_RENDERATOMS_UPDATE; + + } + if (renderBin.localeChanged && !doInfinite) { + if (onUpdateList == 0) + rb.objUpdateList.add(this); + onUpdateList |= LOCALE_CHANGED; + } + + // inform the texture bin that this render molecule is no longer + // in zombie state + + if (numEditingRenderAtoms == 0) { + textureBin.incrActiveRenderMolecule(); + } + numEditingRenderAtoms++; + } + + /** + * Removes the given RenderAtom from this RenderMolecule. + */ + void removeRenderAtom(RenderAtom r) { + + r.renderMolecule = null; + if (r.added == this) { + //Remove this renderAtom from the addRAs list + + // If this is at the head of the list + if (r == addRAs) { + addRAs = r.nextAdd; + if (addRAs != null) + addRAs.prevAdd = null; + r.nextAdd = null; + r.prevAdd = null; + } + // Somewhere in the middle + else { + r.prevAdd.nextAdd = r.nextAdd; + if (r.nextAdd != null) + r.nextAdd.prevAdd = r.prevAdd; + r.nextAdd = null; + r.prevAdd = null; + } + + r.added = null; + r.envSet = null; + // If the number of renderAtoms is zero, and it is on the + // update list for adding new renderatroms only (not for + // bounds update), then remove this rm from the update list + + // Might be expensive to remove this entry from the renderBin + // objUpdateList, just let it call the renderMolecule + /* + if (addRAs == null) { + if (onUpdateList == NEW_RENDERATOMS_UPDATE){ + renderBin.objUpdateList.remove(renderBin.objUpdateList.indexOf(this)); + } + onUpdateList &= ~NEW_RENDERATOMS_UPDATE; + } + */ + + } + else { + // Add this renderAtom to the remove list + if (removeRAs == null) { + removeRAs = r; + r.nextRemove = null; + r.prevRemove = null; + } + else { + r.nextRemove = removeRAs; + r.prevRemove = null; + removeRAs.prevRemove = r; + removeRAs = r; + } + r.removed = this; + } + + // Add it to the removeRenderAtom List , in case the renderMolecule + // needs to be removed + if (!renderBin.removeRenderAtomInRMList.contains(this)) { + renderBin.removeRenderAtomInRMList.add(this); + } + + // decrement the number of editing render atoms in this render molecule + numEditingRenderAtoms--; + + // if there is no more editing render atoms, inform the texture bin + // that this render molecule is going to zombie state + + if (numEditingRenderAtoms == 0) { + textureBin.decrActiveRenderMolecule(); + } + } + + /** + * Recalculates the vwcBounds for a RenderMolecule + */ + void recalcBounds() { + RenderAtomListInfo ra; + + if (primaryRenderMethod == + VirtualUniverse.mc.getDisplayListRenderMethod()) { + vwcBounds.set(null); + ra = primaryRenderAtomList; + while (ra != null) { + vwcBounds.combine(ra.renderAtom.localeVwcBounds); + ra = ra.next; + } + } + } + + void evalAlphaUsage(RenderingAttributesRetained renderAttrs, + TextureUnitStateRetained[] texUnits) { + boolean alphaBlend, alphaTest, textureBlend = false; + + alphaBlend = TransparencyAttributesRetained.useAlpha(definingTransparency); + + if (texUnits != null) { + for (int i = 0; + textureBlend == false && i < texUnits.length; + i++) { + if (texUnits[i] != null && + texUnits[i].texAttrs != null) { + textureBlend = textureBlend || + (texUnits[i].texAttrs.textureMode == + TextureAttributes.BLEND); + } + } + } + + alphaTest = + renderAttrs != null && renderAttrs.alphaTestFunction != RenderingAttributes.ALWAYS; + + boolean oldUseAlpha = useAlpha; + useAlpha = alphaBlend || alphaTest || textureBlend; + + if( !oldUseAlpha && useAlpha) { + GeometryArrayRetained geo = null; + + if(vertexArrayRenderAtomList != null) + geo = (GeometryArrayRetained)vertexArrayRenderAtomList.geometry(); + + if(geo != null) { + if (!(geo instanceof IndexedGeometryArrayRetained) || + ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) { + renderBin.addGeometryToLockList(geo); + // Add the geometry to the dirty list only if the geometry is by + // reference and there is color and we need to use alpha + // Issue 113 - ignore multiScreen + if ((( geo.vertexFormat & GeometryArray.BY_REFERENCE)!=0) && + (geo.c4fAllocated == 0) && + ((geo.vertexFormat & GeometryArray.COLOR) != 0) && + useAlpha) { + renderBin.addDirtyReferenceGeometry(geo); + } + } + } + } + } + + final boolean isSwitchOn() { + // The switchOn status of the entire RM can be determined + // by the switchOn status of any renderAtoms below. + // This is possible because renderAtoms generated from a common + // switch branch are placed in the same renderMolecule + if (primaryRenderAtomList != null) { + return primaryRenderAtomList.renderAtom.geometryAtom. + source.switchState.lastSwitchOn; + + } + + if (vertexArrayRenderAtomList != null) { + return vertexArrayRenderAtomList.renderAtom.geometryAtom. + source.switchState.lastSwitchOn; + + } + + if (separateDlistRenderAtomList != null) { + return separateDlistRenderAtomList.renderAtom.geometryAtom. + source.switchState.lastSwitchOn; + } + return false; + } + + /** + * Renders this RenderMolecule + */ + boolean render(Canvas3D cv, int pass, int dirtyBits) { + assert pass < 0; + + boolean isVisible = isSwitchOn(); + + if (!isVisible) { + return false; + } + + isVisible = false; + + // include this LightBin to the to-be-updated list in Canvas + cv.setStateToUpdate(Canvas3D.RENDERMOLECULE_BIT, this); + + boolean modeSupportDL = true; + isNonUniformScale = !trans[localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]].isCongruent(); + // We have to dynamically switch between using displaymode + // mode or not instead of decide in canBeInDisplayList(), + // since polygonAttribute can be change by editable Appearance + // or editable polygonAttribute which mode we can't take + // advantage of display list mode in many cases just because + // there are three special cases to handle. + + // Another case for punting to vertex array is if pass specifies + // something other than -1. That means, we are in the + // multi-texturing multi-pass case. Then we'll use vertex array + // instead. Or the length of the texCoordSetMap is greater than + // the number of texture units supported by the Canvas, then + // we'll have to punt to vertex array as well. + + if ((pass != TextureBin.USE_DISPLAYLIST) || + (texCoordSetMapLen > cv.maxTexCoordSets)) { + modeSupportDL = false; + } + + /* + System.err.println("texCoord " + texCoordSetMapLen + " " + + cv.maxTexCoordSets + " " + modeSupportDL); + + System.err.println("primaryMoleculeType = "+primaryMoleculeType+" primaryRenderAtomList ="+primaryRenderAtomList+" separateDlistRenderAtomList ="+separateDlistRenderAtomList+" vertexArrayRenderAtomList ="+vertexArrayRenderAtomList); + */ + // Send down the model view only once, if its not of type text + if ((primaryMoleculeType & (TEXT3D_MOLECULE| ORIENTEDSHAPE3D_MOLECULE)) == 0) { + + if (primaryRenderAtomList != null) { + if ((primaryRenderMethod != VirtualUniverse.mc.getDisplayListRenderMethod()) || + modeSupportDL) { + if (primaryMoleculeType != SEPARATE_DLIST_PER_RINFO_MOLECULE) { + + if (primaryRenderMethod.render(this, cv, primaryRenderAtomList,dirtyBits)) + isVisible = true; + } + else { + if (renderBin.dlistRenderMethod.renderSeparateDlistPerRinfo(this, cv, primaryRenderAtomList,dirtyBits)) + isVisible = true; + + } + } else { + if(cachedVertexArrayRenderMethod.render(this, cv, + primaryRenderAtomList, + dirtyBits)) { + isVisible = true; + } + } + } + } + else { // TEXT3D or ORIENTEDSHAPE3D + + if (primaryRenderAtomList != null) { + if(primaryRenderMethod.render(this, cv, primaryRenderAtomList, + dirtyBits)) { + isVisible = true; + } + } + } + + if (separateDlistRenderAtomList != null) { + if (modeSupportDL) { + if(renderBin.dlistRenderMethod.renderSeparateDlists(this, cv, + separateDlistRenderAtomList, + dirtyBits)) { + isVisible = true; + } + + } else { + if(cachedVertexArrayRenderMethod.render(this, cv, + separateDlistRenderAtomList, + dirtyBits)) { + isVisible = true; + } + } + + } + + // XXXX: In the case of independent primitives such as quads, + // it would still be better to call multi draw arrays + if (vertexArrayRenderAtomList != null) { + if(cachedVertexArrayRenderMethod.render(this, cv, + vertexArrayRenderAtomList, + dirtyBits)) { + isVisible = true; + } + } + return isVisible; + } + + void updateAttributes(Canvas3D cv, int dirtyBits) { + + + boolean setTransparency = false; + + // If this is a beginning of a frame OR diff. geometryType + // then reload everything for the first rendermolecule + // System.err.println("updateAttributes"); + int bitMask = geometryType | Canvas3D.MATERIAL_DIRTY| + Canvas3D.COLORINGATTRS_DIRTY| + Canvas3D.TRANSPARENCYATTRS_DIRTY; + + // If beginning of a frame then reload all the attributes + if ((cv.canvasDirty & bitMask) != 0) { + if ((geometryType & SURFACE) != 0) { + if (definingPolygonAttributes == null) { + cv.resetPolygonAttributes(cv.ctx); + } else { + definingPolygonAttributes.updateNative(cv.ctx); + } + cv.polygonAttributes = polygonAttributes; + } + if ((geometryType & LINE) != 0) { + if (definingLineAttributes == null) { + cv.resetLineAttributes(cv.ctx); + } else { + definingLineAttributes.updateNative(cv.ctx); + } + cv.lineAttributes = lineAttributes; + } + if ((geometryType & POINT) != 0) { + if (definingPointAttributes == null) { + cv.resetPointAttributes(cv.ctx); + } else { + definingPointAttributes.updateNative(cv.ctx); + } + cv.pointAttributes = pointAttributes; + } + + if (definingTransparency == null) { + cv.resetTransparency(cv.ctx, geometryType, + polygonMode, lineAA, pointAA); + } else { + definingTransparency.updateNative(cv.ctx, + alpha, geometryType, + polygonMode, lineAA, + pointAA); + } + cv.transparency = transparency; + + if (definingMaterial == null) { + cv.updateMaterial(cv.ctx, red, green, blue, alpha); + } else { + definingMaterial.updateNative(cv.ctx, + red, green, blue, alpha, + enableLighting); + } + cv.material = material; + cv.enableLighting = enableLighting; + + if (definingColoringAttributes == null) { + cv.resetColoringAttributes(cv.ctx, red, green, blue, + alpha, enableLighting); + } else { + definingColoringAttributes.updateNative(cv.ctx, + dRed, + dBlue, + dGreen,alpha, + enableLighting); + } + cv.coloringAttributes = coloringAttributes; + + // Use Object instead of AppearanceRetained class for + // state caching optimation for memory performance + cv.appHandle = appHandle; + } + + // assuming neighbor dirty bits ORing is implemented + // note that we need to set it to ALL_DIRTY at the + // begining of textureBin first and only do the ORing + // whenever encounter a non-visible rm + + else if (cv.renderMolecule != this && (dirtyBits != 0)) { + + // no need to download states if appHandle is the same + if (cv.appHandle != appHandle) { + + // Check if the attribute bundle in the canvas is the same + // as the attribute bundle in this renderMolecule + + if (cv.transparency != transparency && + (dirtyBits & TRANSPARENCY_DIRTY) != 0) { + setTransparency = true; + if (definingTransparency == null) { + + cv.resetTransparency(cv.ctx, geometryType, + polygonMode, lineAA, pointAA); + } else { + definingTransparency.updateNative(cv.ctx, alpha, + geometryType, polygonMode, + lineAA, pointAA); + } + cv.transparency = transparency; + } + + if (setTransparency || ((cv.enableLighting != enableLighting) || + (cv.material != material) && + (dirtyBits & MATERIAL_DIRTY) != 0)){ + if (definingMaterial == null) { + cv.updateMaterial(cv.ctx, red, green, blue, alpha); + } else { + definingMaterial.updateNative(cv.ctx, red, green, + blue, alpha, + enableLighting); + } + cv.material = material; + cv.enableLighting = enableLighting; + } + + if (((geometryType & SURFACE) != 0) && + cv.polygonAttributes != polygonAttributes && + (dirtyBits & POLYGONATTRS_DIRTY) != 0) { + + if (definingPolygonAttributes == null) { + cv.resetPolygonAttributes(cv.ctx); + } else { + definingPolygonAttributes.updateNative(cv.ctx); + } + cv.polygonAttributes = polygonAttributes; + } + + if (((geometryType & LINE) != 0) && + cv.lineAttributes != lineAttributes && + (dirtyBits & LINEATTRS_DIRTY) != 0) { + + if (definingLineAttributes == null) { + cv.resetLineAttributes(cv.ctx); + } else { + definingLineAttributes.updateNative(cv.ctx); + } + cv.lineAttributes = lineAttributes; + } + + if (((geometryType & POINT) != 0) && + cv.pointAttributes != pointAttributes && + (dirtyBits & POINTATTRS_DIRTY) != 0) { + + if (definingPointAttributes == null) { + cv.resetPointAttributes(cv.ctx); + } else { + definingPointAttributes.updateNative(cv.ctx); + } + cv.pointAttributes = pointAttributes; + } + + // Use Object instead of AppearanceRetained class for + // state caching optimation for memory performance + cv.appHandle = appHandle; + } + // no state caching for color attrs, which can also be + // changed by primitive with colors + if(setTransparency || ((dirtyBits & COLORINGATTRS_DIRTY) != 0)) { + + if (definingColoringAttributes == null) { + cv.resetColoringAttributes(cv.ctx, + red, green, blue, alpha, + enableLighting); + } else { + definingColoringAttributes.updateNative(cv.ctx, + dRed, + dBlue, + dGreen,alpha, + enableLighting); + + } + cv.coloringAttributes = coloringAttributes; + } + + } + + if ((primaryMoleculeType & (TEXT3D_MOLECULE| ORIENTEDSHAPE3D_MOLECULE)) == 0) { + /* System.err.println("updateAttributes setModelViewMatrix (1)"); */ + + Transform3D modelMatrix = + trans[localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]]; + + if (cv.modelMatrix != modelMatrix) { + /* System.err.println("updateAttributes setModelViewMatrix (2)"); */ + + cv.setModelViewMatrix(cv.ctx, cv.vworldToEc.mat, + modelMatrix); + } + } + + cv.canvasDirty &= ~bitMask; + cv.renderMolecule = this; + } + + void transparentSortRender(Canvas3D cv, int pass, TransparentRenderingInfo tinfo) { + assert pass < 0; + + Transform3D modelMatrix = + trans[localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]]; + + // include this LightBin to the to-be-updated list in Canvas + cv.setStateToUpdate(Canvas3D.RENDERMOLECULE_BIT, this); + + + boolean modeSupportDL = true; + + // We have to dynamically switch between using displaymode + // mode or not instead of decide in canBeInDisplayList(), + // since polygonAttribute can be change by editable Appearance + // or editable polygonAttribute which mode we can't take + // advantage of display list mode in many cases just because + // there are three special cases to handle. + + // Another case for punting to vertex array is if pass specifies + // something other than -1. That means, we are in the + // multi-texturing multi-pass case. Then we'll use vertex array + // instead. + + if ((pass != TextureBin.USE_DISPLAYLIST) || + (texCoordSetMapLen > cv.maxTexCoordSets)) { + modeSupportDL = false; + } + + // System.err.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 + // 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 + tinfo.rInfo.next = null; + // System.err.println("cachedVertexArrayRenderMethod = "+cachedVertexArrayRenderMethod); + // System.err.println("tinfo.rInfo = "+tinfo.rInfo); + if (modeSupportDL) { + renderBin.dlistRenderMethod.renderSeparateDlistPerRinfo(this, cv, + tinfo.rInfo, + ALL_DIRTY_BITS); + } + else { + cachedVertexArrayRenderMethod.render(this, cv, tinfo.rInfo,ALL_DIRTY_BITS); + } + tinfo.rInfo.next = save; + } + else if ((tinfo.rInfo.groupType & (RenderAtom.VARRAY| RenderAtom.DLIST)) != 0) { + RenderAtomListInfo save= tinfo.rInfo.next; + // Render only one geometry + tinfo.rInfo.next = null; + // System.err.println("cachedVertexArrayRenderMethod = "+cachedVertexArrayRenderMethod); + // System.err.println("tinfo.rInfo = "+tinfo.rInfo); + cachedVertexArrayRenderMethod.render(this, cv, tinfo.rInfo, + ALL_DIRTY_BITS); + tinfo.rInfo.next = save; + } + + // Only support individual dlist or varray + else if ((tinfo.rInfo.groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0) { + RenderAtomListInfo save= tinfo.rInfo.next; + tinfo.rInfo.next = null; + if (modeSupportDL) { + renderBin.dlistRenderMethod.renderSeparateDlists(this, cv, + tinfo.rInfo, + ALL_DIRTY_BITS); + } + else { + cachedVertexArrayRenderMethod.render(this, cv, tinfo.rInfo, + ALL_DIRTY_BITS); + } + tinfo.rInfo.next = save; + } + else { + RenderAtomListInfo save= tinfo.rInfo.next; + primaryRenderMethod.render(this, cv, primaryRenderAtomList, + ALL_DIRTY_BITS); + tinfo.rInfo.next = save; + } + + } + + + /** + * This render method is used to render the transparency attributes. + * It is used in the multi-texture multi-pass case to reset the + * transparency attributes to what it was + */ + void updateTransparencyAttributes(Canvas3D cv) { + if (definingTransparency == null) { + cv.resetTransparency(cv.ctx, geometryType, polygonMode, + lineAA, pointAA); + } else { + definingTransparency.updateNative(cv.ctx, alpha, geometryType, + polygonMode, lineAA, pointAA); + } + } + + void updateDisplayList(Canvas3D cv) { + // This function only gets called when primaryRenderAtomsList are + if (primaryRenderAtomList != null) { + ((DisplayListRenderMethod)primaryRenderMethod).buildDisplayList(this, cv); + } + } + + void releaseAllPrimaryDisplayListID() { + + if (primaryRenderAtomList != null) { + if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) { + RenderAtomListInfo ra = primaryRenderAtomList; + int id; + + while (ra != null) { + id = ra.renderAtom.dlistIds[ra.index]; + + if (id > 0) { + VirtualUniverse.mc.freeDisplayListId(new Integer(id)); + ra.renderAtom.dlistIds[ra.index] = -1; + } + ra = ra.next; + } + } + else if (primaryMoleculeType == DLIST_MOLECULE) { + if (displayListIdObj != null) { + VirtualUniverse.mc.freeDisplayListId(displayListIdObj); + displayListIdObj = null; + displayListId = -1; + } + } + } + + } + + void releaseAllPrimaryDisplayListResources(Canvas3D cv, Context ctx) { + if (primaryRenderAtomList != null) { + if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) { + RenderAtomListInfo ra = primaryRenderAtomList; + int id; + while (ra != null) { + id = ra.renderAtom.dlistIds[ra.index]; + if (id > 0) { + Canvas3D.freeDisplayList(ctx, id); + } + ra = ra.next; + } + } + else if (primaryMoleculeType == DLIST_MOLECULE) { + if (displayListId > 0) { + Canvas3D.freeDisplayList(ctx, displayListId); + } + } + } + } + + void updateAllPrimaryDisplayLists(Canvas3D cv) { + // This function only gets called when primaryRenderAtomsList are + if (primaryRenderAtomList != null) { + if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) { + RenderAtomListInfo ra = primaryRenderAtomList; + while (ra != null) { + renderBin.dlistRenderMethod.buildDlistPerRinfo(ra, this, cv); + ra = ra.next; + } + } + else if(primaryMoleculeType == DLIST_MOLECULE) { + ((DisplayListRenderMethod)primaryRenderMethod).buildDisplayList(this, cv); + } + } + } + + void checkEquivalenceWithBothNeighbors(int dirtyBits) { + dirtyAttrsAcrossRms = ALL_DIRTY_BITS; + + if (prev != null) { + checkEquivalenceWithLeftNeighbor(prev, dirtyBits); + } + if (next != null) { + next.checkEquivalenceWithLeftNeighbor(this, dirtyBits); + } + } + + boolean reloadColor(RenderMolecule rm) { + if (((rm.vertexFormat & GeometryArray.COLOR) == 0) || + (((rm.vertexFormat & GeometryArray.COLOR) != 0) && + (vertexFormat & GeometryArray.COLOR) != 0)) { + return false; + } + return true; + } + + void checkEquivalenceWithLeftNeighbor(RenderMolecule rm, int dirtyBits) { + boolean reload_color = reloadColor(rm); + // XXXX : For now ignore the dirtyBits being sent in + dirtyAttrsAcrossRms = ALL_DIRTY_BITS ; + + + + // There is some interdepenency between the different components + // in the way it is sent down to the native code + // Material is affected by transparency and coloring attrs + // Transparency is affected by poly/line/pointAA + // ColoringAttrs is affected by material and transaparency + int materialColoringDirty = (MATERIAL_DIRTY | + TRANSPARENCY_DIRTY | + COLORINGATTRS_DIRTY); + + int transparencyDirty = (TRANSPARENCY_DIRTY| + POLYGONATTRS_DIRTY | + LINEATTRS_DIRTY | + POINTATTRS_DIRTY); + + if ((dirtyAttrsAcrossRms & POLYGONATTRS_DIRTY) != 0) { + if (rm.geometryType == geometryType && + (rm.polygonAttributes == polygonAttributes || + ((rm.definingPolygonAttributes != null) && + (rm.definingPolygonAttributes.equivalent(definingPolygonAttributes))))) + dirtyAttrsAcrossRms &= ~POLYGONATTRS_DIRTY; + + } + + if ((dirtyAttrsAcrossRms & POINTATTRS_DIRTY) != 0) { + if (rm.geometryType == geometryType && + ((rm.pointAttributes == pointAttributes) || + ((rm.definingPointAttributes != null) && + (rm.definingPointAttributes.equivalent(definingPointAttributes))))) + dirtyAttrsAcrossRms &= ~POINTATTRS_DIRTY; + + } + + if ((dirtyAttrsAcrossRms & LINEATTRS_DIRTY) != 0) { + if (rm.geometryType == geometryType && + ((rm.lineAttributes == lineAttributes) || + ((rm.definingLineAttributes != null) && + (rm.definingLineAttributes.equivalent(definingLineAttributes))))) + dirtyAttrsAcrossRms &= ~LINEATTRS_DIRTY; + } + + if ((dirtyAttrsAcrossRms & materialColoringDirty) != 0) { + if (materialEquivalent(rm, reload_color)) { + dirtyAttrsAcrossRms &= ~MATERIAL_DIRTY; + } + else { + dirtyAttrsAcrossRms |= MATERIAL_DIRTY; + } + } + + + + + if ((dirtyAttrsAcrossRms & materialColoringDirty) != 0) { + if (coloringEquivalent(rm, reload_color)) { + dirtyAttrsAcrossRms &= ~COLORINGATTRS_DIRTY; + } + else { + dirtyAttrsAcrossRms |= COLORINGATTRS_DIRTY; + } + } + + if ((dirtyAttrsAcrossRms & transparencyDirty) != 0) { + if (transparencyEquivalent(rm)) { + dirtyAttrsAcrossRms &= ~TRANSPARENCY_DIRTY; + } + else { + dirtyAttrsAcrossRms |= TRANSPARENCY_DIRTY; + } + } + } + void translate() { + // System.err.println("onUpdateList = "+onUpdateList+" renderBin.localeChanged = "+renderBin.localeChanged+" rm = "+this); + int i = localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]; + + localeLocalToVworld[i].mat[0] = localToVworld[i].mat[0]; + localeLocalToVworld[i].mat[1] = localToVworld[i].mat[1]; + localeLocalToVworld[i].mat[2] = localToVworld[i].mat[2]; + localeLocalToVworld[i].mat[3] = localToVworld[i].mat[3] + localeTranslation.x ; + localeLocalToVworld[i].mat[4] = localToVworld[i].mat[4]; + localeLocalToVworld[i].mat[5] = localToVworld[i].mat[5]; + localeLocalToVworld[i].mat[6] = localToVworld[i].mat[6]; + localeLocalToVworld[i].mat[7] = localToVworld[i].mat[7]+ localeTranslation.y; + localeLocalToVworld[i].mat[8] = localToVworld[i].mat[8]; + localeLocalToVworld[i].mat[9] = localToVworld[i].mat[9]; + localeLocalToVworld[i].mat[10] = localToVworld[i].mat[10]; + localeLocalToVworld[i].mat[11] = localToVworld[i].mat[11]+ localeTranslation.z; + localeLocalToVworld[i].mat[12] = localToVworld[i].mat[12]; + localeLocalToVworld[i].mat[13] = localToVworld[i].mat[13]; + localeLocalToVworld[i].mat[14] = localToVworld[i].mat[14]; + localeLocalToVworld[i].mat[15] = localToVworld[i].mat[15]; + // System.err.println("rm = "+this+" localTovworld = "+localeLocalToVworld[i]+" localeTranslation = "+localeTranslation); + } + + + boolean isOpaque() { + if ((geometryType & SURFACE) != 0) { + if (definingPolygonAttributes != null) { + if ((definingPolygonAttributes.polygonMode == + PolygonAttributes.POLYGON_POINT) && + (definingPointAttributes != null) && + definingPointAttributes.pointAntialiasing) { + return false; + } else if ((definingPolygonAttributes.polygonMode == + PolygonAttributes.POLYGON_LINE) && + (definingLineAttributes != null) && + definingLineAttributes.lineAntialiasing) { + return false; + } + } + } else if ((geometryType & POINT) != 0) { + if ((definingPointAttributes != null) && + definingPointAttributes.pointAntialiasing) { + return false; + } + } else if ((geometryType & LINE) != 0) { + if ((definingLineAttributes != null) && + definingLineAttributes.lineAntialiasing) { + return false; + } + } + return !TransparencyAttributesRetained.useAlpha(definingTransparency); + } + + + boolean updateNodeComponent() { + // System.err.println("soleUser = "+soleUser+" rm = "+this); + if ((soleUserCompDirty & MATERIAL_DIRTY) != 0) { + // Note: this RM is a soleUser(only then this function is called) + // and if definingMaterial == material, then the material is freq + // changed and therefore is not cloned, only other time it can be + // same is when an equivalent material is added in and this can + // never be true when a bin is a soleUser of a appearance + + // Evaluate before replacing the old Value + if (soleUser) { + boolean cloned = definingMaterial != null && definingMaterial != material; + // System.err.println("===>Rm = "+this); + + // System.err.println("===> updating node component, cloned = "+cloned+" material.changedFrequent = "+material.changedFrequent); + // System.err.println("===> definingMaterial ="+definingMaterial+" material = "+material); + + material = ((AppearanceRetained)appHandle).material; + if (material == null) + definingMaterial = null; + else { + if (material.changedFrequent != 0) { + definingMaterial = material; + } + else { + // If the one replaced is a cloned copy, then .. + if (cloned) { + definingMaterial.set(material); + } + else { + definingMaterial = (MaterialRetained)material.clone(); + } + } + } + } + evalMaterialCachedState(); + } + if ((soleUserCompDirty & LINEATTRS_DIRTY) != 0) { + if (soleUser) { + // Evaluate before replacing the old Value + boolean cloned = definingLineAttributes != null && definingLineAttributes != lineAttributes; + + lineAttributes = ((AppearanceRetained)appHandle).lineAttributes; + if (lineAttributes == null) { + lineAA = false; + definingLineAttributes = null; + } else { + if (lineAttributes.changedFrequent != 0) { + definingLineAttributes = lineAttributes; + } + else { + // If the one replaced is a cloned copy, then .. + if (cloned) { + definingLineAttributes.set(lineAttributes); + } + else { + definingLineAttributes = (LineAttributesRetained)lineAttributes.clone(); + } + } + lineAA = definingLineAttributes.lineAntialiasing; + } + } + else { + lineAA = definingLineAttributes.lineAntialiasing; + } + } + if ((soleUserCompDirty & POINTATTRS_DIRTY) != 0) { + if (soleUser) { + // Evaluate before replacing the old Value + boolean cloned = definingPointAttributes != null && definingPointAttributes != pointAttributes; + + pointAttributes = ((AppearanceRetained)appHandle).pointAttributes; + if (pointAttributes == null) { + pointAA = false; + definingPointAttributes = null; + } else { + if (pointAttributes.changedFrequent != 0) { + definingPointAttributes = pointAttributes; + } + else { + // If the one replaced is a cloned copy, then .. + if (cloned) { + definingPointAttributes.set(pointAttributes); + } + else { + definingPointAttributes = (PointAttributesRetained)pointAttributes.clone(); + } + } + pointAA = definingPointAttributes.pointAntialiasing; + } + } + else { + pointAA = definingPointAttributes.pointAntialiasing; + } + + } + if ((soleUserCompDirty & POLYGONATTRS_DIRTY) != 0) { + if (soleUser) { + // Evaluate before replacing the old Value + boolean cloned = definingPolygonAttributes != null && definingPolygonAttributes != polygonAttributes; + + + polygonAttributes = ((AppearanceRetained)appHandle).polygonAttributes; + + if (polygonAttributes == null) { + polygonMode = PolygonAttributes.POLYGON_FILL; + definingPolygonAttributes = null; + } else { + if (polygonAttributes.changedFrequent != 0) { + definingPolygonAttributes = polygonAttributes; + } + else { + // If the one replaced is a cloned copy, then .. + if (cloned) { + definingPolygonAttributes.set(polygonAttributes); + } + else { + definingPolygonAttributes = (PolygonAttributesRetained)polygonAttributes.clone(); + } + } + + polygonMode = definingPolygonAttributes.polygonMode; + } + } + else { + polygonMode = definingPolygonAttributes.polygonMode; + } + + if (polygonMode == PolygonAttributes.POLYGON_LINE) { + geometryType |= LINE; + } else if (polygonMode == PolygonAttributes.POLYGON_POINT) { + geometryType |= POINT; + } + } + + if ((soleUserCompDirty & TRANSPARENCY_DIRTY) != 0) { + if (soleUser) { + // Evaluate before replacing the old Value + boolean cloned = definingTransparency != null && definingTransparency != transparency; + transparency = ((AppearanceRetained)appHandle).transparencyAttributes; + + if (transparency == null) { + alpha = 1.0f ; + definingTransparency = null; + } else { + if (transparency.changedFrequent != 0) { + definingTransparency = transparency; + } + else { + // If the one replaced is a cloned copy, then .. + if (cloned) { + definingTransparency.set(transparency); + } + else { + definingTransparency = (TransparencyAttributesRetained)transparency.clone(); + } + } + + alpha = 1.0f - definingTransparency.transparency; + } + } + else { + alpha = 1.0f - definingTransparency.transparency; + } + } + + if ((soleUserCompDirty & COLORINGATTRS_DIRTY) != 0) { + if (soleUser) { + // Evaluate before replacing the old Value + boolean cloned = definingColoringAttributes != null && definingColoringAttributes != coloringAttributes; + + coloringAttributes = ((AppearanceRetained)appHandle).coloringAttributes; + // System.err.println("coloringAttributes and soleUser"); + // System.err.println("coloringAttributes ="+coloringAttributes); + if (coloringAttributes == null) { + definingColoringAttributes = null; + red = 1.0f; + green = 1.0f; + blue = 1.0f; + } else { + // System.err.println("coloringAttributes.changedFrequent = "+coloringAttributes.changedFrequent ); + if (coloringAttributes.changedFrequent != 0) { + definingColoringAttributes = coloringAttributes; + } + else { + // If the one replaced is a cloned copy, then .. + if (cloned) { + definingColoringAttributes.set(coloringAttributes); + } + else { + definingColoringAttributes = (ColoringAttributesRetained)coloringAttributes.clone(); + } + } + red = definingColoringAttributes.color.x; + green = definingColoringAttributes.color.y; + blue = definingColoringAttributes.color.z; + } + } + else { + red = definingColoringAttributes.color.x; + green = definingColoringAttributes.color.y; + blue = definingColoringAttributes.color.z; + } + } + // System.err.println("rm = "+this+"red = "+red+" green = "+green+" blue = "+blue); + boolean newVal = isOpaque() || inOrderedGroup; + return (isOpaqueOrInOG != newVal); + + } + + // 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;; + definingMaterial = null; + dRed = 1.0f; + dGreen = 1.0f; + dBlue = 1.0f; + } + else { + if ((geometryType & RASTER) != 0) { + enableLighting = false; + dRed = 1.0f; + dGreen = 1.0f; + dBlue = 1.0f; + } else { + if (normalPresent) + enableLighting = definingMaterial.lightingEnable; + else + enableLighting = false; + dRed = definingMaterial.diffuseColor.x; + dGreen = definingMaterial.diffuseColor.y; + dBlue = definingMaterial.diffuseColor.z; + } + } + } + + + void markBitsAsDirty(int leftBits, int rightBits) { + if (prev != null) { + checkEquivalenceWithLeftNeighbor(prev, leftBits); + prev.soleUserCompDirty &= ~ALL_DIRTY_BITS; + } + else if (prevMap != null) { + checkEquivalenceWithLeftNeighbor(prevMap, leftBits); + prevMap.soleUserCompDirty &= ~ALL_DIRTY_BITS; + } + if (next != null) { + if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) { + next.checkEquivalenceWithLeftNeighbor(this, rightBits); + } else { + next.soleUserCompDirty = rightBits; + } + } + else if (nextMap != null) { + if ((nextMap.soleUserCompDirty & ALL_DIRTY_BITS) == 0) { + nextMap.checkEquivalenceWithLeftNeighbor(this, rightBits); + } else { + nextMap.soleUserCompDirty = rightBits; + } + } + + } + + void handleMaterialEquivalence() { + // Check if it has equivalent material to any of the "non-dirty" + // renderMolecules before this one + RenderMolecule curPrevRm = null; + RenderMolecule curNextRm = null; + boolean found = false; + int leftBits = ALL_DIRTY_BITS; + int rightBits = ALL_DIRTY_BITS; + if (prev != null) { + curPrevRm = prev.prev; + if (materialEquivalent(prev, reloadColor(prev))) { + found = true; + leftBits = (((soleUserCompDirty | prev.soleUserCompDirty) &ALL_DIRTY_BITS) & ~MATERIAL_DIRTY); + rightBits = (soleUserCompDirty & ALL_DIRTY_BITS); + markBitsAsDirty(leftBits, rightBits); + } + } + else if (!found && next != null) { + curNextRm = next.next; + + if (materialEquivalent(next, reloadColor(next))) { + found = true; + int bits = 0; + if (prev != null) + bits = prev.soleUserCompDirty; + else if (prevMap != null) + bits = prevMap.soleUserCompDirty; + + leftBits = ((soleUserCompDirty |bits) &ALL_DIRTY_BITS); + rightBits = ((soleUserCompDirty & ALL_DIRTY_BITS) & ~MATERIAL_DIRTY); + markBitsAsDirty(leftBits, rightBits); + + } + } + // try place it next to a equivalent material on the left + while (!found && curPrevRm != null) { + if (materialEquivalent(curPrevRm, reloadColor(curPrevRm))) { + found = true; + // Remove the renderMolecule from it place + prev.next = next; + prev.nextMap = nextMap; + if (next != null) { + next.prev = prev; + if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) { + next.checkEquivalenceWithLeftNeighbor(prev, ALL_DIRTY_BITS); + } + else { + next.soleUserCompDirty = ALL_DIRTY_BITS; + } + } + else if (nextMap != null) { + nextMap.prevMap = prev; + if ((nextMap.soleUserCompDirty & ALL_DIRTY_BITS) == 0) { + nextMap.checkEquivalenceWithLeftNeighbor(prev,ALL_DIRTY_BITS); + } + else { + nextMap.soleUserCompDirty |= ALL_DIRTY_BITS; + } + } + + // Insert it after the equivalent RM + next = curPrevRm.next; + nextMap = curPrevRm.nextMap; + curPrevRm.nextMap = null; + if (next != null) { + next.prev = this; + } + else if (nextMap != null) { + nextMap.prevMap = this; + } + prev = curPrevRm; + curPrevRm.next = this; + leftBits = (ALL_DIRTY_BITS & ~MATERIAL_DIRTY); + markBitsAsDirty(leftBits, ALL_DIRTY_BITS); + } + curPrevRm = curPrevRm.prev; + } + + // Check if it has equivalent material to any of the renderMolecules after + // this one + while (!found && curNextRm != null) { + if (materialEquivalent(curNextRm, reloadColor(curNextRm))) { + found = true; + // switch the pointers + next.prev = prev; + next.prevMap = prevMap; + if (prev != null) { + prev.next = next; + if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) { + next.checkEquivalenceWithLeftNeighbor(prev, ALL_DIRTY_BITS); + } + else { + next.soleUserCompDirty = ALL_DIRTY_BITS; + } + } + else if (prevMap != null) { + prevMap.nextMap = next; + if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) { + next.checkEquivalenceWithLeftNeighbor(prevMap, ALL_DIRTY_BITS); + } + else { + next.soleUserCompDirty = ALL_DIRTY_BITS; + } + } + + // Insert it before the equivalent RM + prev = curNextRm.prev; + prevMap = curNextRm.prevMap; + curNextRm.prevMap = null; + if (curNextRm.prev != null) { + curNextRm.prev.next = this; + } + else if (prevMap != null) { + prevMap.nextMap = this; + } + next = curNextRm; + curNextRm.prev = this; + rightBits = (ALL_DIRTY_BITS & ~MATERIAL_DIRTY); + markBitsAsDirty(ALL_DIRTY_BITS, rightBits); + } + curNextRm = curNextRm.next; + } + // If there are no equivalent ones, evaluate the dirty bits in the current place + if (!found) { + if (prev != null) { + leftBits = ((soleUserCompDirty|prev.soleUserCompDirty) & ALL_DIRTY_BITS); + } + else if (prevMap != null) { + leftBits = ((soleUserCompDirty|prevMap.soleUserCompDirty) & ALL_DIRTY_BITS); + } + if (next != null) { + rightBits = ((soleUserCompDirty|next.soleUserCompDirty) & ALL_DIRTY_BITS); + } + else if (nextMap != null) { + rightBits = ((soleUserCompDirty|nextMap.soleUserCompDirty) & ALL_DIRTY_BITS); + } + markBitsAsDirty(leftBits, rightBits); + } + + } + + void reEvaluateEquivalence () { + // If Material changed, reInsert next to a equivalent material under + // the same transform group + // to prevent unnecessary material download + // This RM may have been evaluated due to an other RM is the same list + // If not, ... + if ((soleUserCompDirty & ALL_DIRTY_BITS) != 0) { + if ((soleUserCompDirty & MATERIAL_DIRTY) != 0) { + handleMaterialEquivalence(); + } + else { + int dirtyBits = (soleUserCompDirty & ALL_DIRTY_BITS); + if (prev != null) { + checkEquivalenceWithLeftNeighbor(prev, ((dirtyBits|prev.soleUserCompDirty) & ALL_DIRTY_BITS)); + prev.soleUserCompDirty = 0; + } else if (prevMap != null) { + checkEquivalenceWithLeftNeighbor(prevMap, ((dirtyBits|prevMap.soleUserCompDirty) & ALL_DIRTY_BITS)); + prevMap.soleUserCompDirty = 0; + } + if (next != null) { + next.checkEquivalenceWithLeftNeighbor(this,((next.soleUserCompDirty|soleUserCompDirty) & ALL_DIRTY_BITS)); + } else if (nextMap != null) { + nextMap.checkEquivalenceWithLeftNeighbor(this,((nextMap.soleUserCompDirty | soleUserCompDirty) & ALL_DIRTY_BITS)); + } + } + } + soleUserCompDirty &= ~ALL_DIRTY_BITS; + } + + + boolean materialEquivalent(RenderMolecule rm, boolean reloadColor) { + if (!reloadColor) { + if (((this.material == rm.material) || + ((rm.definingMaterial != null) && + (rm.definingMaterial.equivalent(definingMaterial)))) && + rm.alpha == alpha && + enableLighting == rm.enableLighting && + (enableLighting || + (!enableLighting && + rm.red ==red && + rm.green == green && + rm.blue == blue))) { + return true; + } + } + return false; + } + + boolean coloringEquivalent(RenderMolecule rm, boolean reload_color) { + if (!reload_color) { + if (((rm.coloringAttributes == coloringAttributes) || + ((rm.definingColoringAttributes != null) && + (rm.definingColoringAttributes.equivalent(definingColoringAttributes)))) && + (!enableLighting || (enableLighting && (dRed == rm.dRed && dBlue == rm.dBlue && dGreen == rm.dGreen)))) { + return true; + } + } + return false; + } + + boolean transparencyEquivalent(RenderMolecule rm) { + if (((rm.transparency == transparency) || + ((rm.definingTransparency != null) && + (rm.definingTransparency.equivalent(definingTransparency))) && + (rm.definingTransparency.transparencyMode < TransparencyAttributes.SCREEN_DOOR && + blendOn() == rm.blendOn()))) { + return true; + } + return false; + } + + boolean blendOn() { + if (lineAA && ((((geometryType & LINE) != 0) || + polygonMode == PolygonAttributes.POLYGON_LINE))) { + return true; + } + if (pointAA && ((((geometryType & POINT) != 0) || + polygonMode == PolygonAttributes.POLYGON_POINT))) { + return true; + } + return false; + } + + @Override + VirtualUniverse getVirtualUniverse() { + return null; + } + + + void handleLocaleChange() { + if (locale == renderBin.locale) { + if (localToVworld != localeLocalToVworld) { + localeLocalToVworld = localToVworld; + localeTranslation = null; + } + } + else { + // Using the localToVworl then, go back to making a new copy + if (localeTranslation == null) { + localeLocalToVworld = new Transform3D[2]; + localeLocalToVworld[0] = new Transform3D(); + localeLocalToVworld[1] = new Transform3D(); + + localeTranslation = new Vector3d(); + locale.hiRes.difference(renderBin.locale.hiRes, localeTranslation); + translate(); + int i = localToVworldIndex[NodeRetained.CURRENT_LOCAL_TO_VWORLD]; + + localeLocalToVworld[i].mat[0] = localToVworld[i].mat[0]; + localeLocalToVworld[i].mat[1] = localToVworld[i].mat[1]; + localeLocalToVworld[i].mat[2] = localToVworld[i].mat[2]; + localeLocalToVworld[i].mat[3] = localToVworld[i].mat[3] + localeTranslation.x ; + localeLocalToVworld[i].mat[4] = localToVworld[i].mat[4]; + localeLocalToVworld[i].mat[5] = localToVworld[i].mat[5]; + localeLocalToVworld[i].mat[6] = localToVworld[i].mat[6]; + localeLocalToVworld[i].mat[7] = localToVworld[i].mat[7]+ localeTranslation.y; + localeLocalToVworld[i].mat[8] = localToVworld[i].mat[8]; + localeLocalToVworld[i].mat[9] = localToVworld[i].mat[9]; + localeLocalToVworld[i].mat[10] = localToVworld[i].mat[10]; + localeLocalToVworld[i].mat[11] = localToVworld[i].mat[11]+ localeTranslation.z; + localeLocalToVworld[i].mat[12] = localToVworld[i].mat[12]; + localeLocalToVworld[i].mat[13] = localToVworld[i].mat[13]; + localeLocalToVworld[i].mat[14] = localToVworld[i].mat[14]; + localeLocalToVworld[i].mat[15] = localToVworld[i].mat[15]; + } + } + + trans = localeLocalToVworld; + } + + + /** + * updateNodeComponentCheck is called for each soleUser RenderMolecule + * into which new renderAtom has been added. This method is called before + * updateNodeComponent() to allow RenderMolecule to catch any node + * component changes that have been missed because the changes + * come when there is no active renderAtom associated with the + * TextureBin. See bug# 4503926 for details. + */ + @Override + public void updateNodeComponentCheck() { + + // If the renderMolecule has been removed, do nothing .. + if ((onUpdateList &ON_UPDATE_CHECK_LIST ) == 0) + return; + + onUpdateList &= ~ON_UPDATE_CHECK_LIST; + NodeComponentRetained nc = (NodeComponentRetained)appHandle; + if ((nc.compChanged & RM_COMPONENTS) != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= (nc.compChanged & RM_COMPONENTS); + } + if (definingPolygonAttributes != null && + definingPolygonAttributes == polygonAttributes) { + if (definingPolygonAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= POLYGONATTRS_DIRTY; + } + } + if (definingLineAttributes != null && + definingLineAttributes == lineAttributes) { + if (definingLineAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= LINEATTRS_DIRTY; + } + } + if (definingPointAttributes != null && + definingPointAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= POINTATTRS_DIRTY; + } + + if (definingMaterial != null && + definingMaterial == material) { + if (definingMaterial.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= MATERIAL_DIRTY; + } + } + + if (definingColoringAttributes != null && + definingColoringAttributes == coloringAttributes) { + if (definingColoringAttributes.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= COLORINGATTRS_DIRTY; + } + } + + if (definingTransparency != null && + definingTransparency == transparency) { + if (definingTransparency.compChanged != 0) { + if ((soleUserCompDirty& ALL_DIRTY_BITS) == 0 ) { + renderBin.rmUpdateList.add(this); + } + soleUserCompDirty |= TRANSPARENCY_DIRTY; + } + } + } +} |