private void applySkinning() { for(FbxBindPose pose : bindMap.values()) pose.fillBindTransforms(); if(limbMap == null) return; List<Bone> bones = new ArrayList<>(); for(FbxNode limb : limbMap.values()) { if(limb.bone != null) { bones.add(limb.bone); limb.buildBindPoseBoneTransform(); } } skeleton = new Skeleton(bones.toArray(new Bone[bones.size()])); skeleton.setBindingPose(); for(FbxNode limb : limbMap.values()) limb.setSkeleton(skeleton); for(FbxSkin skin : skinMap.values()) skin.generateSkinning(); // Attach controls animControl = new AnimControl(skeleton); sceneNode.addControl(animControl); SkeletonControl control = new SkeletonControl(skeleton); sceneNode.addControl(control); }
/** * Remove any bones without vertices from the boneList, so that every hull * shape will contain at least 1 vertex. */ private void filterBoneList(SkeletonControl skeletonControl) { Mesh[] targets = skeletonControl.getTargets(); Skeleton skel = skeletonControl.getSkeleton(); for (int boneI = 0; boneI < skel.getBoneCount(); boneI++) { String boneName = skel.getBone(boneI).getName(); if (boneList.contains(boneName)) { boolean hasVertices = RagdollUtils.hasVertices(boneI, targets, weightThreshold); if (!hasVertices) { boneList.remove(boneName); } } } }
@Override public void visit(Spatial spatial) { SkeletonControl control = spatial.getControl(SkeletonControl.class); if (control != null) { Armature armature = skeletonArmatureMap.get(control.getSkeleton()); SkinningControl skinningControl = new SkinningControl(armature); Map<String, List<Spatial>> attachedSpatials = new HashMap<>(); for (int i = 0; i < control.getSkeleton().getBoneCount(); i++) { Bone b = control.getSkeleton().getBone(i); Node n = control.getAttachmentsNode(b.getName()); n.removeFromParent(); if (!n.getChildren().isEmpty()) { attachedSpatials.put(b.getName(), n.getChildren()); } } spatial.removeControl(control); spatial.addControl(skinningControl); for (String name : attachedSpatials.keySet()) { List<Spatial> spatials = attachedSpatials.get(name); for (Spatial child : spatials) { skinningControl.getAttachmentsNode(name).attachChild(child); } } } }
/** * Update the mesh according to the given transformation matrices * * @param mesh then mesh * @param offsetMatrices the transformation matrices to apply */ private void softwareSkinUpdate(Mesh mesh, Matrix4f[] offsetMatrices) { VertexBuffer tb = mesh.getBuffer(Type.Tangent); if (tb == null) { //if there are no tangents use the classic skinning applySkinning(mesh, offsetMatrices); } else { //if there are tangents use the skinning with tangents applySkinningTangents(mesh, offsetMatrices, tb); } }
@Override protected void controlRender(RenderManager rm, ViewPort vp) { if (!wasMeshUpdated) { updateTargetsAndMaterials(spatial); hwSkinningSupported = testHardwareSupported(rm); switchToSoftware(); switchToHardware(); hwSkinningEnabled = true; } else if (!hwSkinningDesired && hwSkinningEnabled) { switchToSoftware(); hwSkinningEnabled = false; controlRenderHardware(); } else { controlRenderSoftware();
private void controlRenderSoftware() { resetToBind(); // reset morph meshes to bind pose offsetMatrices = skeleton.computeSkinningMatrices(); for (Geometry geometry : targets) { Mesh mesh = geometry.getMesh(); // NOTE: This assumes code higher up has // already ensured this mesh is animated. // Otherwise a crash will happen in skin update. softwareSkinUpdate(mesh, offsetMatrices); } }
public Control cloneForSpatial(Spatial spatial) { Node clonedNode = (Node) spatial; AnimControl ctrl = spatial.getControl(AnimControl.class); SkeletonControl clone = new SkeletonControl(); clone.skeleton = ctrl.getSkeleton(); clone.setSpatial(clonedNode); // Fix attachments for the cloned node for (int i = 0; i < clonedNode.getQuantity(); i++) { // go through attachment nodes, apply them to correct bone Spatial child = clonedNode.getChild(i); if (child instanceof Node) { Node clonedAttachNode = (Node) child; Bone originalBone = (Bone) clonedAttachNode.getUserData("AttachedBone"); if (originalBone != null) { Bone clonedBone = clone.skeleton.getBone(originalBone.getName()); clonedAttachNode.setUserData("AttachedBone", clonedBone); clonedBone.setAttachmentsNode(clonedAttachNode); } } } return clone; }
SkinData skinData = new SkinData(); skinData.bones = bones; skinData.skeletonControl = new SkeletonControl(skeleton); skinData.animControl = new AnimControl(skinData.skeletonControl.getSkeleton()); addToCache("skins", index, skinData, nodes.size()); skinnedSpatials.put(skinData, new ArrayList<Spatial>());
skeleton = sc.getSkeleton(); for (int boneI = 0; boneI < skeleton.getBoneCount(); boneI++) { String boneName = skeleton.getBone(boneI).getName();
@Override public void simpleInitApp() { flyCam.setMoveSpeed(10f); cam.setLocation(new Vector3f(6.4013605f, 7.488437f, 12.843031f)); cam.setRotation(new Quaternion(-0.060740203f, 0.93925786f, -0.2398315f, -0.2378785f)); DirectionalLight dl = new DirectionalLight(); dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal()); dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f)); rootNode.addLight(dl); Spatial model = (Spatial) assetManager.loadModel("Models/Oto/OtoOldAnim.j3o"); model.center(); control = model.getControl(AnimControl.class); control.addListener(this); channel = control.createChannel(); for (String anim : control.getAnimationNames()) System.out.println(anim); channel.setAnim("stand"); geom = (Geometry)((Node)model).getChild(0); SkeletonControl skeletonControl = model.getControl(SkeletonControl.class); Box b = new Box(.25f,3f,.25f); Geometry item = new Geometry("Item", b); item.move(0, 1.5f, 0); item.setMaterial(assetManager.loadMaterial("Common/Materials/RedColor.j3m")); Node n = skeletonControl.getAttachmentsNode("hand.right"); n.attachChild(item); rootNode.attachChild(model); inputManager.addListener(this, "Attack"); inputManager.addMapping("Attack", new KeyTrigger(KeyInput.KEY_SPACE)); }
public SkeletonDebugger addSkeleton(SkeletonControl skeletonControl, boolean guessBonesOrientation) { Skeleton skeleton = skeletonControl.getSkeleton(); Spatial forSpatial = skeletonControl.getSpatial(); return addSkeleton(skeleton, forSpatial, guessBonesOrientation); }
private void findTargets(Node node) { for (Spatial child : node.getChildren()) { if (child instanceof Geometry) { findTargets((Geometry) child); } else if (child instanceof Node) { findTargets((Node) child); } } }
/** * Build a map of mesh vertices in a subtree of the scene graph. * * @param model the root of the subtree (may be null) * @return a new map (not null) */ public static Map<Integer, List<Float>> buildPointMap(Spatial model) { Map<Integer, List<Float>> map = new HashMap<>(); SkeletonControl skeletonCtrl = model.getControl(SkeletonControl.class); Mesh[] targetMeshes = skeletonCtrl.getTargets(); for (Mesh mesh : targetMeshes) { buildPointMapForMesh(mesh, map); } return map; }
@Override protected void controlRender(RenderManager rm, ViewPort vp) { if (!wasMeshUpdated) { updateTargetsAndMaterials(spatial); hwSkinningSupported = testHardwareSupported(rm); switchToSoftware(); switchToHardware(); hwSkinningEnabled = true; } else if (!hwSkinningDesired && hwSkinningEnabled) { switchToSoftware(); hwSkinningEnabled = false; controlRenderHardware(); } else { controlRenderSoftware();
@Override public Control cloneForSpatial(Spatial spatial) { Node clonedNode = (Node) spatial; SkeletonControl clone = new SkeletonControl(); clone.hwSkinningTested = this.hwSkinningTested; clone.setSpatial(clonedNode);
skeleton = sc.getSkeleton(); for (int boneI = 0; boneI < skeleton.getBoneCount(); boneI++) { String boneName = skeleton.getBone(boneI).getName();
@Override public void simpleInitApp() { flyCam.setMoveSpeed(10f); cam.setLocation(new Vector3f(6.4f, 7.5f, 12.8f)); cam.setRotation(new Quaternion(-0.060740203f, 0.93925786f, -0.2398315f, -0.2378785f)); DirectionalLight dl = new DirectionalLight(); dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal()); dl.setColor(ColorRGBA.White); rootNode.addLight(dl); Spatial model = assetManager.loadModel("Models/Jaime/Jaime.j3o"); control = model.getControl(AnimControl.class); SkeletonControl skeletonControl = model.getControl(SkeletonControl.class); model.center(); model.setLocalScale(5f); control.addListener(this); channel = control.createChannel(); channel.setAnim("Idle"); Box box = new Box(0.3f, 0.02f, 0.02f); Geometry saber = new Geometry("saber", box); saber.move(0.4f, 0.05f, 0.01f); Material red = assetManager.loadMaterial("Common/Materials/RedColor.j3m"); saber.setMaterial(red); Node n = skeletonControl.getAttachmentsNode("hand.R"); n.attachChild(saber); rootNode.attachChild(model); inputManager.addListener(this, "Attack"); inputManager.addMapping("Attack", new KeyTrigger(KeyInput.KEY_SPACE)); }
private void controlRenderSoftware() { resetToBind(); // reset morph meshes to bind pose offsetMatrices = skeleton.computeSkinningMatrices(); for (Mesh mesh : targets) { // NOTE: This assumes that code higher up // Already ensured those targets are animated // otherwise a crash will happen in skin update softwareSkinUpdate(mesh, offsetMatrices); } }
/** * Update the mesh according to the given transformation matrices * * @param mesh then mesh * @param offsetMatrices the transformation matrices to apply */ private void softwareSkinUpdate(Mesh mesh, Matrix4f[] offsetMatrices) { VertexBuffer tb = mesh.getBuffer(Type.Tangent); if (tb == null) { //if there are no tangents use the classic skinning applySkinning(mesh, offsetMatrices); } else { //if there are tangents use the skinning with tangents applySkinningTangents(mesh, offsetMatrices, tb); } }
/** * Update the lists of animation targets. * * @param spatial the controlled spatial */ private void updateTargetsAndMaterials(Spatial spatial) { targets.clear(); if (spatial instanceof Node) { findTargets((Node) spatial); } else if (spatial instanceof Geometry) { findTargets((Geometry) spatial); } } }