KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > buchuki > ensmer > SceneGraphUtils


1 /*
2  * Copyright 2004 Dusty Phillips
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package com.buchuki.ensmer;
18
19 import com.sun.j3d.utils.picking.PickTool;
20 import java.util.*;
21 import javax.media.j3d.*;
22 import javax.vecmath.*;
23
24 /**
25  * Static class containing utility methods for manipulating the scenegraph and
26  * capability bits on various BranchGroups.
27  *
28  * @author Dusty Phillips [dusty@buchuki.com]
29  */

30 public class SceneGraphUtils {
31     
32     /**
33      * Creates a new instance of SceneGraphUtils
34      */

35     private SceneGraphUtils() { }
36     
37     /**
38      * Traverse a specific node and enable the various Capability bits
39      * that Ensmer requires to be on for all nodes. This acts as a central
40      * point of control for capabilities in Ensmer; it tries to get around the
41      * very messy capabilities mechanism in Java 3D in a semi-elegant way.
42      *
43      * @param node the node to recursively enable capabilities for.
44      */

45     public static void enableEnsmerCapabilities(Node node) {
46         
47         if (node instanceof Shape3D) {
48             PickTool.setCapabilities(node, PickTool.INTERSECT_TEST);
49             ((Shape3D) node).setCapability(Shape3D.ALLOW_APPEARANCE_READ);
50             Appearance app = ((Shape3D) node).getAppearance();
51             if (app != null) {
52                 app.setCapability(Appearance.ALLOW_MATERIAL_READ);
53                 Material matt = app.getMaterial();
54                 if (matt != null) {
55                     matt.setCapability(Material.ALLOW_COMPONENT_READ);
56                     matt.setCapability(Material.ALLOW_COMPONENT_WRITE);
57                 }
58             }
59         }
60         else if (node instanceof Group) {
61             Enumeration en = ((Group) node).getAllChildren();
62             while (en.hasMoreElements()) {
63                 enableEnsmerCapabilities((Node) en.nextElement());
64             }
65         }
66     }
67     
68     /**
69      * Return an integer that is greater than or equal to the given integer
70      * and is a power of 2, OR if the width is greater than the maximum power,
71      * return the maximum power
72      *
73      * @param value a number to ceiling to a power of 2
74      * @param max the maximum power to go to (ie: if max = 16, then the highest
75      * number that will be returned, regardless of width is 2^16 or 65536).
76      * @return a number that is guaranteed to be a power of 2 below 2^max, and
77      * above width unless width > 2^max
78      */

79     public static int greaterBinaryPower(int value, int max) {
80         int pow = 2;
81         int newWidth = -1;
82         for (int i = 1; i < max; ++i, pow*=2) {
83             if (value <= pow) {
84                 newWidth = pow;
85                 break;
86             }
87         }
88         return newWidth == -1 ? pow : newWidth;
89     }
90     
91     
92     /**
93      * Traverse a specific node and collect all the Appearance nodes that
94      * are associated with that node.
95      *
96      * @param node a node to recursively search for Appearance instances
97      * @return Collection of Appearance nodes
98      */

99     @SuppressWarnings JavaDoc({"unchecked"})
100     public static Collection getAppearanceNodes(Node node) {
101         ArrayList<Appearance> ret = new ArrayList<Appearance>();
102         if (node instanceof Shape3D) {
103             Appearance app = ((Shape3D) node).getAppearance();
104             if (app != null) {
105                 ret.add(app);
106             }
107         }
108         else if (node instanceof Group) {
109             Enumeration en = ((Group) node).getAllChildren();
110             while (en.hasMoreElements()) {
111                 ret.addAll(getAppearanceNodes((Node) en.nextElement()));
112             }
113         }
114         return ret;
115     }
116     
117     /**
118      * Return a position that is directly 'in front of' the user's current
119      * position in the given area.
120      * @param area the area to return a position in
121      * @return a position that is in front of the user's position in that area
122      */

123     public static Matrix4f positionInFrontOfUser(Area area) {
124         return positionInFrontOfUser(area, 2);
125     }
126     
127     /**
128      * Return a position that is directly 'in front of' the user's current
129      * position at a specific distance
130      * @param area the area to return a position in
131      * @param distance the distance the new position should be from the user
132      * @return a position that is in front of the user's position in that area
133      */

134     public static Matrix4f positionInFrontOfUser(Area area, float distance) {
135         Vector3f addition = new Vector3f(0, 0, -1 * distance);
136         return transformToUser(area, addition);
137     }
138     
139     /**
140      * Return a position that is randomly 'in front of' the user's current
141      * position in the given area. This is a simple algorithm for positioning
142      * multiple objects in front of the user at a visible distance.
143      *
144      * @param area the area to return a position in
145      * @return a position that is somewhere in front of the user's position in
146      * that area
147      */

148     public static Matrix4f randomPositionInFrontOfUser(Area area) {
149         return randomPositionInFrontOfUser(area, 5f);
150     }
151     
152     /**
153      * Return a position that is randomly 'in front of' the user's current position
154      * in the given area, but within a maximum distance on the Z axis.
155      *
156      * @param area the area to return a position in
157      * @param maxDistance the maximum distance from the user that the position
158      * should be returned
159      * @return a position that is somewhere in front of the user's position in that
160      * area
161      */

162     public static Matrix4f randomPositionInFrontOfUser(Area area, float maxDistance) {
163         Vector3f addition = new Vector3f((float) (3f * Math.random() - 1.5f),
164             (float) (3f * Math.random() - 1.5f),
165             (float) (3f * Math.random() - (maxDistance + 3)));
166         return transformToUser(area, addition);
167     }
168     
169     /**
170      * Return the given vector transformed according to the user view in the
171      * given area. In other words, the movement in the given vector is relative
172      * to the direction the user is currently facing.
173      *
174      * @param area the area to return a position in
175      * @param vector the vector to transform
176      * @return a matrix containing the transformed vector
177      */

178     private static Matrix4f transformToUser(Area area, Vector3f vector) {
179         Matrix4f userPos = area.getUserPosition();
180         Matrix3f userRot = new Matrix3f();
181         userPos.getRotationScale(userRot);
182         Vector3f userVec = new Vector3f();
183         userPos.get(userVec);
184         userPos.transform(vector);
185         userVec.add(vector);
186         Transform3D trans = new Transform3D();
187         trans.setTranslation(userVec);
188         trans.setRotation(userRot);
189         Matrix4f loc = new Matrix4f();
190         trans.get(loc);
191         return loc;
192     }
193 }
Popular Tags