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:
040: /**
041: * This class is to implement a HAnimLevelsOfAnimation 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. See also GestureLevelOfAnimation for compliance of gestures against the same set of pre-defined Joints and Sites.
042: * Please read the H-Anim specification for more information.
043: *
044: * Please note that there is a problem in H-Anim with sites since:
045: * 1. a H-Anim level 1 compatible avatar should contain:
046: * l_middistal_tip, r_middistal_tip, l_hand_tip, r_hand_tip (among others)
047: * 2. a H-Anim level 2 compatible avatar should contain:
048: * l_forefoot_tip, r_forefoot_tip, l_middle_distal_tip, r_middle_distal_tip (among others)
049: * but not the four Sites given in 1.
050: * This is a problem since levels of articulation are given in ascendant order
051: * however, l_middistal_tip is just the same name for l_forefoot_tip (and so on for the other three).
052: *
053: * Therefore we assume that an avatar is level 1 compatible if it contains either of each pair
054: * (both of a pair could be considered as an error but we assume that users won't use both)
055: * (same conditions applies for higher order levels).
056: *
057: * The following joints are not included in the loa also they are defined by H-Anim
058: * it is assumed they are level 4 (all non standard joints):
059: * Joint.l_eyelid_joint;
060: * Joint.r_eyelid_joint;
061: * Joint.l_eyebrow_joint;
062: * Joint.r_eyebrow_joint;
063: * Joint.temporomandibular;
064: * Joint.NonStandard;
065: *
066: * @author Silvere Martin-Michiellot
067: * @version 1.1
068: */
069:
070: public final class HAnimLevelsOfAnimation {
071:
072: //indexes for loaJoints given in ascendant order
073: //Joint.HumanoidRoot, Joint.sacroiliac, Joint.l_hip, Joint.l_knee, Joint.l_ankle, Joint.l_subtalar,
074: //Joint.l_midtarsal, Joint.l_metatarsal, Joint.r_hip, Joint.r_knee, Joint.r_ankle, Joint.r_subtalar,
075: //Joint.r_midtarsal, Joint.r_metatarsal, Joint.vl5, Joint.vl4, Joint.vl3, Joint.vl2, Joint.vl1,
076: //Joint.vt12, Joint.vt11, Joint.vt10, Joint.vt9, Joint.vt8, Joint.vt7, Joint.vt6, Joint.vt5, Joint.vt4,
077: //Joint.vt3, Joint.vt2, Joint.vt1, Joint.vc7, Joint.vc6, Joint.vc5, Joint.vc4, Joint.vc3, Joint.vc2,
078: //Joint.vc1, Joint.skullbase, Joint.l_eyelid_joint, Joint.r_eyelid_joint, Joint.l_eyeball_joint,
079: //Joint.r_eyeball_joint, Joint.l_eyebrow_joint, Joint.r_eyebrow_joint, Joint.temporomandibular,
080: //Joint.l_sternoclavicular, Joint.l_acromioclavicular, Joint.l_shoulder, Joint.l_elbow, Joint.l_wrist,
081: //Joint.l_thumb1, Joint.l_thumb2, Joint.l_thumb3, Joint.l_index0, Joint.l_index1, Joint.l_index2,
082: //Joint.l_index3, Joint.l_middle0, Joint.l_middle1, Joint.l_middle2, Joint.l_middle3, Joint.l_ring0,
083: //Joint.l_ring1, Joint.l_ring2, Joint.l_ring3, Joint.l_pinky0, Joint.l_pinky1, Joint.l_pinky2,
084: //Joint.l_pinky3, Joint.r_sternoclavicular, Joint.r_acromioclavicular, Joint.r_shoulder, Joint.r_elbow,
085: //Joint.r_wrist, Joint.r_thumb1, Joint.r_thumb2, Joint.r_thumb3, Joint.r_index0, Joint.r_index1,
086: //Joint.r_index2, Joint.r_index3, Joint.r_middle0, Joint.r_middle1, Joint.r_middle2, Joint.r_middle3,
087: //Joint.r_ring0, Joint.r_ring1, Joint.r_ring2, Joint.r_ring3, Joint.r_pinky0, Joint.r_pinky1,
088: //Joint.r_pinky2, Joint.r_pinky3, Joint.NonStandard
089:
090: //the following joints are not included in the loa also they are defined by h-anim
091: //it is assumed they are level 4 (all non standard joints)
092: //Joint.l_eyelid_joint;
093: //Joint.r_eyelid_joint;
094: //Joint.l_eyebrow_joint;
095: //Joint.r_eyebrow_joint;
096: //Joint.temporomandibular;
097: //Joint.NonStandard;
098:
099: static int[] loaJointsTable = { 0, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 2,
100: 1, 2, 1, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
101: 3, 3, 2, 3, 2, 3, 1, 4, 4, 3, 3, 4, 4, 4, 2, 2, 1, 1, 1, 2,
102: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
103: 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
104: 2, 2, 4 };
105:
106: //indexes for loaSites given in ascendant order
107: //Site.l_middistal_tip, Site.l_forefoot_tip, Site.l_metatarsal_pha5, Site.l_digit2, Site.l_metatarsal_pha1,
108: //Site.l_lateral_malleolus, Site.l_medial_malleolus, Site.l_sphyrion, Site.l_calcaneous_post,
109: //Site.l_knee_crease, Site.l_femoral_lateral_epicn, Site.l_femoral_medial_epicn, Site.r_middistal_tip,
110: //Site.r_forefoot_tip, Site.r_metatarsal_pha5, Site.r_digit2, Site.r_metatarsal_pha1,
111: //Site.r_lateral_malleolus, Site.r_medial_malleolus, Site.r_sphyrion, Site.r_calcaneous_post,
112: //Site.r_knee_crease, Site.r_femoral_lateral_epicn, Site.r_femoral_medial_epicn, Site.r_iliocristale,
113: //Site.r_trochanterion, Site.l_iliocristale, Site.l_trochanterion, Site.r_asis, Site.l_asis, Site.r_psis,
114: //Site.l_psis, Site.crotch, Site.skull_tip, Site.sellion, Site.r_infraorbitale, Site.l_infraorbitale,
115: //Site.supramenton, Site.r_tragion, Site.r_gonion, Site.l_tragion, Site.l_gonion, Site.nuchale,
116: //Site.l_hand_tip, Site.r_neck_base, Site.l_neck_base, Site.l_thumb_distal_tip, Site.l_index_distal_tip,
117: //Site.l_dactylion, Site.l_middle_distal_tip, Site.l_ring_distal_tip, Site.l_pinky_distal_tip,
118: //Site.l_metacarpal_pha2, Site.l_ulnar_styloid, Site.l_metacarpal_pha5, Site.l_radial_styloid,
119: //Site.l_olecranon, Site.l_humeral_medial_epicn, Site.l_radiale, Site.l_humeral_lateral_epicn,
120: //Site.r_hand_tip, Site.l_clavicale, Site.l_acromion, Site.l_axilla_ant, Site.l_axilla_post,
121: //Site.r_thumb_distal_tip, Site.r_index_distal_tip, Site.r_dactylion, Site.r_middle_distal_tip,
122: //Site.r_ring_distal_tip, Site.r_pinky_distal_tip, Site.r_metacarpal_pha2, Site.r_ulnar_styloid,
123: //Site.r_metacarpal_pha5, Site.r_radial_styloid, Site.r_olecranon, Site.r_humeral_medial_epicn,
124: //Site.r_radiale, Site.r_humeral_lateral_epicn, Site.r_clavicale, Site.r_acromion, Site.r_axilla_ant,
125: //Site.r_axilla_post, Site.suprasternale, Site.cervicale, Site.r_thelion, Site.l_thelion, Site.substernale,
126: //Site.r_rib10, Site.l_rib10, Site.rib10_midspine, Site.waist_preferred_post, Site.navel, Site.NonStandard
127:
128: //please note that there is a problem in h-anim with sites since:
129: //1. a h-anim level 1 compatible avatar should contain:
130: // l_middistal_tip, r_middistal_tip, l_hand_tip, r_hand_tip (among others)
131: //2. a h-anim level 2 compatible avatar should contain:
132: // l_forefoot_tip, r_forefoot_tip, l_middle_distal_tip, r_middle_distal_tip (among others)
133: // but not the four Sites given in 1.
134: //this is a problem since levels of articulation are given in ascendant order
135: //however, l_middistal_tip is just the same name for l_forefoot_tip (and so on for the other three)
136: //
137: //therefore we assume that an avatar is level 1 compatible if it contains either of each pair
138: //(both of a pair could be considered as an error but we assume that users won't use both)
139: //(same conditions applies for higher order levels)
140:
141: static int[] loaSitesTable = { 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
142: 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, 0, 2, 2, 2,
144: 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 2, 0, 2, 2, 2, 0,
145: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
146: 0, 4 };
147:
148: static int loa0Joints, loa1Joints, loa2Joints, loa3Joints,
149: loa4Joints;
150: static int loa0Sites, loa1Sites, loa2Sites, loa3Sites, loa4Sites;
151:
152: static boolean[] definedJoints;
153: static boolean[] definedSites;
154:
155: /**
156: * Construct a new HAnimLevelsOfAnimation. This class has only to be instanciated once.
157: */
158:
159: public HAnimLevelsOfAnimation() {
160:
161: //static because of method: beware of concurrent access !
162: definedJoints = new boolean[loaJointsTable.length];
163: definedSites = new boolean[loaSitesTable.length];
164:
165: loa0Joints = 0;
166: loa1Joints = 0;
167: loa2Joints = 0;
168: loa3Joints = 0;
169: loa4Joints = 0;
170:
171: loa0Sites = 0;
172: loa1Sites = 0;
173: loa2Sites = 0;
174: loa3Sites = 0;
175: loa4Sites = 0;
176:
177: //recompute the number of joints per level just in case a developper (you ?) modify the standard list of joints
178: for (int i = 0; i < loaJointsTable.length; i++) {
179: switch (loaJointsTable[i]) {
180: case 0:
181: loa0Joints++;
182: break;
183: case 1:
184: loa1Joints++;
185: break;
186: case 2:
187: loa2Joints++;
188: break;
189: case 3:
190: loa3Joints++;
191: break;
192: default:
193: loa4Joints++;
194: break;
195: }
196: }
197:
198: //recompute the number of sites per level just in case a developper (you ?) modify the standard list of joints
199: for (int i = 0; i < loaSitesTable.length; i++) {
200: switch (loaSitesTable[i]) {
201: case 0:
202: loa0Sites++;
203: break;
204: case 1:
205: loa1Sites++;
206: break;
207: case 2:
208: loa2Sites++;
209: break;
210: case 3:
211: loa3Sites++;
212: break;
213: default:
214: loa4Sites++;
215: break;
216: }
217: }
218:
219: }
220:
221: private static void browseTree(Joint joint) {
222: //it is assumed that joint is not null
223:
224: Segment segment;
225: Iterator iterator;
226:
227: definedJoints[Joint.getJointIdentifierNumber(joint.getName())] = true;
228:
229: segment = joint.getSegment();
230:
231: if (segment != null) {
232:
233: iterator = segment.getSites().iterator();
234:
235: while (iterator.hasNext()) {
236: definedSites[Site
237: .getSiteIdentifierNumber(((Site) iterator
238: .next()).getName())] = true;
239: }
240:
241: }
242:
243: iterator = joint.getChildren().iterator();
244:
245: while (iterator.hasNext()) {
246: browseTree((Joint) iterator.next());
247: }
248:
249: }
250:
251: /**
252: * Gets the int level of compatibility of this humanoid. See the H-Anim specification for more details.
253: * @param humanoid the humanoid to check the level of compatibility
254: * @return the int from -1 to 3 certifying corresponding level of compatibility
255: */
256: public static int getLevelOfCompatibility(Humanoid humanoid) {
257: //there can only be one of each standard joint in the whole tree defined by joint
258: //therefore we can sum the number of joints for each level to compare with the standard number for each level
259: //doing this saves a lot of computer time
260:
261: int loa0FoundJoints, loa1FoundJoints, loa2FoundJoints, loa3FoundJoints, loa4FoundJoints;
262: int loa0FoundSites, loa1FoundSites, loa2FoundSites, loa3FoundSites, loa4FoundSites;
263:
264: if (humanoid.getHumanoidRootJoint() != null) {
265:
266: //clear definedJoints
267: for (int i = 0; i < definedJoints.length; i++) {
268: definedJoints[i] = false;
269: }
270: loa0FoundJoints = 0;
271: loa1FoundJoints = 0;
272: loa2FoundJoints = 0;
273: loa3FoundJoints = 0;
274: loa4FoundJoints = 0;
275:
276: //clear definedSites
277: for (int i = 0; i < definedSites.length; i++) {
278: definedSites[i] = false;
279: }
280: loa0FoundSites = 0;
281: loa1FoundSites = 0;
282: loa2FoundSites = 0;
283: loa3FoundSites = 0;
284: loa4FoundSites = 0;
285:
286: //browse the tree defined by joint
287: browseTree(humanoid.getHumanoidRootJoint());
288:
289: //hack to circumvent a problem with h-anim (see top of this file)
290: definedSites[0] = (definedSites[0] || definedSites[1]);
291: definedSites[1] = (definedSites[1] || definedSites[0]);
292: definedSites[12] = (definedSites[12] || definedSites[13]);
293: definedSites[13] = (definedSites[13] || definedSites[12]);
294: definedSites[43] = (definedSites[43] || definedSites[49]);
295: definedSites[49] = (definedSites[49] || definedSites[43]);
296: definedSites[60] = (definedSites[60] || definedSites[68]);
297: definedSites[68] = (definedSites[68] || definedSites[60]);
298:
299: //compute the sums for Joints
300: for (int i = 0; i < definedJoints.length; i++) {
301:
302: if (definedJoints[i]) {
303: switch (loaJointsTable[i]) {
304: case 0:
305: loa0FoundJoints++;
306: break;
307: case 1:
308: loa1FoundJoints++;
309: break;
310: case 2:
311: loa2FoundJoints++;
312: break;
313: case 3:
314: loa3FoundJoints++;
315: break;
316: default:
317: loa4FoundJoints++;
318: break;
319: }
320: }
321:
322: }
323:
324: //compute the sums for Sites
325: for (int i = 0; i < definedSites.length; i++) {
326:
327: if (definedSites[i]) {
328: switch (loaSitesTable[i]) {
329: case 0:
330: loa0FoundSites++;
331: break;
332: case 1:
333: loa1FoundSites++;
334: break;
335: case 2:
336: loa2FoundSites++;
337: break;
338: case 3:
339: loa3FoundSites++;
340: break;
341: default:
342: loa4FoundSites++;
343: break;
344: }
345: }
346:
347: }
348:
349: //return loa
350: if ((loa0Joints == loa0FoundJoints)
351: && (loa0Sites == loa0FoundSites)) {
352: if ((loa1Joints == loa1FoundJoints)
353: && (loa1Sites == loa1FoundSites)) {
354: if ((loa2Joints == loa2FoundJoints)
355: && (loa2Sites == loa2FoundSites)) {
356: if ((loa3Joints == loa3FoundJoints)
357: && (loa3Sites == loa3FoundSites)) {
358: return 3;
359: } else
360: return 2;
361: } else
362: return 1;
363: } else
364: return 0;
365: } else
366: return -1;
367:
368: } else
369: return -1;
370: }
371:
372: }
|