0001: /*
0002: * $RCSfile: RenderMolecule.java,v $
0003: *
0004: * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006: *
0007: * This code is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU General Public License version 2 only, as
0009: * published by the Free Software Foundation. Sun designates this
0010: * particular file as subject to the "Classpath" exception as provided
0011: * by Sun in the LICENSE file that accompanied this code.
0012: *
0013: * This code is distributed in the hope that it will be useful, but WITHOUT
0014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0016: * version 2 for more details (a copy is included in the LICENSE file that
0017: * accompanied this code).
0018: *
0019: * You should have received a copy of the GNU General Public License version
0020: * 2 along with this work; if not, write to the Free Software Foundation,
0021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022: *
0023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024: * CA 95054 USA or visit www.sun.com if you need additional information or
0025: * have any questions.
0026: *
0027: * $Revision: 1.9 $
0028: * $Date: 2008/02/28 20:17:28 $
0029: * $State: Exp $
0030: */
0031:
0032: package javax.media.j3d;
0033:
0034: import javax.vecmath.*;
0035: import java.util.*;
0036:
0037: /**
0038: * The RenderMolecule manages a collection of RenderAtoms.
0039: */
0040:
0041: class RenderMolecule extends IndexedObject implements ObjectUpdate,
0042: NodeComponentUpdate {
0043:
0044: // different types of IndexedUnorderedSet that store RenderMolecule
0045: static final int REMOVE_RENDER_ATOM_IN_RM_LIST = 0;
0046: static final int RENDER_MOLECULE_LIST = 1;
0047:
0048: // total number of different IndexedUnorderedSet types
0049: static final int TOTAL_INDEXED_UNORDER_SET_TYPES = 2;
0050:
0051: /**
0052: * Values for the geometryType field
0053: */
0054: static final int POINT = 0x01;
0055: static final int LINE = 0x02;
0056: static final int SURFACE = 0x04;
0057: static final int RASTER = 0x08;
0058: static final int COMPRESSED = 0x10;
0059:
0060: static int RM_COMPONENTS = (AppearanceRetained.POLYGON
0061: | AppearanceRetained.LINE | AppearanceRetained.POINT
0062: | AppearanceRetained.MATERIAL
0063: | AppearanceRetained.TRANSPARENCY | AppearanceRetained.COLOR);
0064:
0065: // XXXX: use definingMaterial etc. instead of these
0066: // when sole user is completely implement
0067: PolygonAttributesRetained polygonAttributes = null;
0068: LineAttributesRetained lineAttributes = null;
0069: PointAttributesRetained pointAttributes = null;
0070: MaterialRetained material = null;
0071: ColoringAttributesRetained coloringAttributes = null;
0072: TransparencyAttributesRetained transparency = null;
0073:
0074: // Use Object instead of AppearanceRetained class for
0075: // state caching optimation memory performance
0076:
0077: boolean normalPresent = true;
0078:
0079: // Equivalent bits
0080: static final int POINTATTRS_DIRTY = AppearanceRetained.POINT;
0081: static final int LINEATTRS_DIRTY = AppearanceRetained.LINE;
0082: static final int POLYGONATTRS_DIRTY = AppearanceRetained.POLYGON;
0083: static final int MATERIAL_DIRTY = AppearanceRetained.MATERIAL;
0084: static final int TRANSPARENCY_DIRTY = AppearanceRetained.TRANSPARENCY;
0085: static final int COLORINGATTRS_DIRTY = AppearanceRetained.COLOR;
0086:
0087: static final int ALL_DIRTY_BITS = POINTATTRS_DIRTY
0088: | LINEATTRS_DIRTY | POLYGONATTRS_DIRTY | MATERIAL_DIRTY
0089: | TRANSPARENCY_DIRTY | COLORINGATTRS_DIRTY;
0090:
0091: /**
0092: * bit mask of all attr fields that are equivalent across
0093: * renderMolecules
0094: */
0095: int dirtyAttrsAcrossRms = ALL_DIRTY_BITS;
0096:
0097: // Mask set to true is any of the component have changed
0098: int soleUserCompDirty = 0;
0099:
0100: /**
0101: * The PolygonAttributes for this RenderMolecule
0102: */
0103: PolygonAttributesRetained definingPolygonAttributes = null;
0104:
0105: /**
0106: * The LineAttributes for this RenderMolecule
0107: */
0108: LineAttributesRetained definingLineAttributes = null;
0109:
0110: /**
0111: * The PointAttributes for this RenderMolecule
0112: */
0113: PointAttributesRetained definingPointAttributes = null;
0114:
0115: /**
0116: * The TextureBin that this RenderMolecule resides
0117: */
0118: TextureBin textureBin = null;
0119:
0120: /**
0121: * The localToVworld for this RenderMolecule
0122: */
0123: Transform3D[] localToVworld = null;
0124: int[] localToVworldIndex = null;
0125:
0126: /**
0127: * The Material reference for this RenderMolecule
0128: */
0129: MaterialRetained definingMaterial = null;
0130:
0131: /**
0132: * The ColoringAttribute reference for this RenderMolecule
0133: */
0134: ColoringAttributesRetained definingColoringAttributes = null;
0135:
0136: /**
0137: * The Transparency reference for this RenderMolecule
0138: */
0139: TransparencyAttributesRetained definingTransparency = null;
0140:
0141: /**
0142: * Transform3D - point to the right one based on bg or not
0143: */
0144: Transform3D[] trans = null;
0145:
0146: /**
0147: * specify whether scale is nonuniform
0148: */
0149: boolean isNonUniformScale = false;
0150:
0151: /**
0152: * number of renderAtoms to be rendered in this RenderMolecule
0153: */
0154: int numRenderAtoms = 0;
0155:
0156: /**
0157: * number of render atoms, used during the renderBin update time
0158: */
0159: int numEditingRenderAtoms = 0;
0160:
0161: RenderAtom addRAs = null;
0162: RenderAtom removeRAs = null;
0163:
0164: /**
0165: * The cached ColoringAttributes color value. It is
0166: * 1.0, 1.0, 1.0 if there is no ColoringAttributes.
0167: */
0168: float red = 1.0f;
0169: float green = 1.0f;
0170: float blue = 1.0f;
0171:
0172: /**
0173: * Cached diffuse color value
0174: */
0175: float dRed = 1.0f;
0176: float dGreen = 1.0f;
0177: float dBlue = 1.0f;
0178:
0179: /**
0180: * The cached TransparencyAttributes transparency value. It is
0181: * 0.0 if there is no TransparencyAttributes.
0182: */
0183: float alpha = 0.0f;
0184:
0185: /**
0186: * The geometry type for this RenderMolecule
0187: */
0188: int geometryType = -1;
0189:
0190: /**
0191: * A boolean indicating whether or not lighting should be on.
0192: */
0193: boolean enableLighting = false;
0194:
0195: /**
0196: * A boolean indicating whether or not this molecule rendered Text3D
0197: */
0198:
0199: int primaryMoleculeType = 0;
0200: static int COMPRESSED_MOLECULE = 0x1;
0201: static int TEXT3D_MOLECULE = 0x2;
0202: static int DLIST_MOLECULE = 0x4;
0203: static int RASTER_MOLECULE = 0x8;
0204: static int ORIENTEDSHAPE3D_MOLECULE = 0x10;
0205: static int SEPARATE_DLIST_PER_RINFO_MOLECULE = 0x20;
0206:
0207: /**
0208: * Cached values for polygonMode, line antialiasing, and point antialiasing
0209: */
0210: int polygonMode = PolygonAttributes.POLYGON_FILL;
0211: boolean lineAA = false;
0212: boolean pointAA = false;
0213:
0214: /**
0215: * The vertex format for this RenderMolecule. Only looked
0216: * at for GeometryArray and CompressedGeometry objects.
0217: */
0218: int vertexFormat = -1;
0219:
0220: /**
0221: * The texCoordSetMap length for this RenderMolecule.
0222: */
0223: int texCoordSetMapLen = 0;
0224:
0225: /**
0226: * The primary renderMethod object for this RenderMolecule
0227: * this is either a Text3D, display list, or compressed geometry renderer.
0228: */
0229: RenderMethod primaryRenderMethod = null;
0230:
0231: /**
0232: * The secondary renderMethod object for this RenderMolecule
0233: * this is used for geometry that is shared
0234: */
0235: RenderMethod secondaryRenderMethod = null;
0236:
0237: /**
0238: * The RenderBino for this molecule
0239: */
0240: RenderBin renderBin = null;
0241:
0242: /**
0243: * The references to the next and previous RenderMolecule in the
0244: * list.
0245: */
0246: RenderMolecule next = null;
0247: RenderMolecule prev = null;
0248:
0249: /**
0250: * The list of RenderAtoms in this RenderMolecule that are not using
0251: * vertex arrays.
0252: */
0253: RenderAtomListInfo primaryRenderAtomList = null;
0254:
0255: /**
0256: * The list of RenderAtoms in this RenderMolecule that are using
0257: * separte dlist .
0258: */
0259: RenderAtomListInfo separateDlistRenderAtomList = null;
0260:
0261: /**
0262: * The list of RenderAtoms in this RenderMolecule that are using vertex
0263: * arrays.
0264: */
0265: RenderAtomListInfo vertexArrayRenderAtomList = null;
0266:
0267: /**
0268: * This BoundingBox is used for View Frustum culling on the primary
0269: * list
0270: */
0271: BoundingBox vwcBounds = null;
0272:
0273: /**
0274: * If this is end of the linked list for this xform, then
0275: * this field is non-null, if there is a map after this
0276: */
0277: RenderMolecule nextMap = null;
0278: RenderMolecule prevMap = null;
0279:
0280: /**
0281: * If the any of the node component of the appearance in RM will be changed
0282: * frequently, then confine it to a separate bin
0283: */
0284: boolean soleUser = false;
0285: Object appHandle = null;
0286:
0287: VertexArrayRenderMethod cachedVertexArrayRenderMethod = (VertexArrayRenderMethod) VirtualUniverse.mc
0288: .getVertexArrayRenderMethod();
0289:
0290: // In D3D separate Quad/Triangle Geometry with others in RenderMolecule
0291: // Since we need to dynamically switch whether to use DisplayList
0292: // or not in render() as a group.
0293: boolean isQuadGeometryArray = false;
0294: boolean isTriGeometryArray = false;
0295:
0296: // display list id, valid id starts from 1
0297: int displayListId = 0;
0298: Integer displayListIdObj = null;
0299:
0300: int onUpdateList = 0;
0301: static int NEW_RENDERATOMS_UPDATE = 0x1;
0302: static int BOUNDS_RECOMPUTE_UPDATE = 0x2;
0303: static int LOCALE_TRANSLATION = 0x4;
0304: static int UPDATE_BACKGROUND_TRANSFORM = 0x8;
0305: static int IN_DIRTY_RENDERMOLECULE_LIST = 0x10;
0306: static int LOCALE_CHANGED = 0x20;
0307: static int ON_UPDATE_CHECK_LIST = 0x40;
0308:
0309: // background geometry rendering
0310: boolean doInfinite;
0311: Transform3D[] infLocalToVworld;
0312:
0313: // Whether alpha is used in this renderMolecule
0314: boolean useAlpha = false;
0315:
0316: // Support for multiple locales
0317: Locale locale = null;
0318:
0319: // Transform when locale is different from the view's locale
0320: Transform3D[] localeLocalToVworld = null;
0321:
0322: // Vector used for locale translation
0323: Vector3d localeTranslation = null;
0324:
0325: boolean primaryChanged = false;
0326:
0327: boolean isOpaqueOrInOG = true;
0328: boolean inOrderedGroup = false;
0329:
0330: // closest switch parent
0331: SwitchRetained closestSwitchParent = null;
0332:
0333: // the child index from the closest switch parent
0334: int closestSwitchIndex = -1;
0335:
0336: RenderMolecule(GeometryAtom ga,
0337: PolygonAttributesRetained polygonAttributes,
0338: LineAttributesRetained lineAttributes,
0339: PointAttributesRetained pointAttributes,
0340: MaterialRetained material,
0341: ColoringAttributesRetained coloringAttributes,
0342: TransparencyAttributesRetained transparency,
0343: RenderingAttributesRetained renderAttrs,
0344: TextureUnitStateRetained[] texUnits,
0345: Transform3D[] transform, int[] transformIndex, RenderBin rb) {
0346: renderBin = rb;
0347: IndexedUnorderSet.init(this , TOTAL_INDEXED_UNORDER_SET_TYPES);
0348:
0349: reset(ga, polygonAttributes, lineAttributes, pointAttributes,
0350: material, coloringAttributes, transparency,
0351: renderAttrs, texUnits, transform, transformIndex);
0352: }
0353:
0354: void reset(GeometryAtom ga,
0355: PolygonAttributesRetained polygonAttributes,
0356: LineAttributesRetained lineAttributes,
0357: PointAttributesRetained pointAttributes,
0358: MaterialRetained material,
0359: ColoringAttributesRetained coloringAttributes,
0360: TransparencyAttributesRetained transparency,
0361: RenderingAttributesRetained renderAttrs,
0362: TextureUnitStateRetained[] texUnits,
0363: Transform3D[] transform, int[] transformIndex) {
0364: primaryMoleculeType = 0;
0365: numRenderAtoms = 0;
0366: numEditingRenderAtoms = 0;
0367: onUpdateList = 0;
0368: dirtyAttrsAcrossRms = ALL_DIRTY_BITS;
0369: primaryRenderMethod = null;
0370: isNonUniformScale = false;
0371: primaryChanged = false;
0372: this .material = material;
0373: this .polygonAttributes = polygonAttributes;
0374: this .lineAttributes = lineAttributes;
0375: this .pointAttributes = pointAttributes;
0376: this .coloringAttributes = coloringAttributes;
0377: this .transparency = transparency;
0378:
0379: closestSwitchParent = ga.source.closestSwitchParent;
0380: closestSwitchIndex = ga.source.closestSwitchIndex;
0381:
0382: int i1;
0383: // Find the first non-null geometey
0384: GeometryRetained geo = null;
0385: int k = 0;
0386: isOpaqueOrInOG = true;
0387: inOrderedGroup = false;
0388: while (geo == null && (k < ga.geometryArray.length)) {
0389: geo = ga.geometryArray[k];
0390: k++;
0391: }
0392:
0393: // Issue 249 - check for sole user only if property is set
0394: soleUser = false;
0395: if (VirtualUniverse.mc.allowSoleUser) {
0396: if (ga.source.appearance != null) {
0397: soleUser = ((ga.source.appearance.changedFrequent & RM_COMPONENTS) != 0);
0398: }
0399: }
0400:
0401: // Set the appearance only for soleUser case
0402: if (soleUser)
0403: appHandle = ga.source.appearance;
0404: else
0405: appHandle = (Object) this ;
0406:
0407: // If its of type GeometryArrayRetained
0408: if (ga.geoType <= GeometryRetained.GEO_TYPE_GEOMETRYARRAY
0409: || ga.geoType == GeometryRetained.GEO_TYPE_TEXT3D) {
0410:
0411: if (ga.source instanceof OrientedShape3DRetained) {
0412: primaryRenderMethod = VirtualUniverse.mc
0413: .getOrientedShape3DRenderMethod();
0414: primaryMoleculeType = ORIENTEDSHAPE3D_MOLECULE;
0415: } else if (ga.geoType == GeometryRetained.GEO_TYPE_TEXT3D) {
0416: primaryRenderMethod = VirtualUniverse.mc
0417: .getText3DRenderMethod();
0418: primaryMoleculeType = TEXT3D_MOLECULE;
0419: } else {
0420: // Make determination of dlist or not during addRenderAtom
0421: secondaryRenderMethod = cachedVertexArrayRenderMethod;
0422: }
0423: } else {
0424: if (ga.geoType == GeometryRetained.GEO_TYPE_COMPRESSED) {
0425: primaryRenderMethod = VirtualUniverse.mc
0426: .getCompressedGeometryRenderMethod();
0427: primaryMoleculeType = COMPRESSED_MOLECULE;
0428: } else if (geo instanceof RasterRetained) {
0429: primaryRenderMethod = VirtualUniverse.mc
0430: .getDefaultRenderMethod();
0431: primaryMoleculeType = RASTER_MOLECULE;
0432: }
0433: }
0434:
0435: prev = null;
0436: next = null;
0437: prevMap = null;
0438: nextMap = null;
0439:
0440: primaryRenderAtomList = null;
0441: vertexArrayRenderAtomList = null;
0442:
0443: switch (ga.geoType) {
0444: case GeometryRetained.GEO_TYPE_POINT_SET:
0445: case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET:
0446: this .geometryType = POINT;
0447: break;
0448: case GeometryRetained.GEO_TYPE_LINE_SET:
0449: case GeometryRetained.GEO_TYPE_LINE_STRIP_SET:
0450: case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET:
0451: case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET:
0452: this .geometryType = LINE;
0453: break;
0454: case GeometryRetained.GEO_TYPE_RASTER:
0455: this .geometryType = RASTER;
0456: break;
0457: case GeometryRetained.GEO_TYPE_COMPRESSED:
0458: this .geometryType = COMPRESSED;
0459:
0460: switch (((CompressedGeometryRetained) geo).getBufferType()) {
0461: case CompressedGeometryHeader.POINT_BUFFER:
0462: this .geometryType |= POINT;
0463: break;
0464: case CompressedGeometryHeader.LINE_BUFFER:
0465: this .geometryType |= LINE;
0466: break;
0467: default:
0468: case CompressedGeometryHeader.TRIANGLE_BUFFER:
0469: this .geometryType |= SURFACE;
0470: if (polygonAttributes != null) {
0471: if (polygonAttributes.polygonMode == PolygonAttributes.POLYGON_POINT) {
0472: this .geometryType |= POINT;
0473: } else if (polygonAttributes.polygonMode == PolygonAttributes.POLYGON_LINE) {
0474: this .geometryType |= LINE;
0475: }
0476: }
0477: break;
0478: }
0479: break;
0480: default:
0481: this .geometryType = SURFACE;
0482: if (polygonAttributes != null) {
0483: if (polygonAttributes.polygonMode == PolygonAttributes.POLYGON_POINT) {
0484: this .geometryType |= POINT;
0485: } else if (polygonAttributes.polygonMode == PolygonAttributes.POLYGON_LINE) {
0486: this .geometryType |= LINE;
0487: }
0488: }
0489: break;
0490: }
0491:
0492: isQuadGeometryArray = (geo.getClassType() == GeometryRetained.QUAD_TYPE);
0493: isTriGeometryArray = (geo.getClassType() == GeometryRetained.TRIANGLE_TYPE);
0494:
0495: this .localToVworld = transform;
0496: this .localToVworldIndex = transformIndex;
0497: doInfinite = ga.source.inBackgroundGroup;
0498: if (doInfinite) {
0499: if (infLocalToVworld == null) {
0500: infLocalToVworld = new Transform3D[2];
0501: infLocalToVworld[0] = infLocalToVworld[1] = new Transform3D();
0502: }
0503: localToVworld[0].getRotation(infLocalToVworld[0]);
0504: }
0505: int mask = 0;
0506: if (polygonAttributes != null) {
0507: if (polygonAttributes.changedFrequent != 0) {
0508: definingPolygonAttributes = polygonAttributes;
0509:
0510: mask |= POLYGONATTRS_DIRTY;
0511: } else {
0512: if (definingPolygonAttributes != null) {
0513: definingPolygonAttributes.set(polygonAttributes);
0514: } else {
0515: definingPolygonAttributes = (PolygonAttributesRetained) polygonAttributes
0516: .clone();
0517: }
0518: }
0519: polygonMode = definingPolygonAttributes.polygonMode;
0520: } else {
0521: polygonMode = PolygonAttributes.POLYGON_FILL;
0522: definingPolygonAttributes = null;
0523: }
0524:
0525: if (lineAttributes != null) {
0526: if (lineAttributes.changedFrequent != 0) {
0527: definingLineAttributes = lineAttributes;
0528: mask |= LINEATTRS_DIRTY;
0529: } else {
0530: if (definingLineAttributes != null) {
0531: definingLineAttributes.set(lineAttributes);
0532: } else {
0533: definingLineAttributes = (LineAttributesRetained) lineAttributes
0534: .clone();
0535: }
0536: }
0537: lineAA = definingLineAttributes.lineAntialiasing;
0538: } else {
0539: lineAA = false;
0540: definingLineAttributes = null;
0541: }
0542:
0543: if (pointAttributes != null) {
0544: if (pointAttributes.changedFrequent != 0) {
0545: definingPointAttributes = pointAttributes;
0546: mask |= POINTATTRS_DIRTY;
0547:
0548: } else {
0549: if (definingPointAttributes != null) {
0550: definingPointAttributes.set(pointAttributes);
0551: } else {
0552: definingPointAttributes = (PointAttributesRetained) pointAttributes
0553: .clone();
0554: }
0555: }
0556: pointAA = definingPointAttributes.pointAntialiasing;
0557: } else {
0558: pointAA = false;
0559: definingPointAttributes = null;
0560: }
0561:
0562: normalPresent = true;
0563: if (geo instanceof GeometryArrayRetained) {
0564: GeometryArrayRetained gr = (GeometryArrayRetained) geo;
0565: this .vertexFormat = gr.vertexFormat;
0566:
0567: if (gr.texCoordSetMap != null) {
0568: this .texCoordSetMapLen = gr.texCoordSetMap.length;
0569: } else {
0570: this .texCoordSetMapLen = 0;
0571: }
0572:
0573: // Throw an exception if lighting is enabled, but no normals defined
0574: if ((vertexFormat & GeometryArray.NORMALS) == 0) {
0575: // Force lighting to false
0576: normalPresent = false;
0577: }
0578:
0579: } else if (geo instanceof CompressedGeometryRetained) {
0580: this .vertexFormat = ((CompressedGeometryRetained) geo)
0581: .getVertexFormat();
0582: // Throw an exception if lighting is enabled, but no normals defined
0583: if ((vertexFormat & GeometryArray.NORMALS) == 0) {
0584: // Force lighting to false
0585: normalPresent = false;
0586: }
0587:
0588: this .texCoordSetMapLen = 0;
0589:
0590: } else {
0591: this .vertexFormat = -1;
0592: this .texCoordSetMapLen = 0;
0593: }
0594:
0595: if (material != null) {
0596: if (material.changedFrequent != 0) {
0597: definingMaterial = material;
0598: mask |= MATERIAL_DIRTY;
0599: } else {
0600: if (definingMaterial != null)
0601: definingMaterial.set(material);
0602: else {
0603: definingMaterial = (MaterialRetained) material
0604: .clone();
0605: }
0606: }
0607:
0608: } else {
0609: definingMaterial = null;
0610: }
0611: evalMaterialCachedState();
0612: if (coloringAttributes != null) {
0613: if (coloringAttributes.changedFrequent != 0) {
0614: definingColoringAttributes = coloringAttributes;
0615: mask |= COLORINGATTRS_DIRTY;
0616: } else {
0617: if (definingColoringAttributes != null) {
0618: definingColoringAttributes.set(coloringAttributes);
0619: } else {
0620: definingColoringAttributes = (ColoringAttributesRetained) coloringAttributes
0621: .clone();
0622: }
0623: }
0624: red = coloringAttributes.color.x;
0625: green = coloringAttributes.color.y;
0626: blue = coloringAttributes.color.z;
0627: } else {
0628: red = 1.0f;
0629: green = 1.0f;
0630: blue = 1.0f;
0631: definingColoringAttributes = null;
0632: }
0633:
0634: if (transparency != null) {
0635:
0636: if (transparency.changedFrequent != 0) {
0637: definingTransparency = transparency;
0638: mask |= TRANSPARENCY_DIRTY;
0639: } else {
0640: if (definingTransparency != null) {
0641: definingTransparency.set(transparency);
0642: } else {
0643: definingTransparency = (TransparencyAttributesRetained) transparency
0644: .clone();
0645: }
0646: }
0647: alpha = 1.0f - transparency.transparency;
0648:
0649: } else {
0650: alpha = 1.0f;
0651: definingTransparency = null;
0652:
0653: }
0654:
0655: locale = ga.source.locale;
0656: if (locale != renderBin.locale) {
0657: if (localeLocalToVworld == null) {
0658: localeLocalToVworld = new Transform3D[2];
0659: }
0660: localeLocalToVworld[0] = new Transform3D();
0661: localeLocalToVworld[1] = new Transform3D();
0662: localeTranslation = new Vector3d();
0663: ga.locale.hiRes.difference(renderBin.locale.hiRes,
0664: localeTranslation);
0665: translate();
0666: } else {
0667: localeLocalToVworld = localToVworld;
0668: }
0669:
0670: if (doInfinite) {
0671: trans = infLocalToVworld;
0672: } else {
0673: trans = localeLocalToVworld;
0674: }
0675:
0676: evalAlphaUsage(renderAttrs, texUnits);
0677: isOpaqueOrInOG = isOpaque() || (ga.source.orderedPath != null);
0678: inOrderedGroup = (ga.source.orderedPath != null);
0679: // System.err.println("isOpaque = "+isOpaque() +" OrInOG = "+isOpaqueOrInOG);
0680: if (mask != 0) {
0681: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0682: renderBin.rmUpdateList.add(this );
0683: }
0684: soleUserCompDirty |= mask;
0685: }
0686: }
0687:
0688: /**
0689: * This tests if the given attributes matches this TextureBin
0690: */
0691: boolean equals(RenderAtom ra,
0692: PolygonAttributesRetained polygonAttributes,
0693: LineAttributesRetained lineAttributes,
0694: PointAttributesRetained pointAttributes,
0695: MaterialRetained material,
0696: ColoringAttributesRetained coloringAttributes,
0697: TransparencyAttributesRetained transparency,
0698: Transform3D[] transform) {
0699: int geoType = 0;
0700: GeometryAtom ga = ra.geometryAtom;
0701: int eAttrs = 0;
0702:
0703: if (this .localToVworld != transform) {
0704: return (false);
0705: }
0706:
0707: if (locale != ra.geometryAtom.source.locale) {
0708: return (false);
0709: }
0710:
0711: if (ra.geometryAtom.source.closestSwitchParent != closestSwitchParent
0712: || ra.geometryAtom.source.closestSwitchIndex != closestSwitchIndex) {
0713: return (false);
0714: }
0715:
0716: // Find the first non-null geometey
0717: GeometryRetained geo = null;
0718: int k = 0;
0719: while (geo == null && (k < ga.geometryArray.length)) {
0720: geo = ga.geometryArray[k];
0721: k++;
0722: }
0723:
0724: // XXXX: Add tags
0725: switch (ga.geoType) {
0726: case GeometryRetained.GEO_TYPE_POINT_SET:
0727: case GeometryRetained.GEO_TYPE_INDEXED_POINT_SET:
0728: geoType = POINT;
0729: break;
0730: case GeometryRetained.GEO_TYPE_LINE_SET:
0731: case GeometryRetained.GEO_TYPE_LINE_STRIP_SET:
0732: case GeometryRetained.GEO_TYPE_INDEXED_LINE_SET:
0733: case GeometryRetained.GEO_TYPE_INDEXED_LINE_STRIP_SET:
0734: geoType = LINE;
0735: break;
0736: case GeometryRetained.GEO_TYPE_RASTER:
0737: geoType = RASTER;
0738: break;
0739: case GeometryRetained.GEO_TYPE_COMPRESSED:
0740: geoType = COMPRESSED;
0741: switch (((CompressedGeometryRetained) geo).getBufferType()) {
0742: case CompressedGeometryHeader.POINT_BUFFER:
0743: geoType |= POINT;
0744: break;
0745: case CompressedGeometryHeader.LINE_BUFFER:
0746: geoType |= LINE;
0747: break;
0748: default:
0749: case CompressedGeometryHeader.TRIANGLE_BUFFER:
0750: geoType |= SURFACE;
0751: break;
0752: }
0753: break;
0754: default:
0755: geoType = SURFACE;
0756: if (polygonAttributes != null) {
0757: if (polygonAttributes.polygonMode == PolygonAttributes.POLYGON_POINT) {
0758: geoType |= POINT;
0759: } else if (polygonAttributes.polygonMode == PolygonAttributes.POLYGON_LINE) {
0760: geoType |= LINE;
0761: }
0762: }
0763: break;
0764: }
0765:
0766: if (this .geometryType != geoType) {
0767: return (false);
0768: }
0769: /*
0770: // XXXX : Check this
0771: if (useDisplayList &&
0772: (ga.geometry.isEditable ||
0773: ga.geometry.refCount > 1 ||
0774: ((GroupRetained)ga.source.parent).switchLevel >= 0 ||
0775: ga.alphaEditable)) {
0776: return (false);
0777: }
0778: */
0779: if (ga.geoType == GeometryRetained.GEO_TYPE_TEXT3D
0780: && primaryMoleculeType != 0
0781: && ((primaryMoleculeType & TEXT3D_MOLECULE) == 0)) {
0782: return (false);
0783: }
0784:
0785: if (!(ra.geometryAtom.source instanceof OrientedShape3DRetained)
0786: && ((primaryMoleculeType & ORIENTEDSHAPE3D_MOLECULE) != 0)) {
0787: //System.err.println("RA's NOT a OrientedShape3DRetained and RM is a ORIENTEDSHAPE3D_MOLECULE ");
0788:
0789: return (false);
0790: }
0791:
0792: // XXXX: Its is necessary to have same vformat for dl,
0793: // Howabout iteration, should we have 2 vformats in rm?
0794: if (geo instanceof GeometryArrayRetained) {
0795: GeometryArrayRetained gr = (GeometryArrayRetained) geo;
0796: if (this .vertexFormat != gr.vertexFormat) {
0797: return (false);
0798: }
0799:
0800: // we are requiring that texCoordSetMap length to be the same
0801: // so that we can either put all multi-tex ga to a display list,
0802: // or punt all to vertex array. And we don't need to worry
0803: // about some of the ga can be in display list for this canvas,
0804: // and some other can be in display list for the other canvas.
0805: if (((gr.texCoordSetMap != null) && (this .texCoordSetMapLen != gr.texCoordSetMap.length))
0806: || ((gr.texCoordSetMap == null) && (this .texCoordSetMapLen != 0))) {
0807: return (false);
0808: }
0809:
0810: if (VirtualUniverse.mc.isD3D()
0811: && (((geo.getClassType() == GeometryRetained.QUAD_TYPE) && !isQuadGeometryArray) || ((geo
0812: .getClassType() == GeometryRetained.TRIANGLE_TYPE) && !isTriGeometryArray))) {
0813: return false;
0814: }
0815:
0816: } else if (geo instanceof CompressedGeometryRetained) {
0817: if (this .vertexFormat != ((CompressedGeometryRetained) geo)
0818: .getVertexFormat()) {
0819: return (false);
0820: }
0821: } else {
0822: //XXXX: compare isEditable
0823: if (this .vertexFormat != -1) {
0824: return (false);
0825: }
0826: }
0827:
0828: // If the any reference to the appearance components that is cached renderMolecule
0829: // can change frequently, make a separate bin
0830: if (soleUser
0831: || (ra.geometryAtom.source.appearance != null && ((ra.geometryAtom.source.appearance.changedFrequent & RM_COMPONENTS) != 0))) {
0832: if (appHandle == (Object) ra.geometryAtom.source.appearance) {
0833:
0834: // if this RenderMolecule is currently on a zombie state,
0835: // we'll need to put it on the update list to reevaluate
0836: // the state, because while it is on a zombie state,
0837: // state could have been changed. Example,
0838: // application could have detached an appearance,
0839: // made changes to the appearance state, and then
0840: // reattached the appearance. In this case, the
0841: // changes would not have reflected to the RenderMolecule
0842:
0843: if (numEditingRenderAtoms == 0) {
0844:
0845: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0846: renderBin.rmUpdateList.add(this );
0847: }
0848: soleUserCompDirty |= ALL_DIRTY_BITS;
0849: }
0850: return true;
0851: } else {
0852: return false;
0853: }
0854:
0855: }
0856: // Assign the cloned value as the original value
0857:
0858: // Either a changedFrequent or a null case
0859: // and the incoming one is not equal or null
0860: // then return;
0861: // This check also handles null == null case
0862: if (definingPolygonAttributes != null) {
0863: if ((this .definingPolygonAttributes.changedFrequent != 0)
0864: || (polygonAttributes != null && polygonAttributes.changedFrequent != 0))
0865: if (definingPolygonAttributes == polygonAttributes) {
0866: if (definingPolygonAttributes.compChanged != 0) {
0867: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0868: renderBin.rmUpdateList.add(this );
0869: }
0870: soleUserCompDirty |= POLYGONATTRS_DIRTY;
0871: }
0872: } else {
0873: return false;
0874: }
0875: else if (!definingPolygonAttributes
0876: .equivalent(polygonAttributes)) {
0877: return false;
0878: }
0879: } else if (polygonAttributes != null) {
0880: return false;
0881: }
0882:
0883: if (definingLineAttributes != null) {
0884: if ((this .definingLineAttributes.changedFrequent != 0)
0885: || (lineAttributes != null && lineAttributes.changedFrequent != 0))
0886: if (definingLineAttributes == lineAttributes) {
0887: if (definingLineAttributes.compChanged != 0) {
0888: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0889: renderBin.rmUpdateList.add(this );
0890: }
0891: soleUserCompDirty |= LINEATTRS_DIRTY;
0892: }
0893: } else {
0894: return false;
0895: }
0896: else if (!definingLineAttributes.equivalent(lineAttributes)) {
0897: return false;
0898: }
0899: } else if (lineAttributes != null) {
0900: return false;
0901: }
0902:
0903: if (definingPointAttributes != null) {
0904: if ((this .definingPointAttributes.changedFrequent != 0)
0905: || (pointAttributes != null && pointAttributes.changedFrequent != 0))
0906: if (definingPointAttributes == pointAttributes) {
0907: if (definingPointAttributes.compChanged != 0) {
0908: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0909: renderBin.rmUpdateList.add(this );
0910: }
0911: soleUserCompDirty |= POINTATTRS_DIRTY;
0912: }
0913: } else {
0914: return false;
0915: }
0916: else if (!definingPointAttributes
0917: .equivalent(pointAttributes)) {
0918: return false;
0919: }
0920: } else if (pointAttributes != null) {
0921: return false;
0922: }
0923:
0924: if (definingMaterial != null) {
0925: if ((this .definingMaterial.changedFrequent != 0)
0926: || (material != null && material.changedFrequent != 0))
0927: if (definingMaterial == material) {
0928: if (definingMaterial.compChanged != 0) {
0929: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0930: renderBin.rmUpdateList.add(this );
0931: }
0932: soleUserCompDirty |= MATERIAL_DIRTY;
0933: }
0934: } else {
0935: return false;
0936: }
0937: else if (!definingMaterial.equivalent(material)) {
0938: return false;
0939: }
0940: } else if (material != null) {
0941: return false;
0942: }
0943:
0944: if (definingColoringAttributes != null) {
0945: if ((this .definingColoringAttributes.changedFrequent != 0)
0946: || (coloringAttributes != null && coloringAttributes.changedFrequent != 0))
0947: if (definingColoringAttributes == coloringAttributes) {
0948: if (definingColoringAttributes.compChanged != 0) {
0949: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0950: renderBin.rmUpdateList.add(this );
0951: }
0952: soleUserCompDirty |= COLORINGATTRS_DIRTY;
0953: }
0954: } else {
0955: return false;
0956: }
0957: else if (!definingColoringAttributes
0958: .equivalent(coloringAttributes)) {
0959: return false;
0960: }
0961: } else if (coloringAttributes != null) {
0962: return false;
0963: }
0964:
0965: // if the definingTransparency is a non cloned values and the incoming
0966: // one is equivalent, then check if the component is dirty
0967: // this happens when all the RAs from this RM have been removed
0968: // but new ones are not added yet (rbin visibility) not run yet
0969: // and when there is a change in nc based on the new RA, we wil;
0970: // miss the change, doing this check will catch the change durin
0971: // new RAs insertRenderAtom
0972: if (definingTransparency != null) {
0973: if ((this .definingTransparency.changedFrequent != 0)
0974: || (transparency != null && transparency.changedFrequent != 0))
0975: if (definingTransparency == transparency) {
0976: if (definingTransparency.compChanged != 0) {
0977: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
0978: renderBin.rmUpdateList.add(this );
0979: }
0980: soleUserCompDirty |= TRANSPARENCY_DIRTY;
0981: }
0982: } else {
0983: return false;
0984: }
0985: else if (!definingTransparency.equivalent(transparency)) {
0986: return false;
0987: }
0988: } else if (transparency != null) {
0989: return false;
0990: }
0991:
0992: return (true);
0993: }
0994:
0995: public void updateRemoveRenderAtoms() {
0996: int i;
0997: RenderAtom r;
0998: RenderAtomListInfo rinfo;
0999:
1000: // Check if this renderMolecule was created and destroyed this frame.
1001: // so, no display list was created
1002: if (numRenderAtoms == 0 && removeRAs == null && addRAs == null) {
1003: textureBin.removeRenderMolecule(this );
1004: return;
1005: }
1006:
1007: while (removeRAs != null) {
1008: r = (RenderAtom) removeRAs;
1009: r.removed = null;
1010: numRenderAtoms--;
1011:
1012: // Loop thru all geometries in the renderAtom, they could
1013: // potentially be in different buckets in the rendermoleulce
1014: for (int index = 0; index < r.rListInfo.length; index++) {
1015: rinfo = r.rListInfo[index];
1016: // Don't remove null geo
1017: if (rinfo.geometry() == null)
1018: continue;
1019:
1020: if ((rinfo.groupType & RenderAtom.PRIMARY) != 0) {
1021: primaryChanged = true;
1022: if (rinfo.prev == null) { // At the head of the list
1023: primaryRenderAtomList = rinfo.next;
1024: if (rinfo.next != null) {
1025: rinfo.next.prev = null;
1026: }
1027: } else { // In the middle or at the end.
1028: rinfo.prev.next = rinfo.next;
1029: if (rinfo.next != null) {
1030: rinfo.next.prev = rinfo.prev;
1031: }
1032: }
1033:
1034: // If the molecule type is Raster, then add it to the lock list
1035: if (primaryMoleculeType == RASTER) {
1036: RasterRetained geo = (RasterRetained) rinfo
1037: .geometry();
1038: renderBin.removeGeometryFromLockList(geo);
1039: if (geo.image != null)
1040: renderBin.removeNodeComponent(geo.image);
1041:
1042: } else if ((rinfo.groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0) {
1043: if (!rinfo.renderAtom.inRenderBin()) {
1044: renderBin.removeDlistPerRinfo.add(rinfo);
1045: }
1046: }
1047: } else if ((rinfo.groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0) {
1048: if (rinfo.prev == null) { // At the head of the list
1049: separateDlistRenderAtomList = rinfo.next;
1050: if (rinfo.next != null) {
1051: rinfo.next.prev = null;
1052: }
1053: } else { // In the middle or at the end.
1054: rinfo.prev.next = rinfo.next;
1055: if (rinfo.next != null) {
1056: rinfo.next.prev = rinfo.prev;
1057: }
1058: }
1059: renderBin.removeGeometryDlist(rinfo);
1060:
1061: } else {
1062: if (rinfo.prev == null) { // At the head of the list
1063: vertexArrayRenderAtomList = rinfo.next;
1064: if (rinfo.next != null) {
1065: rinfo.next.prev = null;
1066: }
1067: } else { // In the middle or at the end.
1068: rinfo.prev.next = rinfo.next;
1069: if (rinfo.next != null) {
1070: rinfo.next.prev = rinfo.prev;
1071: }
1072: }
1073: // For indexed geometry there is no need to lock since
1074: // the mirror is changed only when the renderer is not
1075: // running
1076: // For indexed geometry, if use_coord is set, then either we
1077: // are using the index geometry as is or we will be unindexifying
1078: // on the fly, so its better to lock
1079: GeometryArrayRetained geo = (GeometryArrayRetained) rinfo
1080: .geometry();
1081: if (!(geo instanceof IndexedGeometryArrayRetained)
1082: || ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) {
1083: renderBin.removeGeometryFromLockList(geo);
1084: }
1085: }
1086: rinfo.prev = null;
1087: rinfo.next = null;
1088: }
1089: removeRAs = removeRAs.nextRemove;
1090: r.nextRemove = null;
1091: r.prevRemove = null;
1092: if (r.isOriented()) {
1093: renderBin.orientedRAs.remove(renderBin.orientedRAs
1094: .indexOf(r));
1095: }
1096:
1097: if ((textureBin.environmentSet.lightBin.geometryBackground == null)
1098: && !isOpaqueOrInOG
1099: && renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY) {
1100: renderBin.removeTransparentObject(r);
1101: }
1102: }
1103: // If this renderMolecule will not be touched for adding new RenderAtoms
1104: // then ..
1105: if (addRAs == null) {
1106: // If there are no more renderAtoms and there will be no more
1107: // renderatoms added to this renderMolecule , then remove
1108: if (numRenderAtoms == 0) {
1109: // If both lists are empty remove this renderMolecule
1110: if ((primaryMoleculeType & DLIST_MOLECULE) != 0) {
1111: renderBin.addDisplayListResourceFreeList(this );
1112: vwcBounds.set(null);
1113: displayListId = 0;
1114: displayListIdObj = null;
1115: }
1116: if (locale != renderBin.locale) {
1117: localeLocalToVworld = null;
1118: }
1119: textureBin.removeRenderMolecule(this );
1120: } else {
1121: if ((primaryMoleculeType & DLIST_MOLECULE) != 0
1122: && primaryChanged) {
1123:
1124: // If a renderAtom is added to the display list
1125: // structure then add this to the dirty list of rm
1126: // for which the display list needs to be recreated
1127: renderBin.addDirtyRenderMolecule(this );
1128: vwcBounds.set(null);
1129: rinfo = primaryRenderAtomList;
1130: while (rinfo != null) {
1131: vwcBounds
1132: .combine(rinfo.renderAtom.localeVwcBounds);
1133: rinfo = rinfo.next;
1134: }
1135: primaryChanged = false;
1136: }
1137: }
1138: }
1139: numEditingRenderAtoms = numRenderAtoms;
1140: }
1141:
1142: public void updateObject() {
1143: int i;
1144: RenderAtom renderAtom;
1145: RenderAtomListInfo r;
1146: if (textureBin == null) {
1147: return;
1148: }
1149:
1150: if (addRAs != null) {
1151: while (addRAs != null) {
1152:
1153: numRenderAtoms++;
1154: renderAtom = (RenderAtom) addRAs;
1155: renderAtom.renderMolecule = this ;
1156: renderAtom.added = null;
1157: for (int j = 0; j < renderAtom.rListInfo.length; j++) {
1158: r = (RenderAtomListInfo) renderAtom.rListInfo[j];
1159: // Don't add null geo
1160: if (r.geometry() == null)
1161: continue;
1162: r.groupType = evalRinfoGroupType(r);
1163: if ((r.groupType & RenderAtom.PRIMARY) != 0) {
1164: if ((r.groupType & RenderAtom.DLIST) != 0
1165: && primaryRenderMethod == null) {
1166: primaryMoleculeType = DLIST_MOLECULE;
1167: renderBin.renderMoleculeList.add(this );
1168:
1169: if (vwcBounds == null)
1170: vwcBounds = new BoundingBox(
1171: (BoundingBox) null);
1172: primaryRenderMethod = VirtualUniverse.mc
1173: .getDisplayListRenderMethod();
1174: // Assign a displayListId for this renderMolecule
1175: if (displayListId == 0) {
1176: displayListIdObj = VirtualUniverse.mc
1177: .getDisplayListId();
1178: displayListId = displayListIdObj
1179: .intValue();
1180: }
1181: } else if ((r.groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0
1182: && primaryRenderMethod == null) {
1183: primaryMoleculeType = SEPARATE_DLIST_PER_RINFO_MOLECULE;
1184: renderBin.renderMoleculeList.add(this );
1185: primaryRenderMethod = VirtualUniverse.mc
1186: .getDisplayListRenderMethod();
1187:
1188: }
1189: primaryChanged = true;
1190: if (primaryRenderAtomList == null) {
1191: primaryRenderAtomList = r;
1192: } else {
1193: r.next = primaryRenderAtomList;
1194: primaryRenderAtomList.prev = r;
1195: primaryRenderAtomList = r;
1196: }
1197: if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) {
1198: if (r.renderAtom.dlistIds == null) {
1199: r.renderAtom.dlistIds = new int[r.renderAtom.rListInfo.length];
1200:
1201: for (int k = 0; k < r.renderAtom.dlistIds.length; k++) {
1202: r.renderAtom.dlistIds[k] = -1;
1203: }
1204: }
1205: if (r.renderAtom.dlistIds[r.index] == -1) {
1206: r.renderAtom.dlistIds[r.index] = VirtualUniverse.mc
1207: .getDisplayListId().intValue();
1208: renderBin.addDlistPerRinfo.add(r);
1209: }
1210: }
1211:
1212: // If the molecule type is Raster, then add it to the lock list
1213: if (primaryMoleculeType == RASTER) {
1214: RasterRetained geo = (RasterRetained) r
1215: .geometry();
1216: renderBin.addGeometryToLockList(geo);
1217: if (geo.image != null)
1218: renderBin.addNodeComponent(geo.image);
1219: }
1220: } else if ((r.groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0) {
1221: if (separateDlistRenderAtomList == null) {
1222: separateDlistRenderAtomList = r;
1223: } else {
1224: r.next = separateDlistRenderAtomList;
1225: separateDlistRenderAtomList.prev = r;
1226: separateDlistRenderAtomList = r;
1227: }
1228: ((GeometryArrayRetained) r.geometry())
1229: .assignDlistId();
1230: renderBin.addGeometryDlist(r);
1231: } else {
1232: if (secondaryRenderMethod == null)
1233: secondaryRenderMethod = cachedVertexArrayRenderMethod;
1234: if (vertexArrayRenderAtomList == null) {
1235: vertexArrayRenderAtomList = r;
1236: } else {
1237: r.next = vertexArrayRenderAtomList;
1238: vertexArrayRenderAtomList.prev = r;
1239: vertexArrayRenderAtomList = r;
1240: }
1241: // For indexed geometry there is no need to lock since
1242: // the mirror is changed only when the renderer is not
1243: // running
1244: // For indexed geometry, if use_coord is set, then either we
1245: // are using the index geometry as is or we will be unindexifying
1246: // on the fly, so its better to loc
1247: GeometryArrayRetained geo = (GeometryArrayRetained) r
1248: .geometry();
1249: if (!(geo instanceof IndexedGeometryArrayRetained)
1250: || ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) {
1251: renderBin.addGeometryToLockList(geo);
1252: // Add the geometry to the dirty list only if the geometry is by
1253: // refernce and there is color and we need to use alpha
1254: // Issue 113 - ignore multiScreen
1255: if (((geo.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
1256: && (geo.c4fAllocated == 0)
1257: && ((geo.vertexFormat & GeometryArray.COLOR) != 0)
1258: && useAlpha) {
1259: renderBin
1260: .addDirtyReferenceGeometry(geo);
1261: }
1262: }
1263: }
1264: }
1265: addRAs = addRAs.nextAdd;
1266: renderAtom.nextAdd = null;
1267: renderAtom.prevAdd = null;
1268: if (renderAtom.isOriented()) {
1269: renderBin.orientedRAs.add(renderAtom);
1270:
1271: }
1272: // If transparent and not in bg geometry and is depth sorted transparency
1273: if (!isOpaqueOrInOG
1274: && (textureBin.environmentSet.lightBin.geometryBackground == null)
1275: && (renderBin.transpSortMode == View.TRANSPARENCY_SORT_GEOMETRY)) {
1276: GeometryRetained geo = null;
1277: int k = 0;
1278: while (geo == null
1279: && k < renderAtom.rListInfo.length) {
1280: geo = renderAtom.rListInfo[k].geometry();
1281: k++;
1282: }
1283: if (geo != null) {
1284: if (renderAtom.parentTInfo != null
1285: && renderAtom.parentTInfo[k - 1] != null) {
1286: renderBin.updateTransparentInfo(renderAtom);
1287: }
1288: // Newly added renderAtom
1289: else {
1290: renderBin.addTransparentObject(renderAtom);
1291: }
1292: }
1293: // Moving within the renderBin
1294:
1295: }
1296: }
1297:
1298: if ((primaryMoleculeType & DLIST_MOLECULE) != 0
1299: && primaryChanged) {
1300:
1301: // If a renderAtom is added to the display list
1302: // structure then add this to the dirty list of rm
1303: // for which the display list needs to be recreated
1304: renderBin.addDirtyRenderMolecule(this );
1305: vwcBounds.set(null);
1306: r = primaryRenderAtomList;
1307: while (r != null) {
1308: vwcBounds.combine(r.renderAtom.localeVwcBounds);
1309: r = r.next;
1310: }
1311: primaryChanged = false;
1312: }
1313:
1314: if ((onUpdateList & LOCALE_CHANGED) != 0) {
1315: handleLocaleChange();
1316: }
1317:
1318: if (locale != renderBin.locale) {
1319: translate();
1320: }
1321: } else {
1322: // The flag LOCALE_CHANGED only gets sets when there is a new additon
1323: // There are cases when RM updateObject() get called (due to addition
1324: // in renderBin - see processTransformChanged()), we need to
1325: // evaluate locale change for this case as well
1326: if (renderBin.localeChanged) {
1327: handleLocaleChange();
1328: }
1329:
1330: if (locale != renderBin.locale) {
1331: translate();
1332: }
1333:
1334: if ((onUpdateList & UPDATE_BACKGROUND_TRANSFORM) != 0) {
1335: i = localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD];
1336: localeLocalToVworld[i].getRotation(infLocalToVworld[i]);
1337: }
1338:
1339: // No new renderAtoms were added, but need to
1340: // recompute vwcBounds in response to xform change
1341: if ((onUpdateList & BOUNDS_RECOMPUTE_UPDATE) != 0) {
1342: vwcBounds.set(null);
1343: r = primaryRenderAtomList;
1344: while (r != null) {
1345: vwcBounds.combine(r.renderAtom.localeVwcBounds);
1346: r = r.next;
1347: }
1348: }
1349: }
1350:
1351: // Clear all bits except the IN_DIRTY_LIST
1352: onUpdateList &= IN_DIRTY_RENDERMOLECULE_LIST;
1353:
1354: numEditingRenderAtoms = numRenderAtoms;
1355: }
1356:
1357: boolean canBeInDisplayList(GeometryRetained geo, GeometryAtom ga) {
1358: if (ga.source.sourceNode instanceof MorphRetained) {
1359: return false;
1360: }
1361:
1362: return geo.canBeInDisplayList(ga.alphaEditable);
1363: }
1364:
1365: // If dlist will be altered due to alpha or ignoreVertexColors, then don't
1366: // put in a separate dlist that can be shared ...
1367: final boolean geoNotAltered(GeometryArrayRetained geo) {
1368: return !(((geo.vertexFormat & GeometryArray.COLOR) != 0) && (textureBin.attributeBin.ignoreVertexColors || useAlpha));
1369: }
1370:
1371: int evalRinfoGroupType(RenderAtomListInfo r) {
1372: int groupType = 0;
1373:
1374: GeometryRetained geo = r.geometry();
1375: if (geo == null)
1376: return groupType;
1377:
1378: if ((primaryMoleculeType & (COMPRESSED_MOLECULE
1379: | RASTER_MOLECULE | TEXT3D_MOLECULE | ORIENTEDSHAPE3D_MOLECULE)) != 0) {
1380: groupType = RenderAtom.OTHER;
1381: } else if (canBeInDisplayList(geo, r.renderAtom.geometryAtom)) {
1382: // if geometry is under share group we immediate set the
1383: // dlistID to something other than -1
1384: if (!((GeometryArrayRetained) geo).isShared ||
1385: // if we do a compiled and push the transform down to
1386: // Geometry, we can't share the displayList
1387: (r.renderAtom.geometryAtom.source.staticTransform != null)) {
1388: // If the molecule is already defined to be SEPARATE_DLIST_PER_RINFO_MOLECULE
1389: // continue adding in that mode even if it was switched back to
1390: // no depth sorted mode
1391: // System.err.println("isOpaqueOrInOG ="+isOpaqueOrInOG+" primaryMoleculeType ="+primaryMoleculeType+" renderBin.transpSortMode ="+renderBin.transpSortMode);
1392: if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) {
1393: groupType = RenderAtom.SEPARATE_DLIST_PER_RINFO;
1394: } else {
1395: if (isOpaqueOrInOG
1396: || renderBin.transpSortMode == View.TRANSPARENCY_SORT_NONE) {
1397: groupType = RenderAtom.DLIST;
1398: } else {
1399: groupType = RenderAtom.SEPARATE_DLIST_PER_RINFO;
1400: }
1401: }
1402:
1403: } else if (geoNotAltered((GeometryArrayRetained) r
1404: .geometry())) {
1405: groupType = RenderAtom.SEPARATE_DLIST_PER_GEO;
1406: } else {
1407: groupType = RenderAtom.VARRAY;
1408: }
1409: } else {
1410: groupType = RenderAtom.VARRAY;
1411: }
1412: return groupType;
1413: }
1414:
1415: /**
1416: * Adds the given RenderAtom to this RenderMolecule.
1417: */
1418: void addRenderAtom(RenderAtom renderAtom, RenderBin rb) {
1419: int i, n;
1420: RenderAtomListInfo r;
1421: int index;
1422:
1423: renderAtom.envSet = textureBin.environmentSet;
1424: renderAtom.renderMolecule = this ;
1425: renderAtom.dirtyMask &= ~RenderAtom.NEED_SEPARATE_LOCALE_VWC_BOUNDS;
1426:
1427: AppearanceRetained raApp = renderAtom.geometryAtom.source.appearance;
1428:
1429: MaterialRetained mat = (raApp == null) ? null : raApp.material;
1430: if (!soleUser && material != mat) {
1431: // no longer sole user
1432: material = definingMaterial;
1433: }
1434:
1435: if ((geometryType & SURFACE) != 0) {
1436: PolygonAttributesRetained pgAttrs = (raApp == null) ? null
1437: : raApp.polygonAttributes;
1438: if (!soleUser && polygonAttributes != pgAttrs) {
1439: // no longer sole user
1440: polygonAttributes = definingPolygonAttributes;
1441: }
1442:
1443: }
1444: if ((geometryType & LINE) != 0) {
1445: LineAttributesRetained lnAttrs = (raApp == null) ? null
1446: : raApp.lineAttributes;
1447: if (!soleUser && lineAttributes != lnAttrs) {
1448: // no longer sole user
1449: lineAttributes = definingLineAttributes;
1450: }
1451:
1452: }
1453: if ((geometryType & POINT) != 0) {
1454: PointAttributesRetained pnAttrs = (raApp == null) ? null
1455: : raApp.pointAttributes;
1456: if (!soleUser && pointAttributes != pnAttrs) {
1457: // no longer sole user
1458: pointAttributes = definingPointAttributes;
1459: }
1460: }
1461:
1462: ColoringAttributesRetained coAttrs = (raApp == null) ? null
1463: : raApp.coloringAttributes;
1464: if (!soleUser && coloringAttributes != coAttrs) {
1465: // no longer sole user
1466: coloringAttributes = definingColoringAttributes;
1467: }
1468:
1469: TransparencyAttributesRetained trAttrs = (raApp == null) ? null
1470: : raApp.transparencyAttributes;
1471: if (!soleUser && transparency != trAttrs) {
1472: // no longer sole user
1473: transparency = definingTransparency;
1474: }
1475:
1476: // If the renderAtom is being inserted first time, then evaluate
1477: // the groupType to determine if need separate localeVwcBounds
1478: if (!renderAtom.inRenderBin()) {
1479: for (i = 0; i < renderAtom.rListInfo.length; i++) {
1480: if (renderAtom.rListInfo[i].geometry() == null)
1481: continue;
1482: int groupType = evalRinfoGroupType(renderAtom.rListInfo[i]);
1483: if (groupType != RenderAtom.DLIST) {
1484: renderAtom.dirtyMask |= RenderAtom.NEED_SEPARATE_LOCALE_VWC_BOUNDS;
1485: }
1486: }
1487: }
1488: if (renderAtom.removed == this ) {
1489: // Remove the renderAtom from the list of removeRAs
1490: // If this is at the head of the list
1491: if (renderAtom == removeRAs) {
1492: removeRAs = renderAtom.nextRemove;
1493: if (removeRAs != null)
1494: removeRAs.prevRemove = null;
1495: renderAtom.nextRemove = null;
1496: renderAtom.prevRemove = null;
1497: }
1498: // Somewhere in the middle
1499: else {
1500: renderAtom.prevRemove.nextRemove = renderAtom.nextRemove;
1501: if (renderAtom.nextRemove != null)
1502: renderAtom.nextRemove.prevRemove = renderAtom.prevRemove;
1503: renderAtom.nextRemove = null;
1504: renderAtom.prevRemove = null;
1505: }
1506:
1507: renderAtom.removed = null;
1508: // Redo any dlist etc, because it has been added
1509: for (i = 0; i < renderAtom.rListInfo.length; i++) {
1510: if (renderAtom.rListInfo[i].geometry() == null)
1511: continue;
1512: if ((renderAtom.rListInfo[i].groupType & RenderAtom.DLIST) != 0)
1513: renderBin.addDirtyRenderMolecule(this );
1514: else if ((renderAtom.rListInfo[i].groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0) {
1515: renderBin.addDlistPerRinfo
1516: .add(renderAtom.rListInfo[i]);
1517: } else if ((renderAtom.rListInfo[i].groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0)
1518: renderBin.addGeometryDlist(renderAtom.rListInfo[i]);
1519:
1520: }
1521: if (removeRAs == null)
1522: rb.removeRenderAtomInRMList.remove(this );
1523: } else {
1524: // Add this renderAtom to the addList
1525: if (addRAs == null) {
1526: addRAs = renderAtom;
1527: renderAtom.nextAdd = null;
1528: renderAtom.prevAdd = null;
1529: } else {
1530: renderAtom.nextAdd = addRAs;
1531: renderAtom.prevAdd = null;
1532: addRAs.prevAdd = renderAtom;
1533: addRAs = renderAtom;
1534: }
1535: renderAtom.added = this ;
1536: if (onUpdateList == 0)
1537: rb.objUpdateList.add(this );
1538: onUpdateList |= NEW_RENDERATOMS_UPDATE;
1539:
1540: }
1541: if (renderBin.localeChanged && !doInfinite) {
1542: if (onUpdateList == 0)
1543: rb.objUpdateList.add(this );
1544: onUpdateList |= LOCALE_CHANGED;
1545: }
1546:
1547: // inform the texture bin that this render molecule is no longer
1548: // in zombie state
1549:
1550: if (numEditingRenderAtoms == 0) {
1551: textureBin.incrActiveRenderMolecule();
1552: }
1553: numEditingRenderAtoms++;
1554: }
1555:
1556: /**
1557: * Removes the given RenderAtom from this RenderMolecule.
1558: */
1559: void removeRenderAtom(RenderAtom r) {
1560: int index;
1561:
1562: r.renderMolecule = null;
1563: if (r.added == this ) {
1564: //Remove this renderAtom from the addRAs list
1565:
1566: // If this is at the head of the list
1567: if (r == addRAs) {
1568: addRAs = r.nextAdd;
1569: if (addRAs != null)
1570: addRAs.prevAdd = null;
1571: r.nextAdd = null;
1572: r.prevAdd = null;
1573: }
1574: // Somewhere in the middle
1575: else {
1576: r.prevAdd.nextAdd = r.nextAdd;
1577: if (r.nextAdd != null)
1578: r.nextAdd.prevAdd = r.prevAdd;
1579: r.nextAdd = null;
1580: r.prevAdd = null;
1581: }
1582:
1583: r.added = null;
1584: r.envSet = null;
1585: // If the number of renderAtoms is zero, and it is on the
1586: // update list for adding new renderatroms only (not for
1587: // bounds update), then remove this rm from the update list
1588:
1589: // Might be expensive to remove this entry from the renderBin
1590: // objUpdateList, just let it call the renderMolecule
1591: /*
1592: if (addRAs == null) {
1593: if (onUpdateList == NEW_RENDERATOMS_UPDATE){
1594: renderBin.objUpdateList.remove(renderBin.objUpdateList.indexOf(this));
1595: }
1596: onUpdateList &= ~NEW_RENDERATOMS_UPDATE;
1597: }
1598: */
1599:
1600: } else {
1601: // Add this renderAtom to the remove list
1602: if (removeRAs == null) {
1603: removeRAs = r;
1604: r.nextRemove = null;
1605: r.prevRemove = null;
1606: } else {
1607: r.nextRemove = removeRAs;
1608: r.prevRemove = null;
1609: removeRAs.prevRemove = r;
1610: removeRAs = r;
1611: }
1612: r.removed = this ;
1613: }
1614:
1615: // Add it to the removeRenderAtom List , in case the renderMolecule
1616: // needs to be removed
1617: if (!renderBin.removeRenderAtomInRMList.contains(this )) {
1618: renderBin.removeRenderAtomInRMList.add(this );
1619: }
1620:
1621: // decrement the number of editing render atoms in this render molecule
1622: numEditingRenderAtoms--;
1623:
1624: // if there is no more editing render atoms, inform the texture bin
1625: // that this render molecule is going to zombie state
1626:
1627: if (numEditingRenderAtoms == 0) {
1628: textureBin.decrActiveRenderMolecule();
1629: }
1630: }
1631:
1632: /**
1633: * Recalculates the vwcBounds for a RenderMolecule
1634: */
1635: void recalcBounds() {
1636: RenderAtomListInfo ra;
1637:
1638: if (primaryRenderMethod == VirtualUniverse.mc
1639: .getDisplayListRenderMethod()) {
1640: vwcBounds.set(null);
1641: ra = primaryRenderAtomList;
1642: while (ra != null) {
1643: vwcBounds.combine(ra.renderAtom.localeVwcBounds);
1644: ra = ra.next;
1645: }
1646: }
1647: }
1648:
1649: void evalAlphaUsage(RenderingAttributesRetained renderAttrs,
1650: TextureUnitStateRetained[] texUnits) {
1651: boolean alphaBlend, alphaTest, textureBlend = false;
1652:
1653: alphaBlend = definingTransparency != null
1654: && definingTransparency.transparencyMode != TransparencyAttributes.NONE
1655: && (VirtualUniverse.mc.isD3D() || !VirtualUniverse.mc
1656: .isD3D()
1657: && definingTransparency.transparencyMode != TransparencyAttributes.SCREEN_DOOR);
1658:
1659: if (texUnits != null) {
1660: for (int i = 0; textureBlend == false
1661: && i < texUnits.length; i++) {
1662: if (texUnits[i] != null && texUnits[i].texAttrs != null) {
1663: textureBlend = textureBlend
1664: || (texUnits[i].texAttrs.textureMode == TextureAttributes.BLEND);
1665: }
1666: }
1667: }
1668:
1669: alphaTest = renderAttrs != null
1670: && renderAttrs.alphaTestFunction != RenderingAttributes.ALWAYS;
1671:
1672: boolean oldUseAlpha = useAlpha;
1673: useAlpha = alphaBlend || alphaTest || textureBlend;
1674:
1675: if (!oldUseAlpha && useAlpha) {
1676: GeometryArrayRetained geo = null;
1677:
1678: if (vertexArrayRenderAtomList != null)
1679: geo = (GeometryArrayRetained) vertexArrayRenderAtomList
1680: .geometry();
1681:
1682: if (geo != null) {
1683: if (!(geo instanceof IndexedGeometryArrayRetained)
1684: || ((geo.vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0)) {
1685: renderBin.addGeometryToLockList(geo);
1686: // Add the geometry to the dirty list only if the geometry is by
1687: // reference and there is color and we need to use alpha
1688: // Issue 113 - ignore multiScreen
1689: if (((geo.vertexFormat & GeometryArray.BY_REFERENCE) != 0)
1690: && (geo.c4fAllocated == 0)
1691: && ((geo.vertexFormat & GeometryArray.COLOR) != 0)
1692: && useAlpha) {
1693: renderBin.addDirtyReferenceGeometry(geo);
1694: }
1695: }
1696: }
1697: }
1698: }
1699:
1700: final boolean isSwitchOn() {
1701: // The switchOn status of the entire RM can be determined
1702: // by the switchOn status of any renderAtoms below.
1703: // This is possible because renderAtoms generated from a common
1704: // switch branch are placed in the same renderMolecule
1705: if (primaryRenderAtomList != null) {
1706: return primaryRenderAtomList.renderAtom.geometryAtom.source.switchState.lastSwitchOn;
1707:
1708: }
1709:
1710: if (vertexArrayRenderAtomList != null) {
1711: return vertexArrayRenderAtomList.renderAtom.geometryAtom.source.switchState.lastSwitchOn;
1712:
1713: }
1714:
1715: if (separateDlistRenderAtomList != null) {
1716: return separateDlistRenderAtomList.renderAtom.geometryAtom.source.switchState.lastSwitchOn;
1717: }
1718: return false;
1719: }
1720:
1721: /**
1722: * Renders this RenderMolecule
1723: */
1724: boolean render(Canvas3D cv, int pass, int dirtyBits) {
1725: assert pass < 0;
1726:
1727: boolean isVisible = isSwitchOn();
1728:
1729: if (!isVisible) {
1730: return false;
1731: }
1732:
1733: isVisible = false;
1734:
1735: // include this LightBin to the to-be-updated list in Canvas
1736: cv.setStateToUpdate(Canvas3D.RENDERMOLECULE_BIT, this );
1737:
1738: boolean modeSupportDL = true;
1739: isNonUniformScale = !trans[localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]]
1740: .isCongruent();
1741: // We have to dynamically switch between using displaymode
1742: // mode or not instead of decide in canBeInDisplayList(),
1743: // since polygonAttribute can be change by editable Appearance
1744: // or editable polygonAttribute which mode we can't take
1745: // advantage of display list mode in many cases just because
1746: // there are three special cases to handle.
1747:
1748: // Another case for punting to vertex array is if pass specifies
1749: // something other than -1. That means, we are in the
1750: // multi-texturing multi-pass case. Then we'll use vertex array
1751: // instead. Or the length of the texCoordSetMap is greater than
1752: // the number of texture units supported by the Canvas, then
1753: // we'll have to punt to vertex array as well.
1754:
1755: if ((pass != TextureBin.USE_DISPLAYLIST)
1756: || (texCoordSetMapLen > cv.maxTexCoordSets)
1757: || (VirtualUniverse.mc.isD3D() && (((definingPolygonAttributes != null) && ((isQuadGeometryArray && (definingPolygonAttributes.polygonMode == PolygonAttributes.POLYGON_LINE)) || (isTriGeometryArray && (definingPolygonAttributes.polygonMode == PolygonAttributes.POLYGON_POINT)))) || cv.texLinearMode))) {
1758: modeSupportDL = false;
1759: }
1760:
1761: /*
1762: System.err.println("texCoord " + texCoordSetMapLen + " " +
1763: cv.maxTexCoordSets + " " + modeSupportDL);
1764:
1765: System.err.println("primaryMoleculeType = "+primaryMoleculeType+" primaryRenderAtomList ="+primaryRenderAtomList+" separateDlistRenderAtomList ="+separateDlistRenderAtomList+" vertexArrayRenderAtomList ="+vertexArrayRenderAtomList);
1766: */
1767: // Send down the model view only once, if its not of type text
1768: if ((primaryMoleculeType & (TEXT3D_MOLECULE | ORIENTEDSHAPE3D_MOLECULE)) == 0) {
1769:
1770: if (primaryRenderAtomList != null) {
1771: if ((primaryRenderMethod != VirtualUniverse.mc
1772: .getDisplayListRenderMethod())
1773: || modeSupportDL) {
1774: if (primaryMoleculeType != SEPARATE_DLIST_PER_RINFO_MOLECULE) {
1775:
1776: if (primaryRenderMethod.render(this , cv,
1777: primaryRenderAtomList, dirtyBits))
1778: isVisible = true;
1779: } else {
1780: if (renderBin.dlistRenderMethod
1781: .renderSeparateDlistPerRinfo(this , cv,
1782: primaryRenderAtomList,
1783: dirtyBits))
1784: isVisible = true;
1785:
1786: }
1787: } else {
1788: if (cachedVertexArrayRenderMethod.render(this , cv,
1789: primaryRenderAtomList, dirtyBits)) {
1790: isVisible = true;
1791: }
1792: }
1793: }
1794: } else { // TEXT3D or ORIENTEDSHAPE3D
1795:
1796: if (primaryRenderAtomList != null) {
1797: if (primaryRenderMethod.render(this , cv,
1798: primaryRenderAtomList, dirtyBits)) {
1799: isVisible = true;
1800: }
1801: }
1802: }
1803:
1804: if (separateDlistRenderAtomList != null) {
1805: if (modeSupportDL) {
1806: if (renderBin.dlistRenderMethod.renderSeparateDlists(
1807: this , cv, separateDlistRenderAtomList,
1808: dirtyBits)) {
1809: isVisible = true;
1810: }
1811:
1812: } else {
1813: if (cachedVertexArrayRenderMethod.render(this , cv,
1814: separateDlistRenderAtomList, dirtyBits)) {
1815: isVisible = true;
1816: }
1817: }
1818:
1819: }
1820:
1821: // XXXX: In the case of independent primitives such as quads,
1822: // it would still be better to call multi draw arrays
1823: if (vertexArrayRenderAtomList != null) {
1824: if (cachedVertexArrayRenderMethod.render(this , cv,
1825: vertexArrayRenderAtomList, dirtyBits)) {
1826: isVisible = true;
1827: }
1828: }
1829: return isVisible;
1830: }
1831:
1832: void updateAttributes(Canvas3D cv, int dirtyBits) {
1833:
1834: boolean setTransparency = false;
1835:
1836: // If this is a beginning of a frame OR diff. geometryType
1837: // then reload everything for the first rendermolecule
1838: // System.err.println("updateAttributes");
1839: int bitMask = geometryType | Canvas3D.MATERIAL_DIRTY
1840: | Canvas3D.COLORINGATTRS_DIRTY
1841: | Canvas3D.TRANSPARENCYATTRS_DIRTY;
1842:
1843: // If beginning of a frame then reload all the attributes
1844: if ((cv.canvasDirty & bitMask) != 0) {
1845: if ((geometryType & SURFACE) != 0) {
1846: if (definingPolygonAttributes == null) {
1847: cv.resetPolygonAttributes(cv.ctx);
1848: } else {
1849: definingPolygonAttributes.updateNative(cv.ctx);
1850: }
1851: cv.polygonAttributes = polygonAttributes;
1852: }
1853: if ((geometryType & LINE) != 0) {
1854: if (definingLineAttributes == null) {
1855: cv.resetLineAttributes(cv.ctx);
1856: } else {
1857: definingLineAttributes.updateNative(cv.ctx);
1858: }
1859: cv.lineAttributes = lineAttributes;
1860: }
1861: if ((geometryType & POINT) != 0) {
1862: if (definingPointAttributes == null) {
1863: cv.resetPointAttributes(cv.ctx);
1864: } else {
1865: definingPointAttributes.updateNative(cv.ctx);
1866: }
1867: cv.pointAttributes = pointAttributes;
1868: }
1869:
1870: if (definingTransparency == null) {
1871: cv.resetTransparency(cv.ctx, geometryType, polygonMode,
1872: lineAA, pointAA);
1873: } else {
1874: definingTransparency.updateNative(cv.ctx, alpha,
1875: geometryType, polygonMode, lineAA, pointAA);
1876: }
1877: cv.transparency = transparency;
1878:
1879: if (definingMaterial == null) {
1880: cv.updateMaterial(cv.ctx, red, green, blue, alpha);
1881: } else {
1882: definingMaterial.updateNative(cv.ctx, red, green, blue,
1883: alpha, enableLighting);
1884: }
1885: cv.material = material;
1886: cv.enableLighting = enableLighting;
1887:
1888: if (definingColoringAttributes == null) {
1889: cv.resetColoringAttributes(cv.ctx, red, green, blue,
1890: alpha, enableLighting);
1891: } else {
1892: definingColoringAttributes.updateNative(cv.ctx, dRed,
1893: dBlue, dGreen, alpha, enableLighting);
1894: }
1895: cv.coloringAttributes = coloringAttributes;
1896:
1897: // Use Object instead of AppearanceRetained class for
1898: // state caching optimation for memory performance
1899: cv.appHandle = appHandle;
1900: }
1901:
1902: // assuming neighbor dirty bits ORing is implemented
1903: // note that we need to set it to ALL_DIRTY at the
1904: // begining of textureBin first and only do the ORing
1905: // whenever encounter a non-visible rm
1906:
1907: else if (cv.renderMolecule != this && (dirtyBits != 0)) {
1908:
1909: // no need to download states if appHandle is the same
1910: if (cv.appHandle != appHandle) {
1911:
1912: // Check if the attribute bundle in the canvas is the same
1913: // as the attribute bundle in this renderMolecule
1914:
1915: if (cv.transparency != transparency
1916: && (dirtyBits & TRANSPARENCY_DIRTY) != 0) {
1917: setTransparency = true;
1918: if (definingTransparency == null) {
1919:
1920: cv.resetTransparency(cv.ctx, geometryType,
1921: polygonMode, lineAA, pointAA);
1922: } else {
1923: definingTransparency.updateNative(cv.ctx,
1924: alpha, geometryType, polygonMode,
1925: lineAA, pointAA);
1926: }
1927: cv.transparency = transparency;
1928: }
1929:
1930: if (setTransparency
1931: || ((cv.enableLighting != enableLighting) || (cv.material != material)
1932: && (dirtyBits & MATERIAL_DIRTY) != 0)) {
1933: if (definingMaterial == null) {
1934: cv.updateMaterial(cv.ctx, red, green, blue,
1935: alpha);
1936: } else {
1937: definingMaterial.updateNative(cv.ctx, red,
1938: green, blue, alpha, enableLighting);
1939: }
1940: cv.material = material;
1941: cv.enableLighting = enableLighting;
1942: }
1943:
1944: if (((geometryType & SURFACE) != 0)
1945: && cv.polygonAttributes != polygonAttributes
1946: && (dirtyBits & POLYGONATTRS_DIRTY) != 0) {
1947:
1948: if (definingPolygonAttributes == null) {
1949: cv.resetPolygonAttributes(cv.ctx);
1950: } else {
1951: definingPolygonAttributes.updateNative(cv.ctx);
1952: }
1953: cv.polygonAttributes = polygonAttributes;
1954: }
1955:
1956: if (((geometryType & LINE) != 0)
1957: && cv.lineAttributes != lineAttributes
1958: && (dirtyBits & LINEATTRS_DIRTY) != 0) {
1959:
1960: if (definingLineAttributes == null) {
1961: cv.resetLineAttributes(cv.ctx);
1962: } else {
1963: definingLineAttributes.updateNative(cv.ctx);
1964: }
1965: cv.lineAttributes = lineAttributes;
1966: }
1967:
1968: if (((geometryType & POINT) != 0)
1969: && cv.pointAttributes != pointAttributes
1970: && (dirtyBits & POINTATTRS_DIRTY) != 0) {
1971:
1972: if (definingPointAttributes == null) {
1973: cv.resetPointAttributes(cv.ctx);
1974: } else {
1975: definingPointAttributes.updateNative(cv.ctx);
1976: }
1977: cv.pointAttributes = pointAttributes;
1978: }
1979:
1980: // Use Object instead of AppearanceRetained class for
1981: // state caching optimation for memory performance
1982: cv.appHandle = appHandle;
1983: }
1984: // no state caching for color attrs, which can also be
1985: // changed by primitive with colors
1986: if (setTransparency
1987: || ((dirtyBits & COLORINGATTRS_DIRTY) != 0)) {
1988:
1989: if (definingColoringAttributes == null) {
1990: cv.resetColoringAttributes(cv.ctx, red, green,
1991: blue, alpha, enableLighting);
1992: } else {
1993: definingColoringAttributes.updateNative(cv.ctx,
1994: dRed, dBlue, dGreen, alpha, enableLighting);
1995:
1996: }
1997: cv.coloringAttributes = coloringAttributes;
1998: }
1999:
2000: }
2001:
2002: if ((primaryMoleculeType & (TEXT3D_MOLECULE | ORIENTEDSHAPE3D_MOLECULE)) == 0) {
2003: /* System.err.println("updateAttributes setModelViewMatrix (1)"); */
2004:
2005: Transform3D modelMatrix = trans[localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]];
2006:
2007: if (cv.modelMatrix != modelMatrix) {
2008: /* System.err.println("updateAttributes setModelViewMatrix (2)"); */
2009:
2010: cv.setModelViewMatrix(cv.ctx, cv.vworldToEc.mat,
2011: modelMatrix);
2012: }
2013: }
2014:
2015: cv.canvasDirty &= ~bitMask;
2016: cv.renderMolecule = this ;
2017: }
2018:
2019: void transparentSortRender(Canvas3D cv, int pass,
2020: TransparentRenderingInfo tinfo) {
2021: assert pass < 0;
2022:
2023: Transform3D modelMatrix = trans[localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]];
2024:
2025: // include this LightBin to the to-be-updated list in Canvas
2026: cv.setStateToUpdate(Canvas3D.RENDERMOLECULE_BIT, this );
2027:
2028: boolean modeSupportDL = true;
2029:
2030: // We have to dynamically switch between using displaymode
2031: // mode or not instead of decide in canBeInDisplayList(),
2032: // since polygonAttribute can be change by editable Appearance
2033: // or editable polygonAttribute which mode we can't take
2034: // advantage of display list mode in many cases just because
2035: // there are three special cases to handle.
2036:
2037: // Another case for punting to vertex array is if pass specifies
2038: // something other than -1. That means, we are in the
2039: // multi-texturing multi-pass case. Then we'll use vertex array
2040: // instead.
2041:
2042: if ((pass != TextureBin.USE_DISPLAYLIST)
2043: || (texCoordSetMapLen > cv.maxTexCoordSets)
2044: || (VirtualUniverse.mc.isD3D() && (((definingPolygonAttributes != null) && ((isQuadGeometryArray && (definingPolygonAttributes.polygonMode == PolygonAttributes.POLYGON_LINE)) || (isTriGeometryArray && (definingPolygonAttributes.polygonMode == PolygonAttributes.POLYGON_POINT)))) || cv.texLinearMode))) {
2045: modeSupportDL = false;
2046: }
2047:
2048: // System.err.println("r.isOpaque = "+isOpaque+" rinfo = "+tinfo.rInfo+" groupType = "+tinfo.rInfo.groupType);
2049: // Only support individual dlist or varray
2050: // If this rInfo is a part of a bigger dlist, render as VA
2051: // XXXX: What to do with Text3D, Raster, CG?
2052: if ((tinfo.rInfo.groupType & RenderAtom.SEPARATE_DLIST_PER_RINFO) != 0) {
2053: RenderAtomListInfo save = tinfo.rInfo.next;
2054: // Render only one geometry
2055: tinfo.rInfo.next = null;
2056: // System.err.println("cachedVertexArrayRenderMethod = "+cachedVertexArrayRenderMethod);
2057: // System.err.println("tinfo.rInfo = "+tinfo.rInfo);
2058: if (modeSupportDL) {
2059: renderBin.dlistRenderMethod
2060: .renderSeparateDlistPerRinfo(this , cv,
2061: tinfo.rInfo, ALL_DIRTY_BITS);
2062: } else {
2063: cachedVertexArrayRenderMethod.render(this , cv,
2064: tinfo.rInfo, ALL_DIRTY_BITS);
2065: }
2066: tinfo.rInfo.next = save;
2067: } else if ((tinfo.rInfo.groupType & (RenderAtom.VARRAY | RenderAtom.DLIST)) != 0) {
2068: RenderAtomListInfo save = tinfo.rInfo.next;
2069: // Render only one geometry
2070: tinfo.rInfo.next = null;
2071: // System.err.println("cachedVertexArrayRenderMethod = "+cachedVertexArrayRenderMethod);
2072: // System.err.println("tinfo.rInfo = "+tinfo.rInfo);
2073: cachedVertexArrayRenderMethod.render(this , cv, tinfo.rInfo,
2074: ALL_DIRTY_BITS);
2075: tinfo.rInfo.next = save;
2076: }
2077:
2078: // Only support individual dlist or varray
2079: else if ((tinfo.rInfo.groupType & RenderAtom.SEPARATE_DLIST_PER_GEO) != 0) {
2080: RenderAtomListInfo save = tinfo.rInfo.next;
2081: tinfo.rInfo.next = null;
2082: if (modeSupportDL) {
2083: renderBin.dlistRenderMethod.renderSeparateDlists(this ,
2084: cv, tinfo.rInfo, ALL_DIRTY_BITS);
2085: } else {
2086: cachedVertexArrayRenderMethod.render(this , cv,
2087: tinfo.rInfo, ALL_DIRTY_BITS);
2088: }
2089: tinfo.rInfo.next = save;
2090: } else {
2091: RenderAtomListInfo save = tinfo.rInfo.next;
2092: primaryRenderMethod.render(this , cv, primaryRenderAtomList,
2093: ALL_DIRTY_BITS);
2094: tinfo.rInfo.next = save;
2095: }
2096:
2097: }
2098:
2099: /**
2100: * This render method is used to render the transparency attributes.
2101: * It is used in the multi-texture multi-pass case to reset the
2102: * transparency attributes to what it was
2103: */
2104: void updateTransparencyAttributes(Canvas3D cv) {
2105: if (definingTransparency == null) {
2106: cv.resetTransparency(cv.ctx, geometryType, polygonMode,
2107: lineAA, pointAA);
2108: } else {
2109: definingTransparency.updateNative(cv.ctx, alpha,
2110: geometryType, polygonMode, lineAA, pointAA);
2111: }
2112: }
2113:
2114: void updateDisplayList(Canvas3D cv) {
2115: // This function only gets called when primaryRenderAtomsList are
2116: if (primaryRenderAtomList != null) {
2117: ((DisplayListRenderMethod) primaryRenderMethod)
2118: .buildDisplayList(this , cv);
2119: }
2120: }
2121:
2122: void releaseAllPrimaryDisplayListID() {
2123:
2124: if (primaryRenderAtomList != null) {
2125: if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) {
2126: RenderAtomListInfo ra = primaryRenderAtomList;
2127: int id;
2128:
2129: while (ra != null) {
2130: id = ra.renderAtom.dlistIds[ra.index];
2131:
2132: if (id > 0) {
2133: VirtualUniverse.mc
2134: .freeDisplayListId(new Integer(id));
2135: ra.renderAtom.dlistIds[ra.index] = -1;
2136: }
2137: ra = ra.next;
2138: }
2139: } else if (primaryMoleculeType == DLIST_MOLECULE) {
2140: if (displayListIdObj != null) {
2141: VirtualUniverse.mc
2142: .freeDisplayListId(displayListIdObj);
2143: displayListIdObj = null;
2144: displayListId = -1;
2145: }
2146: }
2147: }
2148:
2149: }
2150:
2151: void releaseAllPrimaryDisplayListResources(Canvas3D cv, Context ctx) {
2152: if (primaryRenderAtomList != null) {
2153: if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) {
2154: RenderAtomListInfo ra = primaryRenderAtomList;
2155: int id;
2156: while (ra != null) {
2157: id = ra.renderAtom.dlistIds[ra.index];
2158: if (id > 0) {
2159: cv.freeDisplayList(ctx, id);
2160: }
2161: ra = ra.next;
2162: }
2163: } else if (primaryMoleculeType == DLIST_MOLECULE) {
2164: if (displayListId > 0) {
2165: cv.freeDisplayList(ctx, displayListId);
2166: }
2167: }
2168: }
2169: }
2170:
2171: void updateAllPrimaryDisplayLists(Canvas3D cv) {
2172: // This function only gets called when primaryRenderAtomsList are
2173: if (primaryRenderAtomList != null) {
2174: if (primaryMoleculeType == SEPARATE_DLIST_PER_RINFO_MOLECULE) {
2175: RenderAtomListInfo ra = primaryRenderAtomList;
2176: while (ra != null) {
2177: renderBin.dlistRenderMethod.buildDlistPerRinfo(ra,
2178: this , cv);
2179: ra = ra.next;
2180: }
2181: } else if (primaryMoleculeType == DLIST_MOLECULE) {
2182: ((DisplayListRenderMethod) primaryRenderMethod)
2183: .buildDisplayList(this , cv);
2184: }
2185: }
2186: }
2187:
2188: void checkEquivalenceWithBothNeighbors(int dirtyBits) {
2189: RenderMolecule leftRm = prev;
2190: RenderMolecule rightRm = next;
2191: dirtyAttrsAcrossRms = ALL_DIRTY_BITS;
2192: boolean reload_color = true;
2193:
2194: if (prev != null) {
2195: checkEquivalenceWithLeftNeighbor(prev, dirtyBits);
2196: }
2197: if (next != null) {
2198: next.checkEquivalenceWithLeftNeighbor(this , dirtyBits);
2199: }
2200: }
2201:
2202: boolean reloadColor(RenderMolecule rm) {
2203: if (((rm.vertexFormat & GeometryArray.COLOR) == 0)
2204: || (((rm.vertexFormat & GeometryArray.COLOR) != 0) && (vertexFormat & GeometryArray.COLOR) != 0)) {
2205: return false;
2206: }
2207: return true;
2208: }
2209:
2210: void checkEquivalenceWithLeftNeighbor(RenderMolecule rm,
2211: int dirtyBits) {
2212: boolean reload_color = reloadColor(rm);
2213: // XXXX : For now ignore the dirtyBits being sent in
2214: dirtyAttrsAcrossRms = ALL_DIRTY_BITS;
2215:
2216: // There is some interdepenency between the different components
2217: // in the way it is sent down to the native code
2218: // Material is affected by transparency and coloring attrs
2219: // Transparency is affected by poly/line/pointAA
2220: // ColoringAttrs is affected by material and transaparency
2221: int materialColoringDirty = (MATERIAL_DIRTY
2222: | TRANSPARENCY_DIRTY | COLORINGATTRS_DIRTY);
2223:
2224: int transparencyDirty = (TRANSPARENCY_DIRTY
2225: | POLYGONATTRS_DIRTY | LINEATTRS_DIRTY | POINTATTRS_DIRTY);
2226:
2227: if ((dirtyAttrsAcrossRms & POLYGONATTRS_DIRTY) != 0) {
2228: if (rm.geometryType == geometryType
2229: && (rm.polygonAttributes == polygonAttributes || ((rm.definingPolygonAttributes != null) && (rm.definingPolygonAttributes
2230: .equivalent(definingPolygonAttributes)))))
2231: dirtyAttrsAcrossRms &= ~POLYGONATTRS_DIRTY;
2232:
2233: }
2234:
2235: if ((dirtyAttrsAcrossRms & POINTATTRS_DIRTY) != 0) {
2236: if (rm.geometryType == geometryType
2237: && ((rm.pointAttributes == pointAttributes) || ((rm.definingPointAttributes != null) && (rm.definingPointAttributes
2238: .equivalent(definingPointAttributes)))))
2239: dirtyAttrsAcrossRms &= ~POINTATTRS_DIRTY;
2240:
2241: }
2242:
2243: if ((dirtyAttrsAcrossRms & LINEATTRS_DIRTY) != 0) {
2244: if (rm.geometryType == geometryType
2245: && ((rm.lineAttributes == lineAttributes) || ((rm.definingLineAttributes != null) && (rm.definingLineAttributes
2246: .equivalent(definingLineAttributes)))))
2247: dirtyAttrsAcrossRms &= ~LINEATTRS_DIRTY;
2248: }
2249:
2250: if ((dirtyAttrsAcrossRms & materialColoringDirty) != 0) {
2251: if (materialEquivalent(rm, reload_color)) {
2252: dirtyAttrsAcrossRms &= ~MATERIAL_DIRTY;
2253: } else {
2254: dirtyAttrsAcrossRms |= MATERIAL_DIRTY;
2255: }
2256: }
2257:
2258: if ((dirtyAttrsAcrossRms & materialColoringDirty) != 0) {
2259: if (coloringEquivalent(rm, reload_color)) {
2260: dirtyAttrsAcrossRms &= ~COLORINGATTRS_DIRTY;
2261: } else {
2262: dirtyAttrsAcrossRms |= COLORINGATTRS_DIRTY;
2263: }
2264: }
2265:
2266: if ((dirtyAttrsAcrossRms & transparencyDirty) != 0) {
2267: if (transparencyEquivalent(rm)) {
2268: dirtyAttrsAcrossRms &= ~TRANSPARENCY_DIRTY;
2269: } else {
2270: dirtyAttrsAcrossRms |= TRANSPARENCY_DIRTY;
2271: }
2272: }
2273: }
2274:
2275: void translate() {
2276: // System.err.println("onUpdateList = "+onUpdateList+" renderBin.localeChanged = "+renderBin.localeChanged+" rm = "+this);
2277: int i = localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD];
2278:
2279: localeLocalToVworld[i].mat[0] = localToVworld[i].mat[0];
2280: localeLocalToVworld[i].mat[1] = localToVworld[i].mat[1];
2281: localeLocalToVworld[i].mat[2] = localToVworld[i].mat[2];
2282: localeLocalToVworld[i].mat[3] = localToVworld[i].mat[3]
2283: + localeTranslation.x;
2284: localeLocalToVworld[i].mat[4] = localToVworld[i].mat[4];
2285: localeLocalToVworld[i].mat[5] = localToVworld[i].mat[5];
2286: localeLocalToVworld[i].mat[6] = localToVworld[i].mat[6];
2287: localeLocalToVworld[i].mat[7] = localToVworld[i].mat[7]
2288: + localeTranslation.y;
2289: localeLocalToVworld[i].mat[8] = localToVworld[i].mat[8];
2290: localeLocalToVworld[i].mat[9] = localToVworld[i].mat[9];
2291: localeLocalToVworld[i].mat[10] = localToVworld[i].mat[10];
2292: localeLocalToVworld[i].mat[11] = localToVworld[i].mat[11]
2293: + localeTranslation.z;
2294: localeLocalToVworld[i].mat[12] = localToVworld[i].mat[12];
2295: localeLocalToVworld[i].mat[13] = localToVworld[i].mat[13];
2296: localeLocalToVworld[i].mat[14] = localToVworld[i].mat[14];
2297: localeLocalToVworld[i].mat[15] = localToVworld[i].mat[15];
2298: // System.err.println("rm = "+this+" localTovworld = "+localeLocalToVworld[i]+" localeTranslation = "+localeTranslation);
2299: }
2300:
2301: boolean isOpaque() {
2302: if (!VirtualUniverse.mc.isD3D()) {
2303: // D3D doesn't support line/point antialiasing
2304: if ((geometryType & SURFACE) != 0) {
2305: if (definingPolygonAttributes != null) {
2306: if ((definingPolygonAttributes.polygonMode == PolygonAttributes.POLYGON_POINT)
2307: && (definingPointAttributes != null)
2308: && definingPointAttributes.pointAntialiasing) {
2309: return false;
2310: } else if ((definingPolygonAttributes.polygonMode == PolygonAttributes.POLYGON_LINE)
2311: && (definingLineAttributes != null)
2312: && definingLineAttributes.lineAntialiasing) {
2313: return false;
2314: }
2315: }
2316: } else if ((geometryType & POINT) != 0) {
2317: if ((definingPointAttributes != null)
2318: && definingPointAttributes.pointAntialiasing) {
2319: return false;
2320: }
2321: } else if ((geometryType & LINE) != 0) {
2322: if ((definingLineAttributes != null)
2323: && definingLineAttributes.lineAntialiasing) {
2324: return false;
2325: }
2326: }
2327: return ((definingTransparency == null)
2328: || (definingTransparency.transparencyMode == TransparencyAttributes.NONE) || (definingTransparency.transparencyMode == TransparencyAttributes.SCREEN_DOOR));
2329: } else {
2330: return ((definingTransparency == null) || (definingTransparency.transparencyMode == TransparencyAttributes.NONE));
2331: }
2332: }
2333:
2334: boolean updateNodeComponent() {
2335: // System.err.println("soleUser = "+soleUser+" rm = "+this);
2336: if ((soleUserCompDirty & MATERIAL_DIRTY) != 0) {
2337: // Note: this RM is a soleUser(only then this function is called)
2338: // and if definingMaterial == material, then the material is freq
2339: // changed and therefore is not cloned, only other time it can be
2340: // same is when an equivalent material is added in and this can
2341: // never be true when a bin is a soleUser of a appearance
2342:
2343: // Evaluate before replacing the old Value
2344: if (soleUser) {
2345: boolean cloned = definingMaterial != null
2346: && definingMaterial != material;
2347: // System.err.println("===>Rm = "+this);
2348:
2349: // System.err.println("===> updating node component, cloned = "+cloned+" material.changedFrequent = "+material.changedFrequent);
2350: // System.err.println("===> definingMaterial ="+definingMaterial+" material = "+material);
2351:
2352: material = ((AppearanceRetained) appHandle).material;
2353: if (material == null)
2354: definingMaterial = null;
2355: else {
2356: if (material.changedFrequent != 0) {
2357: definingMaterial = material;
2358: } else {
2359: // If the one replaced is a cloned copy, then ..
2360: if (cloned) {
2361: definingMaterial.set(material);
2362: } else {
2363: definingMaterial = (MaterialRetained) material
2364: .clone();
2365: }
2366: }
2367: }
2368: }
2369: evalMaterialCachedState();
2370: }
2371: if ((soleUserCompDirty & LINEATTRS_DIRTY) != 0) {
2372: if (soleUser) {
2373: // Evaluate before replacing the old Value
2374: boolean cloned = definingLineAttributes != null
2375: && definingLineAttributes != lineAttributes;
2376:
2377: lineAttributes = ((AppearanceRetained) appHandle).lineAttributes;
2378: if (lineAttributes == null) {
2379: lineAA = false;
2380: definingLineAttributes = null;
2381: } else {
2382: if (lineAttributes.changedFrequent != 0) {
2383: definingLineAttributes = lineAttributes;
2384: } else {
2385: // If the one replaced is a cloned copy, then ..
2386: if (cloned) {
2387: definingLineAttributes.set(lineAttributes);
2388: } else {
2389: definingLineAttributes = (LineAttributesRetained) lineAttributes
2390: .clone();
2391: }
2392: }
2393: lineAA = definingLineAttributes.lineAntialiasing;
2394: }
2395: } else {
2396: lineAA = definingLineAttributes.lineAntialiasing;
2397: }
2398: }
2399: if ((soleUserCompDirty & POINTATTRS_DIRTY) != 0) {
2400: if (soleUser) {
2401: // Evaluate before replacing the old Value
2402: boolean cloned = definingPointAttributes != null
2403: && definingPointAttributes != pointAttributes;
2404:
2405: pointAttributes = ((AppearanceRetained) appHandle).pointAttributes;
2406: if (pointAttributes == null) {
2407: pointAA = false;
2408: definingPointAttributes = null;
2409: } else {
2410: if (pointAttributes.changedFrequent != 0) {
2411: definingPointAttributes = pointAttributes;
2412: } else {
2413: // If the one replaced is a cloned copy, then ..
2414: if (cloned) {
2415: definingPointAttributes
2416: .set(pointAttributes);
2417: } else {
2418: definingPointAttributes = (PointAttributesRetained) pointAttributes
2419: .clone();
2420: }
2421: }
2422: pointAA = definingPointAttributes.pointAntialiasing;
2423: }
2424: } else {
2425: pointAA = definingPointAttributes.pointAntialiasing;
2426: }
2427:
2428: }
2429: if ((soleUserCompDirty & POLYGONATTRS_DIRTY) != 0) {
2430: if (soleUser) {
2431: // Evaluate before replacing the old Value
2432: boolean cloned = definingPolygonAttributes != null
2433: && definingPolygonAttributes != polygonAttributes;
2434:
2435: polygonAttributes = ((AppearanceRetained) appHandle).polygonAttributes;
2436:
2437: if (polygonAttributes == null) {
2438: polygonMode = PolygonAttributes.POLYGON_FILL;
2439: definingPolygonAttributes = null;
2440: } else {
2441: if (polygonAttributes.changedFrequent != 0) {
2442: definingPolygonAttributes = polygonAttributes;
2443: } else {
2444: // If the one replaced is a cloned copy, then ..
2445: if (cloned) {
2446: definingPolygonAttributes
2447: .set(polygonAttributes);
2448: } else {
2449: definingPolygonAttributes = (PolygonAttributesRetained) polygonAttributes
2450: .clone();
2451: }
2452: }
2453:
2454: polygonMode = definingPolygonAttributes.polygonMode;
2455: }
2456: } else {
2457: polygonMode = definingPolygonAttributes.polygonMode;
2458: }
2459:
2460: if (polygonMode == PolygonAttributes.POLYGON_LINE) {
2461: geometryType |= LINE;
2462: } else if (polygonMode == PolygonAttributes.POLYGON_POINT) {
2463: geometryType |= POINT;
2464: }
2465: }
2466:
2467: if ((soleUserCompDirty & TRANSPARENCY_DIRTY) != 0) {
2468: if (soleUser) {
2469: // Evaluate before replacing the old Value
2470: boolean cloned = definingTransparency != null
2471: && definingTransparency != transparency;
2472: transparency = ((AppearanceRetained) appHandle).transparencyAttributes;
2473:
2474: if (transparency == null) {
2475: alpha = 1.0f;
2476: definingTransparency = null;
2477: } else {
2478: if (transparency.changedFrequent != 0) {
2479: definingTransparency = transparency;
2480: } else {
2481: // If the one replaced is a cloned copy, then ..
2482: if (cloned) {
2483: definingTransparency.set(transparency);
2484: } else {
2485: definingTransparency = (TransparencyAttributesRetained) transparency
2486: .clone();
2487: }
2488: }
2489:
2490: alpha = 1.0f - definingTransparency.transparency;
2491: }
2492: } else {
2493: alpha = 1.0f - definingTransparency.transparency;
2494: }
2495: }
2496:
2497: if ((soleUserCompDirty & COLORINGATTRS_DIRTY) != 0) {
2498: if (soleUser) {
2499: // Evaluate before replacing the old Value
2500: boolean cloned = definingColoringAttributes != null
2501: && definingColoringAttributes != coloringAttributes;
2502:
2503: coloringAttributes = ((AppearanceRetained) appHandle).coloringAttributes;
2504: // System.err.println("coloringAttributes and soleUser");
2505: // System.err.println("coloringAttributes ="+coloringAttributes);
2506: if (coloringAttributes == null) {
2507: definingColoringAttributes = null;
2508: red = 1.0f;
2509: green = 1.0f;
2510: blue = 1.0f;
2511: } else {
2512: // System.err.println("coloringAttributes.changedFrequent = "+coloringAttributes.changedFrequent );
2513: if (coloringAttributes.changedFrequent != 0) {
2514: definingColoringAttributes = coloringAttributes;
2515: } else {
2516: // If the one replaced is a cloned copy, then ..
2517: if (cloned) {
2518: definingColoringAttributes
2519: .set(coloringAttributes);
2520: } else {
2521: definingColoringAttributes = (ColoringAttributesRetained) coloringAttributes
2522: .clone();
2523: }
2524: }
2525: red = definingColoringAttributes.color.x;
2526: green = definingColoringAttributes.color.y;
2527: blue = definingColoringAttributes.color.z;
2528: }
2529: } else {
2530: red = definingColoringAttributes.color.x;
2531: green = definingColoringAttributes.color.y;
2532: blue = definingColoringAttributes.color.z;
2533: }
2534: }
2535: // System.err.println("rm = "+this+"red = "+red+" green = "+green+" blue = "+blue);
2536: boolean newVal = isOpaque() || inOrderedGroup;
2537: return (isOpaqueOrInOG != newVal);
2538:
2539: }
2540:
2541: // Issue 129: method to add or remove all rendering atoms in this
2542: // RenderMolecule to or from the transparent info list when we are
2543: // in depth sorted transparency mode and the RenderMolecule
2544: // changes from opaque to transparent or vice versa.
2545: void addRemoveTransparentObject(RenderBin renderBin, boolean add) {
2546: addRemoveTransparentObject(renderBin, add,
2547: primaryRenderAtomList);
2548: addRemoveTransparentObject(renderBin, add,
2549: separateDlistRenderAtomList);
2550: addRemoveTransparentObject(renderBin, add,
2551: vertexArrayRenderAtomList);
2552: }
2553:
2554: private void addRemoveTransparentObject(RenderBin renderBin,
2555: boolean add, RenderAtomListInfo rinfo) {
2556: while (rinfo != null) {
2557: if (add) {
2558: renderBin.addTransparentObject(rinfo.renderAtom);
2559: } else {
2560: renderBin.removeTransparentObject(rinfo.renderAtom);
2561: }
2562: rinfo = rinfo.next;
2563: }
2564: }
2565:
2566: void evalMaterialCachedState() {
2567: if (definingMaterial == null) {
2568: enableLighting = false;
2569: ;
2570: definingMaterial = null;
2571: dRed = 1.0f;
2572: dGreen = 1.0f;
2573: dBlue = 1.0f;
2574: } else {
2575: if ((geometryType & RASTER) != 0) {
2576: enableLighting = false;
2577: dRed = 1.0f;
2578: dGreen = 1.0f;
2579: dBlue = 1.0f;
2580: } else {
2581: if (normalPresent)
2582: enableLighting = definingMaterial.lightingEnable;
2583: else
2584: enableLighting = false;
2585: dRed = definingMaterial.diffuseColor.x;
2586: dGreen = definingMaterial.diffuseColor.y;
2587: dBlue = definingMaterial.diffuseColor.z;
2588: }
2589: }
2590: }
2591:
2592: void markBitsAsDirty(int leftBits, int rightBits) {
2593: if (prev != null) {
2594: checkEquivalenceWithLeftNeighbor(prev, leftBits);
2595: prev.soleUserCompDirty &= ~ALL_DIRTY_BITS;
2596: } else if (prevMap != null) {
2597: checkEquivalenceWithLeftNeighbor(prevMap, leftBits);
2598: prevMap.soleUserCompDirty &= ~ALL_DIRTY_BITS;
2599: }
2600: if (next != null) {
2601: if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2602: next.checkEquivalenceWithLeftNeighbor(this , rightBits);
2603: } else {
2604: next.soleUserCompDirty = rightBits;
2605: }
2606: } else if (nextMap != null) {
2607: if ((nextMap.soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2608: nextMap.checkEquivalenceWithLeftNeighbor(this ,
2609: rightBits);
2610: } else {
2611: nextMap.soleUserCompDirty = rightBits;
2612: }
2613: }
2614:
2615: }
2616:
2617: void handleMaterialEquivalence() {
2618: // Check if it has equivalent material to any of the "non-dirty"
2619: // renderMolecules before this one
2620: RenderMolecule curPrevRm = null;
2621: RenderMolecule curNextRm = null;
2622: boolean found = false;
2623: int leftBits = ALL_DIRTY_BITS;
2624: int rightBits = ALL_DIRTY_BITS;
2625: if (prev != null) {
2626: curPrevRm = prev.prev;
2627: if (materialEquivalent(prev, reloadColor(prev))) {
2628: found = true;
2629: leftBits = (((soleUserCompDirty | prev.soleUserCompDirty) & ALL_DIRTY_BITS) & ~MATERIAL_DIRTY);
2630: rightBits = (soleUserCompDirty & ALL_DIRTY_BITS);
2631: markBitsAsDirty(leftBits, rightBits);
2632: }
2633: } else if (!found && next != null) {
2634: curNextRm = next.next;
2635:
2636: if (materialEquivalent(next, reloadColor(next))) {
2637: found = true;
2638: int bits = 0;
2639: if (prev != null)
2640: bits = prev.soleUserCompDirty;
2641: else if (prevMap != null)
2642: bits = prevMap.soleUserCompDirty;
2643:
2644: leftBits = ((soleUserCompDirty | bits) & ALL_DIRTY_BITS);
2645: rightBits = ((soleUserCompDirty & ALL_DIRTY_BITS) & ~MATERIAL_DIRTY);
2646: markBitsAsDirty(leftBits, rightBits);
2647:
2648: }
2649: }
2650: // try place it next to a equivalent material on the left
2651: while (!found && curPrevRm != null) {
2652: if (materialEquivalent(curPrevRm, reloadColor(curPrevRm))) {
2653: found = true;
2654: // Remove the renderMolecule from it place
2655: prev.next = next;
2656: prev.nextMap = nextMap;
2657: if (next != null) {
2658: next.prev = prev;
2659: if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2660: next.checkEquivalenceWithLeftNeighbor(prev,
2661: ALL_DIRTY_BITS);
2662: } else {
2663: next.soleUserCompDirty = ALL_DIRTY_BITS;
2664: }
2665: } else if (nextMap != null) {
2666: nextMap.prevMap = prev;
2667: if ((nextMap.soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2668: nextMap.checkEquivalenceWithLeftNeighbor(prev,
2669: ALL_DIRTY_BITS);
2670: } else {
2671: nextMap.soleUserCompDirty |= ALL_DIRTY_BITS;
2672: }
2673: }
2674:
2675: // Insert it after the equivalent RM
2676: next = curPrevRm.next;
2677: nextMap = curPrevRm.nextMap;
2678: curPrevRm.nextMap = null;
2679: if (next != null) {
2680: next.prev = this ;
2681: } else if (nextMap != null) {
2682: nextMap.prevMap = this ;
2683: }
2684: prev = curPrevRm;
2685: curPrevRm.next = this ;
2686: leftBits = (ALL_DIRTY_BITS & ~MATERIAL_DIRTY);
2687: markBitsAsDirty(leftBits, ALL_DIRTY_BITS);
2688: }
2689: curPrevRm = curPrevRm.prev;
2690: }
2691:
2692: // Check if it has equivalent material to any of the renderMolecules after
2693: // this one
2694: while (!found && curNextRm != null) {
2695: if (materialEquivalent(curNextRm, reloadColor(curNextRm))) {
2696: found = true;
2697: // switch the pointers
2698: next.prev = prev;
2699: next.prevMap = prevMap;
2700: if (prev != null) {
2701: prev.next = next;
2702: if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2703: next.checkEquivalenceWithLeftNeighbor(prev,
2704: ALL_DIRTY_BITS);
2705: } else {
2706: next.soleUserCompDirty = ALL_DIRTY_BITS;
2707: }
2708: } else if (prevMap != null) {
2709: prevMap.nextMap = next;
2710: if ((next.soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2711: next.checkEquivalenceWithLeftNeighbor(prevMap,
2712: ALL_DIRTY_BITS);
2713: } else {
2714: next.soleUserCompDirty = ALL_DIRTY_BITS;
2715: }
2716: }
2717:
2718: // Insert it before the equivalent RM
2719: prev = curNextRm.prev;
2720: prevMap = curNextRm.prevMap;
2721: curNextRm.prevMap = null;
2722: if (curNextRm.prev != null) {
2723: curNextRm.prev.next = this ;
2724: } else if (prevMap != null) {
2725: prevMap.nextMap = this ;
2726: }
2727: next = curNextRm;
2728: curNextRm.prev = this ;
2729: rightBits = (ALL_DIRTY_BITS & ~MATERIAL_DIRTY);
2730: markBitsAsDirty(ALL_DIRTY_BITS, rightBits);
2731: }
2732: curNextRm = curNextRm.next;
2733: }
2734: // If there are no equivalent ones, evaluate the dirty bits in the current place
2735: if (!found) {
2736: if (prev != null) {
2737: leftBits = ((soleUserCompDirty | prev.soleUserCompDirty) & ALL_DIRTY_BITS);
2738: } else if (prevMap != null) {
2739: leftBits = ((soleUserCompDirty | prevMap.soleUserCompDirty) & ALL_DIRTY_BITS);
2740: }
2741: if (next != null) {
2742: rightBits = ((soleUserCompDirty | next.soleUserCompDirty) & ALL_DIRTY_BITS);
2743: } else if (nextMap != null) {
2744: rightBits = ((soleUserCompDirty | nextMap.soleUserCompDirty) & ALL_DIRTY_BITS);
2745: }
2746: markBitsAsDirty(leftBits, rightBits);
2747: }
2748:
2749: }
2750:
2751: void reEvaluateEquivalence() {
2752: // If Material changed, reInsert next to a equivalent material under
2753: // the same transform group
2754: // to prevent unnecessary material download
2755: // This RM may have been evaluated due to an other RM is the same list
2756: // If not, ...
2757: if ((soleUserCompDirty & ALL_DIRTY_BITS) != 0) {
2758: if ((soleUserCompDirty & MATERIAL_DIRTY) != 0) {
2759: handleMaterialEquivalence();
2760: } else {
2761: int dirtyBits = (soleUserCompDirty & ALL_DIRTY_BITS);
2762: if (prev != null) {
2763: checkEquivalenceWithLeftNeighbor(
2764: prev,
2765: ((dirtyBits | prev.soleUserCompDirty) & ALL_DIRTY_BITS));
2766: prev.soleUserCompDirty = 0;
2767: } else if (prevMap != null) {
2768: checkEquivalenceWithLeftNeighbor(
2769: prevMap,
2770: ((dirtyBits | prevMap.soleUserCompDirty) & ALL_DIRTY_BITS));
2771: prevMap.soleUserCompDirty = 0;
2772: }
2773: if (next != null) {
2774: next
2775: .checkEquivalenceWithLeftNeighbor(
2776: this ,
2777: ((next.soleUserCompDirty | soleUserCompDirty) & ALL_DIRTY_BITS));
2778: } else if (nextMap != null) {
2779: nextMap
2780: .checkEquivalenceWithLeftNeighbor(
2781: this ,
2782: ((nextMap.soleUserCompDirty | soleUserCompDirty) & ALL_DIRTY_BITS));
2783: }
2784: }
2785: }
2786: soleUserCompDirty &= ~ALL_DIRTY_BITS;
2787: }
2788:
2789: boolean materialEquivalent(RenderMolecule rm, boolean reloadColor) {
2790: if (!reloadColor) {
2791: if (((this .material == rm.material) || ((rm.definingMaterial != null) && (rm.definingMaterial
2792: .equivalent(definingMaterial))))
2793: && rm.alpha == alpha
2794: && enableLighting == rm.enableLighting
2795: && (enableLighting || (!enableLighting
2796: && rm.red == red && rm.green == green && rm.blue == blue))) {
2797: return true;
2798: }
2799: }
2800: return false;
2801: }
2802:
2803: boolean coloringEquivalent(RenderMolecule rm, boolean reload_color) {
2804: if (!reload_color) {
2805: if (((rm.coloringAttributes == coloringAttributes) || ((rm.definingColoringAttributes != null) && (rm.definingColoringAttributes
2806: .equivalent(definingColoringAttributes))))
2807: && (!enableLighting || (enableLighting && (dRed == rm.dRed
2808: && dBlue == rm.dBlue && dGreen == rm.dGreen)))) {
2809: return true;
2810: }
2811: }
2812: return false;
2813: }
2814:
2815: boolean transparencyEquivalent(RenderMolecule rm) {
2816: if (((rm.transparency == transparency) || ((rm.definingTransparency != null) && (rm.definingTransparency
2817: .equivalent(definingTransparency)))
2818: && (rm.definingTransparency.transparencyMode < TransparencyAttributes.SCREEN_DOOR && blendOn() == rm
2819: .blendOn()))) {
2820: return true;
2821: }
2822: return false;
2823: }
2824:
2825: boolean blendOn() {
2826: if (lineAA
2827: && ((((geometryType & LINE) != 0) || polygonMode == PolygonAttributes.POLYGON_LINE))) {
2828: return true;
2829: }
2830: if (pointAA
2831: && ((((geometryType & POINT) != 0) || polygonMode == PolygonAttributes.POLYGON_POINT))) {
2832: return true;
2833: }
2834: return false;
2835: }
2836:
2837: VirtualUniverse getVirtualUniverse() {
2838: return null;
2839: }
2840:
2841: void handleLocaleChange() {
2842: if (locale == renderBin.locale) {
2843: if (localToVworld != localeLocalToVworld) {
2844: localeLocalToVworld = localToVworld;
2845: localeTranslation = null;
2846: }
2847: } else {
2848: // Using the localToVworl then, go back to making a new copy
2849: if (localeTranslation == null) {
2850: localeLocalToVworld = new Transform3D[2];
2851: localeLocalToVworld[0] = new Transform3D();
2852: localeLocalToVworld[1] = new Transform3D();
2853:
2854: localeTranslation = new Vector3d();
2855: locale.hiRes.difference(renderBin.locale.hiRes,
2856: localeTranslation);
2857: translate();
2858: int i = localToVworldIndex[NodeRetained.CURRENT_LOCAL_TO_VWORLD];
2859:
2860: localeLocalToVworld[i].mat[0] = localToVworld[i].mat[0];
2861: localeLocalToVworld[i].mat[1] = localToVworld[i].mat[1];
2862: localeLocalToVworld[i].mat[2] = localToVworld[i].mat[2];
2863: localeLocalToVworld[i].mat[3] = localToVworld[i].mat[3]
2864: + localeTranslation.x;
2865: localeLocalToVworld[i].mat[4] = localToVworld[i].mat[4];
2866: localeLocalToVworld[i].mat[5] = localToVworld[i].mat[5];
2867: localeLocalToVworld[i].mat[6] = localToVworld[i].mat[6];
2868: localeLocalToVworld[i].mat[7] = localToVworld[i].mat[7]
2869: + localeTranslation.y;
2870: localeLocalToVworld[i].mat[8] = localToVworld[i].mat[8];
2871: localeLocalToVworld[i].mat[9] = localToVworld[i].mat[9];
2872: localeLocalToVworld[i].mat[10] = localToVworld[i].mat[10];
2873: localeLocalToVworld[i].mat[11] = localToVworld[i].mat[11]
2874: + localeTranslation.z;
2875: localeLocalToVworld[i].mat[12] = localToVworld[i].mat[12];
2876: localeLocalToVworld[i].mat[13] = localToVworld[i].mat[13];
2877: localeLocalToVworld[i].mat[14] = localToVworld[i].mat[14];
2878: localeLocalToVworld[i].mat[15] = localToVworld[i].mat[15];
2879: }
2880: }
2881:
2882: trans = localeLocalToVworld;
2883: }
2884:
2885: /**
2886: * updateNodeComponentCheck is called for each soleUser RenderMolecule
2887: * into which new renderAtom has been added. This method is called before
2888: * updateNodeComponent() to allow RenderMolecule to catch any node
2889: * component changes that have been missed because the changes
2890: * come when there is no active renderAtom associated with the
2891: * TextureBin. See bug# 4503926 for details.
2892: */
2893: public void updateNodeComponentCheck() {
2894:
2895: // If the renderMolecule has been removed, do nothing ..
2896: if ((onUpdateList & ON_UPDATE_CHECK_LIST) == 0)
2897: return;
2898:
2899: onUpdateList &= ~ON_UPDATE_CHECK_LIST;
2900: NodeComponentRetained nc = (NodeComponentRetained) appHandle;
2901: if ((nc.compChanged & RM_COMPONENTS) != 0) {
2902: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2903: renderBin.rmUpdateList.add(this );
2904: }
2905: soleUserCompDirty |= (nc.compChanged & RM_COMPONENTS);
2906: }
2907: if (definingPolygonAttributes != null
2908: && definingPolygonAttributes == polygonAttributes) {
2909: if (definingPolygonAttributes.compChanged != 0) {
2910: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2911: renderBin.rmUpdateList.add(this );
2912: }
2913: soleUserCompDirty |= POLYGONATTRS_DIRTY;
2914: }
2915: }
2916: if (definingLineAttributes != null
2917: && definingLineAttributes == lineAttributes) {
2918: if (definingLineAttributes.compChanged != 0) {
2919: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2920: renderBin.rmUpdateList.add(this );
2921: }
2922: soleUserCompDirty |= LINEATTRS_DIRTY;
2923: }
2924: }
2925: if (definingPointAttributes != null
2926: && definingPointAttributes.compChanged != 0) {
2927: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2928: renderBin.rmUpdateList.add(this );
2929: }
2930: soleUserCompDirty |= POINTATTRS_DIRTY;
2931: }
2932:
2933: if (definingMaterial != null && definingMaterial == material) {
2934: if (definingMaterial.compChanged != 0) {
2935: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2936: renderBin.rmUpdateList.add(this );
2937: }
2938: soleUserCompDirty |= MATERIAL_DIRTY;
2939: }
2940: }
2941:
2942: if (definingColoringAttributes != null
2943: && definingColoringAttributes == coloringAttributes) {
2944: if (definingColoringAttributes.compChanged != 0) {
2945: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2946: renderBin.rmUpdateList.add(this );
2947: }
2948: soleUserCompDirty |= COLORINGATTRS_DIRTY;
2949: }
2950: }
2951:
2952: if (definingTransparency != null
2953: && definingTransparency == transparency) {
2954: if (definingTransparency.compChanged != 0) {
2955: if ((soleUserCompDirty & ALL_DIRTY_BITS) == 0) {
2956: renderBin.rmUpdateList.add(this);
2957: }
2958: soleUserCompDirty |= TRANSPARENCY_DIRTY;
2959: }
2960: }
2961: }
2962: }
|