private static void linkTrianglesToBones( E3DActor actor, HashMap orphanedTriangleBoneAttachments) { ArrayList triangleList = actor.getTriangleList(); E3DTriangle triangle = null; for (int i = 0; i < triangleList.size(); i++) { triangle = (E3DTriangle) triangleList.get(i); if (orphanedTriangleBoneAttachments.containsKey(triangle)) { VertexBoneInformation boneInfo = (VertexBoneInformation) orphanedTriangleBoneAttachments.get(triangle); E3DBone bone; for (int b = 0; b < 3; b++) { bone = actor.getSkeleton().findBoneByID(boneInfo.boneIDs[b]); if (bone != null) bone.attachVertex(triangle.getVertex(b)); else actor .getEngine() .getLogger() .writeLine( E3DEngineLogger.SEVERITY_WARNING, "The bone: " + E3DStringHelper.getNonNullableString(boneInfo.boneIDs[b]) + " could not be found in the actor thus vertices were not linked to it."); } } } }
private static boolean readActor( BufferedReader actorFile, StringTokenizer tokenizer, E3DActor actor) throws IOException { String str; String line; boolean startBlockFound = false; boolean endBlockFound = false; // Hold onto bones that don't have parents yet // (String parentBoneID, (ArrayList)E3DBone bone) E3DHashListMap orphanedBones = new E3DHashListMap(); // We can't attach triangles to bones until the bones are all loaded, so we do that in the end // (E3DTriangle triangle, VertexBoneInformation boneInformation) HashMap orphanedTriangleBoneAttachments = new HashMap(); while (!endBlockFound && (line = actorFile.readLine()) != null) { tokenizer = new StringTokenizer(line, TOKENIZER_CHARS); while (!endBlockFound && tokenizer.hasMoreTokens()) { str = readNextValue(tokenizer); if (START_BLOCK.equals(str)) { startBlockFound = true; } else if (ACTORTAG_BONE.equals(str)) { if (!startBlockFound) return false; String boneID = readNextValue(tokenizer); String parentBoneID = readNextValue(tokenizer); E3DBone bone = readBone(actor.getEngine(), actorFile, boneID); if (bone != null) { if (!actor.getSkeleton().addBone(bone, parentBoneID)) orphanedBones.put(parentBoneID, bone); else // did add it, so there may be some children of it { // by the time we get done adding the last bone, we should be able to link up all // children linkOrphanedBonesToNewBone(actor, bone, orphanedBones); } } else actor .getEngine() .getLogger() .writeLine( E3DEngineLogger.SEVERITY_WARNING, "Unable to read bone: " + E3DStringHelper.getNonNullableString(boneID) + ". Possibly missing attributes or malformed definition."); } else if (ACTORTAG_TRIANGLE.equals(str)) { if (!startBlockFound) return false; TempTriangle tempTriangle = readTriangle(actor.getEngine(), actorFile); if (tempTriangle != null) { E3DTriangle triangle = tempTriangle.triangle; VertexBoneInformation boneInformation = tempTriangle.vertexBoneInformation; if (triangle != null) { actor.getMesh().addTriangle(triangle); if (boneInformation != null) // these will be linked later orphanedTriangleBoneAttachments.put(triangle, boneInformation); } } } else if (ACTORTAG_ANIMATION.equals(str)) { if (!startBlockFound) return false; String animationName = readNextValue(tokenizer); String fps = readNextValue(tokenizer); double dFPS = 20.0; try { dFPS = Double.parseDouble(fps); } catch (NumberFormatException e) { actor .getEngine() .getLogger() .writeLine( E3DEngineLogger.SEVERITY_WARNING, "No FPS specified for animation. 20 FPS will be used by default (1 frame == 0.5s)"); } if (dFPS == 0) dFPS = 20.0; E3DAnimation animation = readAnimation(actor.getEngine(), animationName, dFPS, actorFile); if (animation != null) actor.getSkeleton().addAnimation(animation); } else if (COMMENT.equals(str)) break; else if (END_BLOCK.equals(str)) endBlockFound = true; else actor .getEngine() .getLogger() .writeLine( E3DEngineLogger.SEVERITY_INFO, "Unknown tag in actor model definition: " + str); } } linkTrianglesToBones(actor, orphanedTriangleBoneAttachments); return endBlockFound; }