001: /*
002: * Copyright (c) 2000-2001 Silvere Martin-Michiellot All Rights Reserved.
003: *
004: * Silvere Martin-Michiellot grants you ("Licensee") a non-exclusive,
005: * royalty free, license to use, but not to modify or redistribute this
006: * software in source and binary code form,
007: * provided that i) this copyright notice and license appear on all copies of
008: * the software; and ii) Licensee does not utilize the software in a manner
009: * which is disparaging to Silvere Martin-Michiellot.
010: *
011: * This software is provided "AS IS," without a warranty of any kind. ALL
012: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
013: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
014: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. Silvere Martin-Michiellot
015: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
016: * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
017: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
018: * Silvere Martin-Michiellot OR ITS LICENSORS BE LIABLE
019: * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
020: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
021: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
022: * OR INABILITY TO USE SOFTWARE, EVEN IF Silvere Martin-Michiellot HAS BEEN
023: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
024: *
025: * This software is not designed or intended for use in on-line control of
026: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
027: * the design, construction, operation or maintenance of any nuclear
028: * facility. Licensee represents and warrants that it will not use or
029: * redistribute the Software for such purposes.
030: *
031: * @Author: Silvere Martin-Michiellot for Digital Biosphere
032: * @Version: 1.1 (to stay in touch with h-anim)
033: *
034: */
035:
036: package com.db.hanim;
037:
038: import java.util.*;
039: import javax.media.j3d.Interpolator;
040:
041: /**
042: * This class is to implement a GestureLevelsOfAnimation checker. Basically, given a humanoid, it ouputs an integer that gives the level of compliance of this humanoid against a standard pre-defined set of Joints and Sites. This integer ranges from -1 to 3, -1 meaning that it does not comply with any level of animation. This is feature that did not exist in H-Anim specification but we felt it would be useful if implemented. It's behavior is similar to HAnimLevelsOfAnimation. See also HAnimLevelsOfAnimation for compliance of humanoids against the same set of pre-defined Joints and Sites.
043: * Please read the H-Anim specification for more information.
044: *
045: * Please note that there is a problem in H-Anim with sites since:
046: * 1. a H-Anim level 1 compatible avatar should contain:
047: * l_middistal_tip, r_middistal_tip, l_hand_tip, r_hand_tip (among others)
048: * 2. a H-Anim level 2 compatible avatar should contain:
049: * l_forefoot_tip, r_forefoot_tip, l_middle_distal_tip, r_middle_distal_tip (among others)
050: * but not the four Sites given in 1.
051: * This is a problem since levels of articulation are given in ascendant order
052: * however, l_middistal_tip is just the same name for l_forefoot_tip (and so on for the other three).
053: *
054: * Therefore we assume that an avatar is level 1 compatible if it contains either of each pair
055: * (both of a pair could be considered as an error but we assume that users won't use both)
056: * (same conditions applies for higher order levels).
057: *
058: * The following joints are not included in the loa also they are defined by H-Anim
059: * it is assumed they are level 4 (all non standard joints):
060: * Joint.l_eyelid_joint;
061: * Joint.r_eyelid_joint;
062: * Joint.l_eyebrow_joint;
063: * Joint.r_eyebrow_joint;
064: * Joint.temporomandibular;
065: * Joint.NonStandard;
066: *
067: * @author Silvere Martin-Michiellot
068: * @version 1.1
069: */
070:
071: public final class GestureLevelsOfAnimation {
072:
073: //indexes for loaJoints given in ascendant order
074: //Joint.HumanoidRoot, Joint.sacroiliac, Joint.l_hip, Joint.l_knee, Joint.l_ankle, Joint.l_subtalar,
075: //Joint.l_midtarsal, Joint.l_metatarsal, Joint.r_hip, Joint.r_knee, Joint.r_ankle, Joint.r_subtalar,
076: //Joint.r_midtarsal, Joint.r_metatarsal, Joint.vl5, Joint.vl4, Joint.vl3, Joint.vl2, Joint.vl1,
077: //Joint.vt12, Joint.vt11, Joint.vt10, Joint.vt9, Joint.vt8, Joint.vt7, Joint.vt6, Joint.vt5, Joint.vt4,
078: //Joint.vt3, Joint.vt2, Joint.vt1, Joint.vc7, Joint.vc6, Joint.vc5, Joint.vc4, Joint.vc3, Joint.vc2,
079: //Joint.vc1, Joint.skullbase, Joint.l_eyelid_joint, Joint.r_eyelid_joint, Joint.l_eyeball_joint,
080: //Joint.r_eyeball_joint, Joint.l_eyebrow_joint, Joint.r_eyebrow_joint, Joint.temporomandibular,
081: //Joint.l_sternoclavicular, Joint.l_acromioclavicular, Joint.l_shoulder, Joint.l_elbow, Joint.l_wrist,
082: //Joint.l_thumb1, Joint.l_thumb2, Joint.l_thumb3, Joint.l_index0, Joint.l_index1, Joint.l_index2,
083: //Joint.l_index3, Joint.l_middle0, Joint.l_middle1, Joint.l_middle2, Joint.l_middle3, Joint.l_ring0,
084: //Joint.l_ring1, Joint.l_ring2, Joint.l_ring3, Joint.l_pinky0, Joint.l_pinky1, Joint.l_pinky2,
085: //Joint.l_pinky3, Joint.r_sternoclavicular, Joint.r_acromioclavicular, Joint.r_shoulder, Joint.r_elbow,
086: //Joint.r_wrist, Joint.r_thumb1, Joint.r_thumb2, Joint.r_thumb3, Joint.r_index0, Joint.r_index1,
087: //Joint.r_index2, Joint.r_index3, Joint.r_middle0, Joint.r_middle1, Joint.r_middle2, Joint.r_middle3,
088: //Joint.r_ring0, Joint.r_ring1, Joint.r_ring2, Joint.r_ring3, Joint.r_pinky0, Joint.r_pinky1,
089: //Joint.r_pinky2, Joint.r_pinky3, Joint.NonStandard
090:
091: //the following joints are not included in the loa also they are defined by h-anim
092: //it is assumed they are level 4 (all non standard joints)
093: //Joint.l_eyelid_joint;
094: //Joint.r_eyelid_joint;
095: //Joint.l_eyebrow_joint;
096: //Joint.r_eyebrow_joint;
097: //Joint.temporomandibular;
098: //Joint.NonStandard;
099:
100: static int[] loaJointsTable = { 0, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2,
101: 1, 2, 1, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
102: 3, 3, 2, 3, 2, 3, 1, 4, 4, 3, 3, 4, 4, 4, 2, 2, 1, 1, 1, 2,
103: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
104: 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
105: 2, 2, 4 };
106:
107: //Sites are not used for Gestures, only Joints move and the rest follows
108:
109: static int loa0Joints, loa1Joints, loa2Joints, loa3Joints,
110: loa4Joints;
111:
112: static boolean[] definedJoints;
113:
114: /**
115: * Construct a new GestureLevelsOfAnimation. This class has only to be instanciated once.
116: */
117:
118: public GestureLevelsOfAnimation() {
119:
120: //static because of method: beware of concurrent access !
121: definedJoints = new boolean[loaJointsTable.length];
122:
123: loa0Joints = 0;
124: loa1Joints = 0;
125: loa2Joints = 0;
126: loa3Joints = 0;
127: loa4Joints = 0;
128:
129: //recompute the number of joints per level just in case a developper (you ?) modify the standard list of joints
130: for (int i = 0; i < loaJointsTable.length; i++) {
131: switch (loaJointsTable[i]) {
132: case 0:
133: loa0Joints++;
134: break;
135: case 1:
136: loa1Joints++;
137: break;
138: case 2:
139: loa2Joints++;
140: break;
141: case 3:
142: loa3Joints++;
143: break;
144: default:
145: loa4Joints++;
146: break;
147: }
148: }
149:
150: }
151:
152: /**
153: * Gets the int level of compatibility of this gesture. See com.db.hanim.HAnimLevelsOfAnimation for more details.
154: * There must be at least one Position, Rotation, Rotation & Position Interpolator for each Joint
155: * defined in a Level Of Animation for the Gesture to be of that Level Of Animation.
156: * There is no check about the duration of any Interpolator.
157: *
158: * @param gesture the Gesture to check the level of compatibility
159: * @return the int from -1 to 3 certifying corresponding level of compatibility
160: */
161: public static int getLevelOfCompatibility(Gesture gesture) {
162: //there must be at least one Position, Rotation, Rotation & Position Interpolator for each Joint
163: //defined in a Level Of Animation for the Gesture to be of that Level Of Animation
164: //there is no check about the duration of any Interpolator
165:
166: //we can sum the number of joints for each level to compare with the standard number for each level
167: //doing this saves a lot of computer time
168:
169: int loa0FoundJoints, loa1FoundJoints, loa2FoundJoints, loa3FoundJoints, loa4FoundJoints;
170: Enumeration enumeration;
171:
172: if (gesture != null) {
173:
174: //clear definedJoints
175: for (int i = 0; i < definedJoints.length; i++) {
176: definedJoints[i] = false;
177: }
178: loa0FoundJoints = 0;
179: loa1FoundJoints = 0;
180: loa2FoundJoints = 0;
181: loa3FoundJoints = 0;
182: loa4FoundJoints = 0;
183:
184: //browse the BranchGroup
185: enumeration = gesture.getBranchGroup().getAllChildren();
186: while (enumeration.hasMoreElements()) {
187: definedJoints[Joint
188: .getJointIdentifierNumber((String) (((Interpolator) enumeration
189: .nextElement()).getUserData()))] = true;
190: }
191:
192: //compute the sums for Joints
193: for (int i = 0; i < definedJoints.length; i++) {
194:
195: if (definedJoints[i]) {
196: switch (loaJointsTable[i]) {
197: case 0:
198: loa0FoundJoints++;
199: break;
200: case 1:
201: loa1FoundJoints++;
202: break;
203: case 2:
204: loa2FoundJoints++;
205: break;
206: case 3:
207: loa3FoundJoints++;
208: break;
209: default:
210: loa4FoundJoints++;
211: break;
212: }
213: }
214:
215: }
216:
217: //return loa
218: if (loa0Joints == loa0FoundJoints) {
219: if (loa1Joints == loa1FoundJoints) {
220: if (loa2Joints == loa2FoundJoints) {
221: if (loa3Joints == loa3FoundJoints) {
222: return 3;
223: } else
224: return 2;
225: } else
226: return 1;
227: } else
228: return 0;
229: } else
230: return -1;
231:
232: } else
233: return -1;
234: }
235:
236: }
|