/** Creates a nested copy of this Node, any child nodes are copied using the {@link #copy()} method. This will detach this node * from its parent, but does not attach it to the parent of node being copied. The {@link #parts} are copied using the * {@link NodePart#copy()} method. Note that that method copies the material and nodes (bones) by reference. If you intend to * use this node in a different node tree (e.g. a different Model or ModelInstance) then you will need to update these * references afterwards. * * Override this method in your custom Node class to copy any additional fields you've added. * @return This Node for chaining */ protected Node set (Node other) { detach(); id = other.id; isAnimated = other.isAnimated; inheritTransform = other.inheritTransform; translation.set(other.translation); rotation.set(other.rotation); scale.set(other.scale); localTransform.set(other.localTransform); globalTransform.set(other.globalTransform); parts.clear(); for (NodePart nodePart : other.parts) { parts.add(nodePart.copy()); } children.clear(); for (Node child : other.getChildren()) { addChild(child.copy()); } return this; }
/** Adds the nodes of the specified model to a new node of the model being build. After this method the given model can no * longer be used. Do not call the {@link Model#dispose()} method on that model. * @return The newly created node containing the nodes of the given model. */ public Node node (final String id, final Model model) { final Node node = new Node(); node.id = id; node.addChildren(model.nodes); node(node); for (final Disposable disposable : model.getManagedDisposables()) manage(disposable); return node; }
/** Creates a nested copy of this Node, any child nodes are copied using this method as well. The {@link #parts} are copied * using the {@link NodePart#copy()} method. Note that that method copies the material and nodes (bones) by reference. If you * intend to use the copy in a different node tree (e.g. a different Model or ModelInstance) then you will need to update these * references afterwards. * * Override this method in your custom Node class to instantiate that class, in that case you should override the * {@link #set(Node)} method as well. */ public Node copy () { return new Node().set(this); }
protected void getRenderables (Node node, Array<Renderable> renderables, Pool<Renderable> pool) { if (node.parts.size > 0) { for (NodePart nodePart : node.parts) { if (nodePart.enabled) renderables.add(getRenderable(pool.obtain(), node, nodePart)); } } for (Node child : node.getChildren()) { getRenderables(child, renderables, pool); } }
part.parts.add(node.parts.get(i).meshPart); if (node.hasChildren()) { final boolean transformed = applyTransform && !Arrays.equals(transform.val, idt.val); final int o = transformed ? out.size : offset; getShapeParts(node.getChildren(), out, o, pool); if (transformed) { for (int i = o, n = out.size; i < n; i++) {
/** @param model The source {@link Model} * @param transform The {@link Matrix4} instance for this ModelInstance to reference or null to create a new matrix. * @param nodeId The ID of the {@link Node} within the {@link Model} for the instance to contain * @param recursive True to recursively search the Model's node tree, false to only search for a root node * @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true). * @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */ public ModelInstance (final Model model, final Matrix4 transform, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform, boolean shareKeyframes) { this.model = model; this.transform = transform == null ? new Matrix4() : transform; Node copy, node = model.getNode(nodeId, recursive); this.nodes.add(copy = node.copy()); if (mergeTransform) { this.transform.mul(parentTransform ? node.globalTransform : node.localTransform); copy.translation.set(0, 0, 0); copy.rotation.idt(); copy.scale.set(1, 1, 1); } else if (parentTransform && copy.hasParent()) this.transform.mul(node.getParent().globalTransform); invalidate(); copyAnimations(model.animations, shareKeyframes); calculateTransforms(); }
Gdx.app.log("Test", anim.id); ship = assets.get("data/g3d/ship.obj", Model.class).nodes.get(0).copy(); ship.detach(); ship.translation.x = 10f; // offset from the sword node to the tip of the sword, in rest pose ship.rotation.set(Vector3.Z, 90f); ship.scale.scl(5f); ship.parts.get(0).enabled = false; character.getNode("sword").addChild(ship);
private void drawArmatureNodes(Node currentNode, Vector3 modelPos, Quaternion modelRot, Vector3 parentNodePos, Vector3 currentNodePos) { currentNode.globalTransform.getTranslation(currentNodePos); modelRot.transform(currentNodePos); currentNodePos.add(modelPos); drawVertex(currentNodePos, 0.02f, Color.GREEN); shapeRenderer.setColor(Color.YELLOW); if (currentNode.hasParent()) { shapeRenderer.line(parentNodePos, currentNodePos); } if (currentNode.hasChildren()) { float x = currentNodePos.x; float y = currentNodePos.y; float z = currentNodePos.z; for (Node child : currentNode.getChildren()) { drawArmatureNodes(child, modelPos, modelRot, currentNodePos, parentNodePos); currentNodePos.set(x, y, z); } } }
private void copyNodes (Array<Node> nodes, final Array<String> nodeIds) { for (int i = 0, n = nodes.size; i < n; ++i) { final Node node = nodes.get(i); for (final String nodeId : nodeIds) { if (nodeId.equals(node.id)) { this.nodes.add(node.copy()); break; } } } invalidate(); }
/** Makes sure that each {@link NodePart} of the {@link Node} and its sub-nodes, doesn't reference a node outside this node * tree and that all materials are listed in the {@link #materials} array. */ private void invalidate (Node node) { for (int i = 0, n = node.parts.size; i < n; ++i) { NodePart part = node.parts.get(i); ArrayMap<Node, Matrix4> bindPose = part.invBoneBindTransforms; if (bindPose != null) { for (int j = 0; j < bindPose.size; ++j) { bindPose.keys[j] = getNode(bindPose.keys[j].id); } } if (!materials.contains(part.material, true)) { final int midx = materials.indexOf(part.material, false); if (midx < 0) materials.add(part.material = part.material.copy()); else part.material = materials.get(midx); } } for (int i = 0, n = node.getChildCount(); i < n; ++i) { invalidate(node.getChild(i)); } }
/** * Direction vector of an armature bone, in world coordinate system. * * @param nodeId Name of the bone * @param out Output vector * @return Output vector for chaining */ public Vector3 getBoneDirection(String nodeId, Vector3 out) { Node node = modelInstance.getNode(nodeId); Node endPointNode = (node.hasChildren()) ? node.getChild(0) : node; node.globalTransform.getTranslation(TMP_V1); endPointNode.globalTransform.getTranslation(TMP_V2); TMP_V1.sub(TMP_V2).scl(-1); modelInstance.transform.getRotation(TMP_Q); TMP_Q.transform(TMP_V1); return out.set(TMP_V1).nor(); }
/** Add a node to the model. Use any of the part(...) method to add a NodePart. * @return The node being created. */ public Node node () { final Node node = new Node(); node(node); node.id = "node" + model.nodes.size; return node; }
/** Adds this node as child to specified parent Node, synonym for: <code>parent.addChild(this)</code> * @param parent The Node to attach this Node to. */ public <T extends Node> void attachTo (T parent) { parent.addChild(this); }
/** * @param bodyPart The rigid body which is to be synchronized with a node * @param node The node which is to be synchronized with a body */ private void addPart(btRigidBody bodyPart, Node node) { if (!bodyPartMap.containsKey(bodyPart)) { bodyPartMap.put(bodyPart, new RigidBodyNodeConnection()); } RigidBodyNodeConnection conn = bodyPartMap.get(bodyPart); conn.followNode = node; // Set the follow offset to the middle of the armature bone Vector3 offsetTranslation = new Vector3(); node.getChild(0).localTransform.getTranslation(offsetTranslation).scl(0.5f); conn.bodyNodeOffsets.put(node, offsetTranslation); if (!ragdollMappedNodes.contains(node, true)) { ragdollMappedNodes.add(node); } }
protected void getRenderables (Node node, Array<Renderable> renderables, Pool<Renderable> pool) { if (node.parts.size > 0) { for (NodePart nodePart : node.parts) { if (nodePart.enabled) renderables.add(getRenderable(pool.obtain(), node, nodePart)); } } for (Node child : node.getChildren()) { getRenderables(child, renderables, pool); } }
part.parts.add(node.parts.get(i).meshPart); if (node.hasChildren()) { final boolean transformed = applyTransform && !Arrays.equals(transform.val, idt.val); final int o = transformed ? out.size : offset; getShapeParts(node.getChildren(), out, o, pool); if (transformed) { for (int i = o, n = out.size; i < n; i++) {
/** @param model The source {@link Model} * @param transform The {@link Matrix4} instance for this ModelInstance to reference or null to create a new matrix. * @param nodeId The ID of the {@link Node} within the {@link Model} for the instance to contain * @param recursive True to recursively search the Model's node tree, false to only search for a root node * @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true). * @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */ public ModelInstance (final Model model, final Matrix4 transform, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform, boolean shareKeyframes) { this.model = model; this.transform = transform == null ? new Matrix4() : transform; Node copy, node = model.getNode(nodeId, recursive); this.nodes.add(copy = node.copy()); if (mergeTransform) { this.transform.mul(parentTransform ? node.globalTransform : node.localTransform); copy.translation.set(0, 0, 0); copy.rotation.idt(); copy.scale.set(1, 1, 1); } else if (parentTransform && copy.hasParent()) this.transform.mul(node.getParent().globalTransform); invalidate(); copyAnimations(model.animations, shareKeyframes); calculateTransforms(); }
private void copyNodes (Array<Node> nodes, final String... nodeIds) { for (int i = 0, n = nodes.size; i < n; ++i) { final Node node = nodes.get(i); for (final String nodeId : nodeIds) { if (nodeId.equals(node.id)) { this.nodes.add(node.copy()); break; } } } invalidate(); }