Source Code Cross Referenced for Text3DRetained.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: Text3DRetained.java,v $
0003:         *
0004:         * Copyright 1998-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:31 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import javax.vecmath.*;
0035:        import java.awt.font.*;
0036:        import java.awt.*;
0037:        import java.awt.geom.Rectangle2D;
0038:        import java.util.ArrayList;
0039:
0040:        /**
0041:         * Implements Text3D class.
0042:         */
0043:        class Text3DRetained extends GeometryRetained {
0044:            /**
0045:             * Packaged scope variables needed for implementation
0046:             */
0047:            Font3D font3D = null;
0048:            String string = null;
0049:            Point3f position = new Point3f(0.0f, 0.0f, 0.0f);
0050:            int alignment = Text3D.ALIGN_FIRST, path = Text3D.PATH_RIGHT;
0051:            float charSpacing = 0.0f;
0052:            int numChars = 0;
0053:            static final int targetThreads = (J3dThread.UPDATE_TRANSFORM
0054:                    | J3dThread.UPDATE_GEOMETRY | J3dThread.UPDATE_RENDER);
0055:            /**
0056:             * The temporary transforms for this Text3D
0057:             */
0058:            Transform3D[] charTransforms = new Transform3D[0];
0059:
0060:            /**
0061:             * A cached list of geometry arrays for the current settings
0062:             */
0063:            GeometryArrayRetained[] geometryList = new GeometryArrayRetained[0];
0064:            GlyphVector[] glyphVecs = new GlyphVector[0];
0065:
0066:            /**
0067:             * Bounding box data for this text string.
0068:             */
0069:            Point3d lower = new Point3d();
0070:            Point3d upper = new Point3d();
0071:
0072:            /**
0073:             * An Array list used for messages
0074:             */
0075:            ArrayList newGeometryAtomList = new ArrayList();
0076:            ArrayList oldGeometryAtomList = new ArrayList();
0077:
0078:            /**
0079:             * temporary model view matrix for immediate mode only
0080:             */
0081:            Transform3D vpcToEc;
0082:            Transform3D drawTransform;
0083:
0084:            Text3DRetained() {
0085:                this .geoType = GEO_TYPE_TEXT3D;
0086:            }
0087:
0088:            synchronized void computeBoundingBox() {
0089:                Point3d l = new Point3d();
0090:                Point3d u = new Point3d();
0091:                Vector3f location = new Vector3f(this .position);
0092:                int i, k = 0, numTotal = 0;
0093:                double width = 0, height = 0;
0094:                Rectangle2D bounds;
0095:
0096:                //Reset bounds data 
0097:                l.set(location);
0098:                u.set(location);
0099:
0100:                if (numChars != 0) {
0101:                    // Set loop counters based on path type
0102:                    if (path == Text3D.PATH_RIGHT || path == Text3D.PATH_UP) {
0103:                        k = 0;
0104:                        numTotal = numChars + 1;
0105:                    } else if (path == Text3D.PATH_LEFT
0106:                            || path == Text3D.PATH_DOWN) {
0107:                        k = 1;
0108:                        numTotal = numChars;
0109:                        // Reset bounds to bounding box if first character
0110:                        bounds = glyphVecs[0].getVisualBounds();
0111:                        u.x += bounds.getWidth();
0112:                        u.y += bounds.getHeight();
0113:                    }
0114:
0115:                    for (i = 1; i < numTotal; i++, k++) {
0116:                        width = glyphVecs[k].getLogicalBounds().getWidth();
0117:                        bounds = glyphVecs[k].getVisualBounds();
0118:                        // 'switch' could be outside loop with little hacking,
0119:                        width += charSpacing;
0120:                        height = bounds.getHeight();
0121:
0122:                        switch (this .path) {
0123:                        case Text3D.PATH_RIGHT:
0124:                            u.x += (width);
0125:                            if (u.y < (height + location.y)) {
0126:                                u.y = location.y + height;
0127:                            }
0128:                            break;
0129:                        case Text3D.PATH_LEFT:
0130:                            l.x -= (width);
0131:                            if (u.y < (height + location.y)) {
0132:                                u.y = location.y + height;
0133:                            }
0134:                            break;
0135:                        case Text3D.PATH_UP:
0136:                            u.y += height;
0137:                            if (u.x < (bounds.getWidth() + location.x)) {
0138:                                u.x = location.x + bounds.getWidth();
0139:                            }
0140:                            break;
0141:                        case Text3D.PATH_DOWN:
0142:                            l.y -= height;
0143:                            if (u.x < (bounds.getWidth() + location.x)) {
0144:                                u.x = location.x + bounds.getWidth();
0145:                            }
0146:                            break;
0147:                        }
0148:                    }
0149:
0150:                    // Handle string alignment. ALIGN_FIRST is handled by default 
0151:                    if (alignment != Text3D.ALIGN_FIRST) {
0152:                        double cx = (u.x - l.x);
0153:                        double cy = (u.y - l.y);
0154:
0155:                        if (alignment == Text3D.ALIGN_CENTER) {
0156:                            cx *= .5;
0157:                            cy *= .5;
0158:                        }
0159:                        switch (path) {
0160:                        case Text3D.PATH_RIGHT:
0161:                            l.x -= cx;
0162:                            u.x -= cx;
0163:                            break;
0164:                        case Text3D.PATH_LEFT:
0165:                            l.x += cx;
0166:                            u.x += cx;
0167:                            break;
0168:                        case Text3D.PATH_UP:
0169:                            l.y -= cy;
0170:                            u.y -= cy;
0171:                            break;
0172:                        case Text3D.PATH_DOWN:
0173:                            l.y += cy;
0174:                            u.y += cy;
0175:                            break;
0176:
0177:                        }
0178:                    }
0179:                }
0180:
0181:                l.z = 0.0f;
0182:                if ((font3D == null) || (font3D.fontExtrusion == null)) {
0183:                    u.z = l.z;
0184:                } else {
0185:                    u.z = l.z + font3D.fontExtrusion.length;
0186:                }
0187:            }
0188:
0189:            void update() {
0190:            }
0191:
0192:            /**
0193:             * Returns the Font3D objects used by this Text3D NodeComponent object.
0194:             *
0195:             * @return the Font3D object of this Text3D node - null if no Font3D
0196:             *  has been associated with this node.
0197:             *
0198:             * @exception CapabilityNotSetException if appropriate capability is
0199:             * not set and this object is part of live or compiled scene graph
0200:             */
0201:            final Font3D getFont3D() {
0202:                return this .font3D;
0203:            }
0204:
0205:            /**
0206:             * Sets the Font3D object used by this Text3D NodeComponent object.
0207:             *
0208:             * @param font3d the Font3D object to associate with this Text3D node.
0209:             *
0210:             * @exception CapabilityNotSetException if appropriate capability is
0211:             * not set and this object is part of live or compiled scene graph
0212:             */
0213:            final void setFont3D(Font3D font3d) {
0214:                geomLock.getLock();
0215:                this .font3D = font3d;
0216:                updateCharacterData();
0217:                geomLock.unLock();
0218:                sendDataChangedMessage();
0219:            }
0220:
0221:            /**
0222:             * Copies the character string used in the construction of the
0223:             * Text3D node into the supplied parameter.
0224:             *
0225:             * @return a copy of the String object in this Text3D node.
0226:             *
0227:             * @exception CapabilityNotSetException if appropriate capability is
0228:             * not set and this object is part of live or compiled scene graph
0229:             */
0230:            final String getString() {
0231:                return this .string;
0232:            }
0233:
0234:            /**
0235:             * Copies the character string from the supplied parameter into Tex3D
0236:             * node.
0237:             *
0238:             * @param string the String object to recieve the Text3D node's string.
0239:             *
0240:             * @exception CapabilityNotSetException if appropriate capability is
0241:             * not set and this object is part of live or compiled scene graph
0242:             */
0243:            final void setString(String string) {
0244:                geomLock.getLock();
0245:                this .string = string;
0246:                if (string == null) {
0247:                    numChars = 0;
0248:                } else {
0249:                    numChars = string.length();
0250:                }
0251:                updateCharacterData();
0252:                geomLock.unLock();
0253:                sendDataChangedMessage();
0254:            }
0255:
0256:            /**
0257:             * Copies the node's <code>position</code> field into the supplied
0258:             * parameter.  The <code>position</code> is used to determine the
0259:             * initial placement of the Text3D string.  The position, combined with
0260:             * the path and alignment control how the text is displayed.
0261:             *
0262:             * @param position the point to position the text.
0263:             *
0264:             * @exception CapabilityNotSetException if appropriate capability is
0265:             * not set and this object is part of live or compiled scene graph
0266:             *
0267:             * @see #getAlignment
0268:             * @see #getPath
0269:             */
0270:            final void getPosition(Point3f position) {
0271:                position.set(this .position);
0272:            }
0273:
0274:            /**
0275:             * Sets the node's <code>position</code> field to the supplied
0276:             * parameter.  The <code>position</code> is used to determine the
0277:             * initial placement of the Text3D string.  The position, combined with
0278:             * the path and alignment control how the text is displayed.
0279:             *
0280:             * @param position the point to position the text.
0281:             *
0282:             * @exception CapabilityNotSetException if appropriate capability is
0283:             * not set and this object is part of live or compiled scene graph
0284:             *
0285:             * @see #getAlignment
0286:             * @see #getPath
0287:             */
0288:            final void setPosition(Point3f position) {
0289:                geomLock.getLock();
0290:                this .position.set(position);
0291:                updateTransformData();
0292:                geomLock.unLock();
0293:                sendTransformChangedMessage();
0294:            }
0295:
0296:            /**
0297:             * Retrieves the text alignment policy for this Text3D NodeComponent
0298:             * object. The <code>alignment</code> is used to specify how
0299:             * glyphs in the string are placed in relation to the
0300:             * <code>position</code> field.  Valid values for this field
0301:             * are:
0302:             * <UL>
0303:             * <LI> ALIGN_CENTER - the center of the string is placed on the
0304:             *  <code>position</code> point.
0305:             * <LI> ALIGN_FIRST - the first character of the string is placed on
0306:             *   the <code>position</code> point.
0307:             * <LI> ALIGN_LAST - the last character of the string is placed on the
0308:             *   <code>position</code> point.
0309:             * </UL>
0310:             * The default value of this field is <code>ALIGN_FIRST</code>.
0311:             *
0312:             * @return the current alingment policy for this node.
0313:             *
0314:             * @exception CapabilityNotSetException if appropriate capability is
0315:             * not set and this object is part of live or compiled scene graph
0316:             *
0317:             * @see #getPosition
0318:             */
0319:            final int getAlignment() {
0320:                return alignment;
0321:            }
0322:
0323:            /**
0324:             * Sets the text alignment policy for this Text3D NodeComponent
0325:             * object. The <code>alignment</code> is used to specify how
0326:             * glyphs in the string are placed in relation to the
0327:             * <code>position</code> field.  Valid values for this field
0328:             * are:
0329:             * <UL>
0330:             * <LI> ALIGN_CENTER - the center of the string is placed on the
0331:             *  <code>position</code> point.
0332:             * <LI> ALIGN_FIRST - the first character of the string is placed on
0333:             *   the <code>position</code> point.
0334:             * <LI> ALIGN_LAST - the last character of the string is placed on the
0335:             *   <code>position</code> point.
0336:             * </UL>
0337:             * The default value of this field is <code>ALIGN_FIRST</code>.
0338:             *
0339:             * @return the current alingment policy for this node.
0340:             *
0341:             * @exception CapabilityNotSetException if appropriate capability is
0342:             * not set and this object is part of live or compiled scene graph
0343:             * 
0344:             * @see #getPosition
0345:             */
0346:            final void setAlignment(int alignment) {
0347:                geomLock.getLock();
0348:                this .alignment = alignment;
0349:                updateTransformData();
0350:                geomLock.unLock();
0351:                sendTransformChangedMessage();
0352:            }
0353:
0354:            /**
0355:             * Retrieves the node's <code>path</code> field.  This field
0356:             * is used  to specify how succeeding
0357:             * glyphs in the string are placed in relation to the previous glyph.
0358:             * Valid values for this field are:
0359:             * <UL>
0360:             * <LI> PATH_LEFT: - succeeding glyphs are placed to the left of the
0361:             *  current glyph.
0362:             * <LI> PATH_RIGHT: - succeeding glyphs are placed to the right of the
0363:             *  current glyph.
0364:             * <LI> PATH_UP: - succeeding glyphs are placed above the current glyph.
0365:             * <LI> PATH_DOWN: - succeeding glyphs are placed below the current glyph.
0366:             * </UL>
0367:             * The default value of this field is <code>PATH_RIGHT</code>.
0368:             *
0369:             * @return the current alingment policy for this node.
0370:             *
0371:             * @exception CapabilityNotSetException if appropriate capability is
0372:             * not set and this object is part of live or compiled scene graph
0373:             */
0374:            final int getPath() {
0375:                return this .path;
0376:            }
0377:
0378:            /**
0379:             * Sets the node's <code>path</code> field.  This field
0380:             * is used  to specify how succeeding
0381:             * glyphs in the string are placed in relation to the previous glyph.
0382:             * Valid values for this field are:
0383:             * <UL>
0384:             * <LI> PATH_LEFT - succeeding glyphs are placed to the left of the
0385:             *  current glyph.
0386:             * <LI> PATH_RIGHT - succeeding glyphs are placed to the right of the
0387:             *  current glyph.
0388:             * <LI> PATH_UP - succeeding glyphs are placed above the current glyph.
0389:             * <LI> PATH_DOWN - succeeding glyphs are placed below the current glyph.
0390:             * </UL>
0391:             * The default value of this field is <code>PATH_RIGHT</code>.
0392:             *
0393:             * @param path the value to set the path to.
0394:             *
0395:             * @return the current alingment policy for this node.
0396:             *
0397:             * @exception CapabilityNotSetException if appropriate capability is
0398:             * not set and this object is part of live or compiled scene graph
0399:             */
0400:            final void setPath(int path) {
0401:                this .path = path;
0402:                updateTransformData();
0403:                sendTransformChangedMessage();
0404:            }
0405:
0406:            /**
0407:             * Retrieves the 3D bounding box that encloses this Text3D object.
0408:             *
0409:             * @param bounds the object to copy the bounding information to.
0410:             *
0411:             * @exception CapabilityNotSetException if appropriate capability is
0412:             * not set and this object is part of live or compiled scene graph
0413:             *
0414:             * @see BoundingBox
0415:             */
0416:            final void getBoundingBox(BoundingBox bounds) {
0417:                synchronized (this ) {
0418:                    bounds.setLower(lower);
0419:                    bounds.setUpper(upper);
0420:                }
0421:            }
0422:
0423:            /**
0424:             * Retrieves the character spacing used to construct the Text3D string.
0425:             * This spacing is in addition to the regular spacing between glyphs as
0426:             * defined in the Font object.  1.0 in this space is measured as the
0427:             * width of the largest glyph in the 2D Font.  The default value is
0428:             * 0.0.
0429:             *
0430:             * @return the current character spacing value
0431:             *
0432:             * @exception CapabilityNotSetException if appropriate capability is
0433:             * not set and this object is part of live or compiled scene graph
0434:             */
0435:            final float getCharacterSpacing() {
0436:                return charSpacing;
0437:            }
0438:
0439:            /**
0440:             * Sets the character spacing used hwne constructing the Text3D string.
0441:             * This spacing is in addition to the regular spacing between glyphs as
0442:             * defined in the Font object.  1.0 in this space is measured as the
0443:             * width of the largest glyph in the 2D Font.  The default value is
0444:             * 0.0.
0445:             *
0446:             * @param characterSpacing the new character spacing value
0447:             *
0448:             * @exception CapabilityNotSetException if appropriate capability is
0449:             * not set and this object is part of live or compiled scene graph
0450:             */
0451:            final void setCharacterSpacing(float characterSpacing) {
0452:                geomLock.getLock();
0453:                this .charSpacing = characterSpacing;
0454:                updateTransformData();
0455:                geomLock.unLock();
0456:                sendTransformChangedMessage();
0457:            }
0458:
0459:            final void sendDataChangedMessage() {
0460:                J3dMessage[] m;
0461:                int i, j, k, kk, numMessages;
0462:                int gSize;
0463:                ArrayList shapeList, gaList;
0464:                Shape3DRetained s;
0465:                GeometryAtom[] newGeometryAtoms;
0466:                ArrayList tiArrList = new ArrayList();
0467:                ArrayList newCtArrArrList = new ArrayList();
0468:
0469:                synchronized (liveStateLock) {
0470:                    if (source.isLive()) {
0471:                        synchronized (universeList) {
0472:                            numMessages = universeList.size();
0473:                            m = new J3dMessage[numMessages];
0474:                            for (i = 0; i < numMessages; i++) {
0475:                                m[i] = new J3dMessage();
0476:                                m[i].type = J3dMessage.TEXT3D_DATA_CHANGED;
0477:                                m[i].threads = targetThreads;
0478:                                shapeList = (ArrayList) userLists.get(i);
0479:                                newGeometryAtomList.clear();
0480:                                oldGeometryAtomList.clear();
0481:
0482:                                for (j = 0; j < shapeList.size(); j++) {
0483:                                    s = (Shape3DRetained) shapeList.get(j);
0484:                                    if (s.boundsAutoCompute) {
0485:                                        // update combine bounds of mirrorShape3Ds. So we need to
0486:                                        // use its bounds and not localBounds.
0487:                                        // bounds is actually a reference to
0488:                                        // mirrorShape3D.source.localBounds.
0489:                                        // XXXX : Should only need to update distinct localBounds.
0490:                                        s
0491:                                                .getCombineBounds((BoundingBox) s.bounds);
0492:                                    }
0493:
0494:                                    gSize = s.geometryList.size();
0495:
0496:                                    GeometryAtom oldGA = Shape3DRetained
0497:                                            .getGeomAtom(s);
0498:                                    GeometryAtom newGA = new GeometryAtom();
0499:
0500:                                    int geometryCnt = 0;
0501:                                    for (k = 0; k < gSize; k++) {
0502:                                        GeometryRetained geomRetained = (GeometryRetained) s.geometryList
0503:                                                .get(k);
0504:                                        if (geomRetained != null) {
0505:                                            Text3DRetained tempT3d = (Text3DRetained) geomRetained;
0506:                                            geometryCnt += tempT3d.numChars;
0507:                                        } else {
0508:                                            // Slightly wasteful, but not quite worth to optimize yet. 
0509:                                            geometryCnt++;
0510:                                        }
0511:                                    }
0512:
0513:                                    newGA.geometryArray = new GeometryRetained[geometryCnt];
0514:                                    newGA.lastLocalTransformArray = new Transform3D[geometryCnt];
0515:                                    // Reset geometryCnt;
0516:                                    geometryCnt = 0;
0517:
0518:                                    newGA.locale = s.locale;
0519:                                    newGA.visible = s.visible;
0520:                                    newGA.source = s;
0521:                                    int gaCnt = 0;
0522:                                    GeometryRetained geometry = null;
0523:                                    for (; gaCnt < gSize; gaCnt++) {
0524:                                        geometry = (GeometryRetained) s.geometryList
0525:                                                .get(gaCnt);
0526:                                        if (geometry != null) {
0527:                                            newGA.geoType = geometry.geoType;
0528:                                            newGA.alphaEditable = s
0529:                                                    .isAlphaEditable(geometry);
0530:                                            break;
0531:                                        }
0532:                                    }
0533:
0534:                                    for (; gaCnt < gSize; gaCnt++) {
0535:                                        geometry = (GeometryRetained) s.geometryList
0536:                                                .get(gaCnt);
0537:                                        if (geometry == null) {
0538:                                            newGA.geometryArray[gaCnt] = null;
0539:                                        } else {
0540:                                            Text3DRetained t = (Text3DRetained) geometry;
0541:                                            GeometryRetained geo;
0542:                                            for (k = 0; k < t.numChars; k++, geometryCnt++) {
0543:                                                geo = t.geometryList[k];
0544:                                                if (geo != null) {
0545:                                                    newGA.geometryArray[geometryCnt] = geo;
0546:                                                    newGA.lastLocalTransformArray[geometryCnt] = t.charTransforms[k];
0547:
0548:                                                } else {
0549:                                                    newGA.geometryArray[geometryCnt] = null;
0550:                                                    newGA.lastLocalTransformArray[geometryCnt] = null;
0551:                                                }
0552:
0553:                                            }
0554:
0555:                                        }
0556:                                    }
0557:
0558:                                    oldGeometryAtomList.add(oldGA);
0559:                                    newGeometryAtomList.add(newGA);
0560:                                    Shape3DRetained.setGeomAtom(s, newGA);
0561:                                }
0562:
0563:                                Object[] oldGAArray = oldGeometryAtomList
0564:                                        .toArray();
0565:                                Object[] newGAArray = newGeometryAtomList
0566:                                        .toArray();
0567:                                ArrayList uniqueList = getUniqueSource(shapeList);
0568:                                int numSrc = uniqueList.size();
0569:                                int numMS3D;
0570:                                Shape3DRetained ms, src;
0571:
0572:                                for (j = 0; j < numSrc; j++) {
0573:                                    CachedTargets[] newCtArr = null;
0574:                                    src = (Shape3DRetained) uniqueList.get(j);
0575:                                    numMS3D = src.mirrorShape3D.size();
0576:
0577:                                    TargetsInterface ti = ((GroupRetained) src.parent)
0578:                                            .getClosestTargetsInterface(TargetsInterface.TRANSFORM_TARGETS);
0579:
0580:                                    if (ti != null) {
0581:                                        CachedTargets ct;
0582:                                        newCtArr = new CachedTargets[numMS3D];
0583:
0584:                                        for (k = 0; k < numMS3D; k++) {
0585:                                            ms = (Shape3DRetained) src.mirrorShape3D
0586:                                                    .get(k);
0587:
0588:                                            GeometryAtom ga = Shape3DRetained
0589:                                                    .getGeomAtom(ms);
0590:                                            for (kk = 0; kk < newGAArray.length; kk++) {
0591:                                                if (ga == newGAArray[kk]) {
0592:                                                    break;
0593:                                                }
0594:                                            }
0595:
0596:                                            if (kk == newGAArray.length) {
0597:                                                System.err
0598:                                                        .println("Text3DRetained : Problem !!! Can't find matching geomAtom");
0599:                                            }
0600:
0601:                                            ct = ti
0602:                                                    .getCachedTargets(
0603:                                                            TargetsInterface.TRANSFORM_TARGETS,
0604:                                                            k, -1);
0605:                                            if (ct != null) {
0606:                                                newCtArr[k] = new CachedTargets();
0607:                                                newCtArr[k].copy(ct);
0608:                                                newCtArr[k].replace(
0609:                                                        (NnuId) oldGAArray[kk],
0610:                                                        (NnuId) newGAArray[kk],
0611:                                                        Targets.GEO_TARGETS);
0612:                                            } else {
0613:                                                newCtArr[k] = null;
0614:                                            }
0615:
0616:                                        }
0617:
0618:                                        ti
0619:                                                .resetCachedTargets(
0620:                                                        TargetsInterface.TRANSFORM_TARGETS,
0621:                                                        newCtArr, -1);
0622:
0623:                                        tiArrList.add(ti);
0624:                                        newCtArrArrList.add(newCtArr);
0625:
0626:                                    }
0627:
0628:                                }
0629:
0630:                                m[i].args[0] = oldGAArray;
0631:                                m[i].args[1] = newGAArray;
0632:                                m[i].universe = (VirtualUniverse) universeList
0633:                                        .get(i);
0634:
0635:                                if (tiArrList.size() > 0) {
0636:                                    m[i].args[2] = tiArrList.toArray();
0637:                                    m[i].args[3] = newCtArrArrList.toArray();
0638:                                }
0639:
0640:                                tiArrList.clear();
0641:                                newCtArrArrList.clear();
0642:
0643:                            }
0644:                            VirtualUniverse.mc.processMessage(m);
0645:                        }
0646:
0647:                    }
0648:                }
0649:            }
0650:
0651:            final void sendTransformChangedMessage() {
0652:                J3dMessage[] m;
0653:                int i, j, numMessages, sCnt;
0654:                ArrayList shapeList;
0655:                ArrayList gaList = new ArrayList();
0656:                Shape3DRetained s;
0657:                GeometryRetained geomR;
0658:                synchronized (liveStateLock) {
0659:                    if (source.isLive()) {
0660:                        synchronized (universeList) {
0661:                            numMessages = universeList.size();
0662:                            m = new J3dMessage[numMessages];
0663:                            for (i = 0; i < numMessages; i++) {
0664:                                m[i] = new J3dMessage();
0665:                                m[i].type = J3dMessage.TEXT3D_TRANSFORM_CHANGED;
0666:                                m[i].threads = targetThreads;
0667:                                shapeList = (ArrayList) userLists.get(i);
0668:                                // gaList = new GeometryAtom[shapeList.size() * numChars];
0669:                                for (j = 0; j < shapeList.size(); j++) {
0670:                                    s = (Shape3DRetained) shapeList.get(j);
0671:
0672:                                    // Find the right geometry.
0673:                                    for (sCnt = 0; sCnt < s.geometryList.size(); sCnt++) {
0674:                                        geomR = (GeometryRetained) s.geometryList
0675:                                                .get(sCnt);
0676:                                        if (geomR == this ) {
0677:                                            break;
0678:                                        }
0679:                                    }
0680:
0681:                                    if (sCnt < s.geometryList.size())
0682:                                        gaList.add(Shape3DRetained
0683:                                                .getGeomAtom(s));
0684:
0685:                                }
0686:                                m[i].args[0] = gaList.toArray();
0687:                                m[i].args[1] = charTransforms;
0688:                                m[i].universe = (VirtualUniverse) universeList
0689:                                        .get(i);
0690:                            }
0691:                            VirtualUniverse.mc.processMessage(m);
0692:                        }
0693:                    }
0694:                }
0695:            }
0696:
0697:            /**
0698:             * Update internal reprsentation of tranform matrices and geometry.
0699:             * This method will be called whenever string or font3D change.
0700:             */
0701:            final void updateCharacterData() {
0702:                char c[] = new char[1];
0703:
0704:                if (geometryList.length != numChars) {
0705:                    geometryList = new GeometryArrayRetained[numChars];
0706:                    glyphVecs = new GlyphVector[numChars];
0707:                }
0708:
0709:                if (font3D != null) {
0710:                    for (int i = 0; i < numChars; i++) {
0711:                        c[0] = string.charAt(i);
0712:                        glyphVecs[i] = font3D.font.createGlyphVector(
0713:                                font3D.frc, c);
0714:                        geometryList[i] = font3D.triangulateGlyphs(
0715:                                glyphVecs[i], c[0]);
0716:                    }
0717:                }
0718:
0719:                updateTransformData();
0720:            }
0721:
0722:            /**
0723:             * Update per character transform based on Text3D location,
0724:             * per character size and path. 
0725:             *
0726:             * WARNING: Caller of this method must make sure SceneGraph is live,
0727:             * else exceptions may be thrown.
0728:             */
0729:            final void updateTransformData() {
0730:                int i, k = 0, numTotal = 0;
0731:                double width = 0, height = 0;
0732:                Vector3f location = new Vector3f(this .position);
0733:                Rectangle2D bounds;
0734:
0735:                //Reset bounds data 
0736:                lower.set(location);
0737:                upper.set(location);
0738:
0739:                charTransforms = new Transform3D[numChars];
0740:                for (i = 0; i < numChars; i++) {
0741:                    charTransforms[i] = new Transform3D();
0742:                }
0743:
0744:                if (numChars != 0) {
0745:                    charTransforms[0].set(location);
0746:
0747:                    // Set loop counters based on path type
0748:                    if (path == Text3D.PATH_RIGHT || path == Text3D.PATH_UP) {
0749:                        k = 0;
0750:                        numTotal = numChars + 1;
0751:                    } else if (path == Text3D.PATH_LEFT
0752:                            || path == Text3D.PATH_DOWN) {
0753:                        k = 1;
0754:                        numTotal = numChars;
0755:                        // Reset bounds to bounding box if first character
0756:                        bounds = glyphVecs[0].getVisualBounds();
0757:                        upper.x += bounds.getWidth();
0758:                        upper.y += bounds.getHeight();
0759:                    }
0760:
0761:                    for (i = 1; i < numTotal; i++, k++) {
0762:                        width = glyphVecs[k].getLogicalBounds().getWidth();
0763:                        bounds = glyphVecs[k].getVisualBounds();
0764:                        // 'switch' could be outside loop with little hacking,
0765:                        width += charSpacing;
0766:                        height = bounds.getHeight();
0767:
0768:                        switch (this .path) {
0769:                        case Text3D.PATH_RIGHT:
0770:                            location.x += width;
0771:                            upper.x += (width);
0772:                            if (upper.y < (height + location.y)) {
0773:                                upper.y = location.y + height;
0774:                            }
0775:                            break;
0776:                        case Text3D.PATH_LEFT:
0777:                            location.x -= width;
0778:                            lower.x -= (width);
0779:                            if (upper.y < (height + location.y)) {
0780:                                upper.y = location.y + height;
0781:                            }
0782:                            break;
0783:                        case Text3D.PATH_UP:
0784:                            location.y += height;
0785:                            upper.y += height;
0786:                            if (upper.x < (bounds.getWidth() + location.x)) {
0787:                                upper.x = location.x + bounds.getWidth();
0788:                            }
0789:                            break;
0790:                        case Text3D.PATH_DOWN:
0791:                            location.y -= height;
0792:                            lower.y -= height;
0793:                            if (upper.x < (bounds.getWidth() + location.x)) {
0794:                                upper.x = location.x + bounds.getWidth();
0795:                            }
0796:                            break;
0797:                        }
0798:                        if (i < numChars) {
0799:                            charTransforms[i].set(location);
0800:                        }
0801:                    }
0802:
0803:                    // Handle string alignment. ALIGN_FIRST is handled by default 
0804:                    if (alignment != Text3D.ALIGN_FIRST) {
0805:                        double cx = (upper.x - lower.x);
0806:                        double cy = (upper.y - lower.y);
0807:
0808:                        if (alignment == Text3D.ALIGN_CENTER) {
0809:                            cx *= .5;
0810:                            cy *= .5;
0811:                        }
0812:                        switch (path) {
0813:                        case Text3D.PATH_RIGHT:
0814:                            for (i = 0; i < numChars; i++) {
0815:                                charTransforms[i].mat[3] -= cx;
0816:                            }
0817:                            lower.x -= cx;
0818:                            upper.x -= cx;
0819:                            break;
0820:                        case Text3D.PATH_LEFT:
0821:                            for (i = 0; i < numChars; i++) {
0822:                                charTransforms[i].mat[3] += cx;
0823:                            }
0824:                            lower.x += cx;
0825:                            upper.x += cx;
0826:                            break;
0827:
0828:                        case Text3D.PATH_UP:
0829:                            for (i = 0; i < numChars; i++) {
0830:                                charTransforms[i].mat[7] -= cy;
0831:                            }
0832:                            lower.y -= cy;
0833:                            upper.y -= cy;
0834:                            break;
0835:                        case Text3D.PATH_DOWN:
0836:                            for (i = 0; i < numChars; i++) {
0837:                                charTransforms[i].mat[7] += cy;
0838:                            }
0839:                            lower.y += cy;
0840:                            upper.y += cy;
0841:                            break;
0842:
0843:                        }
0844:                    }
0845:                }
0846:
0847:                lower.z = 0.0f;
0848:                if ((font3D == null) || (font3D.fontExtrusion == null)) {
0849:                    upper.z = lower.z;
0850:                } else {
0851:                    upper.z = lower.z + font3D.fontExtrusion.length;
0852:                }
0853:
0854:                // update geoBounds
0855:                getBoundingBox(geoBounds);
0856:            }
0857:
0858:            /**
0859:             * This method is called when the SceneGraph becomes live. All characters
0860:             * used by this.string are tesselated in this method, to avoid wait during
0861:             * traversal and rendering.
0862:             */
0863:            void setLive(boolean inBackgroundGroup, int refCount) {
0864:                // Tesselate all character data and update character transforms
0865:                updateCharacterData();
0866:                super .doSetLive(inBackgroundGroup, refCount);
0867:                super .markAsLive();
0868:            }
0869:
0870:            // TODO -- Need to rethink. Might have to consider charTransform[] in returns pickInfo.
0871:            boolean intersect(PickShape pickShape, PickInfo pickInfo,
0872:                    int flags, Point3d iPnt, GeometryRetained geom,
0873:                    int geomIndex) {
0874:                Transform3D tempT3D = new Transform3D();
0875:                GeometryArrayRetained geo = null;
0876:                int sIndex = -1;
0877:                PickShape newPS;
0878:                double minDist = Double.MAX_VALUE;
0879:                double distance = 0.0;
0880:                Point3d closestIPnt = new Point3d();
0881:
0882:                for (int i = 0; i < numChars; i++) {
0883:                    geo = geometryList[i];
0884:                    if (geo != null) {
0885:                        tempT3D.invert(charTransforms[i]);
0886:                        newPS = pickShape.transform(tempT3D);
0887:                        if (geo.intersect(newPS, pickInfo, flags, iPnt, geom,
0888:                                geomIndex)) {
0889:                            if (flags == 0) {
0890:                                return true;
0891:                            }
0892:                            distance = newPS.distance(iPnt);
0893:                            if (distance < minDist) {
0894:                                sIndex = i;
0895:                                minDist = distance;
0896:                                closestIPnt.set(iPnt);
0897:                            }
0898:                        }
0899:                    }
0900:                }
0901:
0902:                if (sIndex >= 0) {
0903:                    // We need to transform iPnt to the vworld to compute the actual distance.
0904:                    // In this method we'll transform iPnt by its char. offset. Shape3D will
0905:                    // do the localToVworld transform.
0906:                    iPnt.set(closestIPnt);
0907:                    charTransforms[sIndex].transform(iPnt);
0908:                    return true;
0909:                }
0910:                return false;
0911:            }
0912:
0913:            boolean intersect(Point3d[] pnts) {
0914:                Transform3D tempT3D = new Transform3D();
0915:                GeometryArrayRetained ga;
0916:                boolean isIntersect = false;
0917:                Point3d transPnts[] = new Point3d[pnts.length];
0918:                for (int j = pnts.length - 1; j >= 0; j--) {
0919:                    transPnts[j] = new Point3d();
0920:                }
0921:
0922:                for (int i = numChars - 1; i >= 0; i--) {
0923:                    ga = geometryList[i];
0924:                    if (ga != null) {
0925:                        tempT3D.invert(charTransforms[i]);
0926:                        for (int j = pnts.length - 1; j >= 0; j--) {
0927:                            tempT3D.transform(pnts[j], transPnts[j]);
0928:                        }
0929:                        if (ga.intersect(transPnts)) {
0930:                            isIntersect = true;
0931:                            break;
0932:                        }
0933:                    }
0934:                }
0935:                return isIntersect;
0936:            }
0937:
0938:            boolean intersect(Transform3D this ToOtherVworld,
0939:                    GeometryRetained geom) {
0940:                GeometryArrayRetained ga;
0941:
0942:                for (int i = numChars - 1; i >= 0; i--) {
0943:                    ga = geometryList[i];
0944:                    if ((ga != null) && ga.intersect(this ToOtherVworld, geom)) {
0945:                        return true;
0946:                    }
0947:                }
0948:
0949:                return false;
0950:            }
0951:
0952:            boolean intersect(Bounds targetBound) {
0953:                GeometryArrayRetained ga;
0954:
0955:                for (int i = numChars - 1; i >= 0; i--) {
0956:                    ga = geometryList[i];
0957:                    if ((ga != null) && ga.intersect(targetBound)) {
0958:                        return true;
0959:                    }
0960:                }
0961:
0962:                return false;
0963:
0964:            }
0965:
0966:            void setModelViewMatrix(Transform3D vpcToEc,
0967:                    Transform3D drawTransform) {
0968:                this .vpcToEc = vpcToEc;
0969:                this .drawTransform = drawTransform;
0970:            }
0971:
0972:            void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
0973:                    boolean updateAlpha, float alpha, int screen,
0974:                    boolean ignoreVertexColors) {
0975:
0976:                Transform3D trans = new Transform3D();
0977:
0978:                for (int i = 0; i < geometryList.length; i++) {
0979:                    trans.set(drawTransform);
0980:                    trans.mul(charTransforms[i]);
0981:                    cv.setModelViewMatrix(cv.ctx, vpcToEc.mat, trans);
0982:                    geometryList[i].execute(cv, ra, isNonUniformScale,
0983:                            updateAlpha, alpha, screen, ignoreVertexColors);
0984:                }
0985:            }
0986:
0987:            int getClassType() {
0988:                return TEXT3D_TYPE;
0989:            }
0990:
0991:            ArrayList getUniqueSource(ArrayList shapeList) {
0992:                ArrayList uniqueList = new ArrayList();
0993:                int size = shapeList.size();
0994:                Object src;
0995:                int i, index;
0996:
0997:                for (i = 0; i < size; i++) {
0998:                    src = ((Shape3DRetained) shapeList.get(i)).sourceNode;
0999:                    index = uniqueList.indexOf(src);
1000:                    if (index == -1) {
1001:                        uniqueList.add(src);
1002:                    }
1003:                }
1004:                return uniqueList;
1005:            }
1006:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.