private void init() { float centerX = 0f; float centerY = ((((float) words.length) * FONT_HEIGHT) - FONT_HEIGHT) / 2f; nodes.clear(); nodesPosition = new Array<Vector3>(); if(words != null && words.length > 0){ for(int y = 0; y < words.length; y++){ String[] word = translateSpecialCharacters(words[y]); centerX = (((float) word.length) * FONT_WIDTH) / 2f; for(int x = 0; x < word.length; x++){ String letter = String.valueOf(word[x]); Node node = model.getNode(letter); if(node != null){ Vector3 position = new Vector3((FONT_WIDTH*x) - centerX,(-FONT_HEIGHT*y) + centerY,0); node = node.copy(); node.globalTransform.setTranslation(position); nodes.add(node); nodesPosition.add(position.cpy()); } } } } }
public NodeComponent() { node = new Node(); tempVec = new Vector3(); tempVec2 = new Vector3(); tempQuat = new Quaternion(); translation = new Vector3(); rotation = new Vector3(); scale = new Vector3(1, 1, 1); localTranslation = new Vector3(); localRotation = new Vector3(); localScale = new Vector3(1, 1, 1); translationDelta = new Vector3(); rotationDelta = new Vector3(); scaleDelta = new Vector3(); localRotationQuaternion = new Quaternion(); rotationQuaternion = new Quaternion(); }
/** * Updates the rigid body parts to follow nodes of the model instance */ private void updateBodiesToArmature() { // Ragdoll parts should follow the model animation. // Loop over each part and set it to the global transform of the armature node it should follow. capsuleTransform.set(modelTransform); for (Iterator<ObjectMap.Entry<btRigidBody, RigidBodyNodeConnection>> iterator = bodyPartMap.iterator(); iterator.hasNext(); ) { ObjectMap.Entry<btRigidBody, RigidBodyNodeConnection> entry = iterator.next(); RigidBodyNodeConnection data = entry.value; btRigidBody body = entry.key; Node followNode = data.followNode; Vector3 offset = data.bodyNodeOffsets.get(followNode); body.proceedToTransform(tmpMatrix.set(capsuleTransform) .mul(followNode.globalTransform).translate(offset)); } }
/** * @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); } }
/** * Creates and adds the navmesh to this scene. */ private void setNavmesh(GameObjectBlueprint bp) { // We need to set the node transforms before calculating the navmesh shape GameModel gameModel = new GameModel(bp.model, bp.name, bp.position, bp.rotation, bp.scale); Array<NodePart> nodes = gameModel.modelInstance.model.getNode("navmesh").parts; // Sort the model meshParts array according to material name nodes.sort(new NavMeshNodeSorter()); // The model transform must be applied to the meshparts for shape generation to work correctly. gameModel.modelInstance.calculateTransforms(); Matrix4 transform = new Matrix4(); for (Node node : gameModel.modelInstance.nodes) { transform.set(node.globalTransform).inv(); for (NodePart nodePart : node.parts) { nodePart.meshPart.mesh.transform(transform); } } navMesh = new NavMesh(gameModel.modelInstance.model); btCollisionShape shape = navMesh.getShape(); navmeshBody = new InvisibleBody("navmesh", shape, 0, gameModel.modelInstance.transform, GameEngine.NAVMESH_FLAG, GameEngine.NAVMESH_FLAG, false, false); worldBounds.set(gameModel.boundingBox); gameModel.dispose(); }
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); } } }
@Deprecated public static Model createFromMesh (final Mesh mesh, int indexOffset, int vertexCount, int primitiveType, final Material material) { Model result = new Model(); MeshPart meshPart = new MeshPart(); meshPart.id = "part1"; meshPart.indexOffset = indexOffset; meshPart.numVertices = vertexCount; meshPart.primitiveType = primitiveType; meshPart.mesh = mesh; NodePart partMaterial = new NodePart(); partMaterial.material = material; partMaterial.meshPart = meshPart; Node node = new Node(); node.id = "node1"; node.parts.add(partMaterial); result.meshes.add(mesh); result.materials.add(material); result.nodes.add(node); result.meshParts.add(meshPart); result.manageDisposable(mesh); return result; }
/** Convenience method to create a model with three orthonormal vectors shapes. The resources the Material might contain are not * managed, use {@link Model#manageDisposable(Disposable)} to add those to the model. * @param axisLength Length of each axis. * @param capLength is the height of the cap in percentage, must be in (0,1) * @param stemThickness is the percentage of stem diameter compared to cap diameter, must be in (0,1] * @param divisions the amount of vertices used to generate the cap and stem ellipsoidal bases */ public Model createXYZCoordinates (float axisLength, float capLength, float stemThickness, int divisions, int primitiveType, Material material, long attributes) { begin(); MeshPartBuilder partBuilder; Node node = node(); partBuilder = part("xyz", primitiveType, attributes, material); partBuilder.setColor(Color.RED); partBuilder.arrow(0, 0, 0, axisLength, 0, 0, capLength, stemThickness, divisions); partBuilder.setColor(Color.GREEN); partBuilder.arrow(0, 0, 0, 0, axisLength, 0, capLength, stemThickness, divisions); partBuilder.setColor(Color.BLUE); partBuilder.arrow(0, 0, 0, 0, 0, axisLength, capLength, stemThickness, divisions); return end(); }
private void loadAnimations (Iterable<ModelAnimation> modelAnimations) { for (final ModelAnimation anim : modelAnimations) { Animation animation = new Animation(); animation.id = anim.id; for (ModelNodeAnimation nanim : anim.nodeAnimations) { final Node node = getNode(nanim.nodeId); if (node == null) continue; NodeAnimation nodeAnim = new NodeAnimation(); nodeAnim.node = node; for (ModelNodeKeyframe kf : nanim.keyframes) { if (kf.keytime > animation.duration) animation.duration = kf.keytime; NodeKeyframe keyframe = new NodeKeyframe(); keyframe.keytime = kf.keytime; keyframe.rotation.set(kf.rotation == null ? node.rotation : kf.rotation); keyframe.scale.set(kf.scale == null ? node.scale : kf.scale); keyframe.translation.set(kf.translation == null ? node.translation : kf.translation); nodeAnim.keyframes.add(keyframe); } if (nodeAnim.keyframes.size > 0) animation.nodeAnimations.add(nodeAnim); } if (animation.nodeAnimations.size > 0) animations.add(animation); } }
/** @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; nodePartBones.clear(); Node copy, node = model.getNode(nodeId, recursive); this.nodes.add(copy = copyNode(node)); 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); setBones(); copyAnimations(model.animations, shareKeyframes); calculateTransforms(); }
private Node copyNode (Node node) { Node copy = new Node(); copy.id = node.id; copy.inheritTransform = node.inheritTransform; copy.translation.set(node.translation); copy.rotation.set(node.rotation); copy.scale.set(node.scale); copy.localTransform.set(node.localTransform); copy.globalTransform.set(node.globalTransform); for (NodePart nodePart : node.parts) { copy.parts.add(copyNodePart(nodePart)); } for (Node child : node.getChildren()) { copy.addChild(copyNode(child)); } return copy; }
@Deprecated public static Model createFromMesh(final Mesh mesh, int indexOffset, int vertexCount, int primitiveType, final Material material) { Model result = new Model(); MeshPart meshPart = new MeshPart(); meshPart.id = "part1"; meshPart.offset = indexOffset; meshPart.size = vertexCount; meshPart.primitiveType = primitiveType; meshPart.mesh = mesh; NodePart partMaterial = new NodePart(); partMaterial.material = material; partMaterial.meshPart = meshPart; Node node = new Node(); node.id = "node1"; node.parts.add(partMaterial); result.meshes.add(mesh); result.materials.add(material); result.nodes.add(node); result.meshParts.add(meshPart); result.manageDisposable(mesh); return result; }
/** players are represented by cubes, with another cube marking the direction it is facing */ public void createPlayerModel() { ModelBuilder mb = new ModelBuilder(); ModelBuilder mb2 = new ModelBuilder(); long attr = Usage.Position | Usage.Normal; float r = 0.5f; float g = 1f; float b = 0.75f; Material material = new Material(ColorAttribute.createDiffuse(new Color(r, g, b, 1f))); Material faceMaterial = new Material(ColorAttribute.createDiffuse(Color.BLUE)); float w = 1f; float d = w; float h = 2f; mb.begin(); //playerModel = mb.createBox(w, h, d, material, attr); Node node = mb.node("box", mb2.createBox(w, h, d, material, attr)); // the face is just a box to show which direction the player is facing Node faceNode = mb.node("face", mb2.createBox(w/2, h/2, d/2, faceMaterial, attr)); faceNode.translation.set(0f, 0f, d/2); playerModel = mb.end(); }
/** client builds statics, probably based on info from server */ public static void buildStatics(LevelStatic[] statics) { if (staticGeometry == null) { staticGeometry = new Array<>(); } Log.debug("client building statics received from server: " + statics.length); ModelBuilder mb = new ModelBuilder(); mb.begin(); for (LevelStatic stat : statics) { Model model = Assets.manager.get(stat.modelName, Model.class); setupStaticModel(model.meshParts, stat.mtx, true); Node node = mb.node("piece", model); stat.mtx.getTranslation(tmp); node.translation.set(tmp); node.rotation.set(stat.mtx.getRotation(q)); } Model finalModel = mb.end(); ModelInstance instance = new ModelInstance(finalModel); staticGeometry.add(instance); }
/** @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 SharedModel(final Model model, final Matrix4 transform, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) { this.model = model; this.transform = transform == null ? new Matrix4() : transform; nodePartBones.clear(); Node copy, node = model.getNode(nodeId, recursive); this.nodes.add(copy = copyNode(null, node)); 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.parent != null) this.transform.mul(node.parent.globalTransform); setBones(); copyAnimations(model.animations); calculateTransforms(); }
private Node copyNode(Node parent, Node node) { Node copy = new Node(); copy.id = node.id; //copy.boneId = node.boneId; copy.parent = parent; copy.translation.set(node.translation); copy.rotation.set(node.rotation); copy.scale.set(node.scale); copy.localTransform.set(node.localTransform); copy.globalTransform.set(node.globalTransform); for(NodePart nodePart: node.parts) { copy.parts.add(copyNodePart(nodePart)); } for(Node child: node.children) { copy.children.add(copyNode(copy, child)); } return copy; }
private void copyAnimations (final Iterable<Animation> source) { for (final Animation anim : source) { Animation animation = new Animation(); animation.id = anim.id; animation.duration = anim.duration; for (final NodeAnimation nanim : anim.nodeAnimations) { final Node node = getNode(nanim.node.id); if (node == null) continue; NodeAnimation nodeAnim = new NodeAnimation(); nodeAnim.node = node; for (final NodeKeyframe kf : nanim.keyframes) { NodeKeyframe keyframe = new NodeKeyframe(); keyframe.keytime = kf.keytime; keyframe.rotation.set(kf.rotation); keyframe.scale.set(kf.scale); keyframe.translation.set(kf.translation); nodeAnim.keyframes.add(keyframe); } if (nodeAnim.keyframes.size > 0) animation.nodeAnimations.add(nodeAnim); } if (animation.nodeAnimations.size > 0) animations.add(animation); } }
private void doneLoading() { Model model = assets.get("data/g3d/test.g3db", Model.class); for (int i = 0; i < model.nodes.size; i++) { Node node = model.nodes.get(i); log.debug("loader node " + node.id); if (node.id.equals("test_root")) { node = node.getChild("Building", false, false); log.debug("loader node " + node.id); node.rotation.setFromAxis(1, 0, 0, 90); mModel = model; break; } //} } loading = false; }
protected void collectModelNodeVertexPositions(Node node, Array<Vector3> destVertices, Vector3 scaleFactor, Vector3 positionOffset) { final Matrix4 transform = node.globalTransform; for (int i = 0; i < node.parts.size; ++i) { NodePart nodePart = node.parts.get(i); MeshPart meshPart = nodePart.meshPart; ShortBuffer indices = meshPart.mesh.getIndicesBuffer(); FloatBuffer vertices = meshPart.mesh.getVerticesBuffer(); final int strideInFloats = meshPart.mesh.getVertexSize() / (Float.SIZE / 8); for (int j = 0; j < meshPart.numVertices; ++j) { int index = indices.get(meshPart.indexOffset + j); int offset = index * strideInFloats; tmpPosition.set(vertices.get(offset), vertices.get(offset + 1), vertices.get(offset + 2)) .add(positionOffset) .scl(scaleFactor) .mul(transform); destVertices.add(new Vector3(tmpPosition)); } } for (int i = 0; i < node.children.size; ++i) collectModelNodeVertexPositions(node.children.get(i), destVertices, scaleFactor, positionOffset); }
public Gun(Matrix4 transform, int hp, int health, int range, float cooldown, EnumSet<Types> types, EnumSet<Effects> effects, ModelInstance instance, btCollisionShape shape, btCollisionWorld world, IntMap<Entity> entities, String attack, EntityTemplate<Bullet> projectile, Vector3 attackOffset, Map<String, Sound> sounds) { super(transform, hp, health, range, cooldown, types, effects, instance, shape, world, entities, attack, projectile, attackOffset, sounds); nodes = new HashMap<String, Node>(); /*for(Node node: instance.model.nodes) { System.out.println(node.id); if (node.id.startsWith("Leg")) { legs.add(node); } }*/ //legs.get(0).rotation.setEulerAngles(100, 0, 0); for(Node node: instance.getNode("Gun_root").getChildren()) nodes.put(node.id, node); }
public static btCollisionShape obtainStaticNodeShape (final Node node, final boolean applyTransform) { getShapeParts(node, applyTransform, shapePartArray, 0, shapePartPool); btCollisionShape result = obtainStaticShape(shapePartArray); shapePartPool.freeAll(shapePartArray); shapePartArray.clear(); return result; }
public static btCollisionShape obtainStaticNodeShape (final Array<Node> nodes) { getShapeParts(nodes, shapePartArray, 0, shapePartPool); btCollisionShape result = obtainStaticShape(shapePartArray); shapePartPool.freeAll(shapePartArray); shapePartArray.clear(); return result; }
private NodePart getPart(int index) { ModelInstance inst = gameWorld.renderer().getRenderable(selected()); int i = 0; for (Node node : inst.nodes) { for (NodePart part : node.parts) { if(i == index) return part; i++; } } return null; }
public Hydrogen(int ve, boolean[][][] mtx, PerspectiveCamera cam) { super(ve, mtx, cam); //begin building the model hydrogen_builder.begin(); //first node Node electron_1 = hydrogen_builder.node(); electron_1.id = Hydrogen.VE_1; //make the cube hydrogen_builder.part(Hydrogen.VE_1, GL20.GL_TRIANGLES, VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal, new Material(ColorAttribute.createDiffuse(new Color(195f/255f,207f/255f,255f/255f,1f)))) .box(1f, 1f, 1f); //end the model Model hModel = hydrogen_builder.end(); atom = new ModelInstance(hModel,2,10,2); shadow = new ModelInstance(hModel,2,10,2); frame = new ModelInstance(hModel,2,10,2); frame.transform.scl(.01f); for(int i = 0; i < shadow.materials.size; ++i){ shadow.materials.get(i).set(ColorAttribute.createDiffuse(105/255f,105/255f,105/255f,1f)); frame.materials.get(i).set(ColorAttribute.createDiffuse(Color.WHITE)); } }
private static void buildCave(Matrix4 transform) { Model caveModel = Assets.get(CURR_MODEL, Model.class); if (WORLD.getConstructor("cave") == null) { for (Node n : caveModel.nodes) n.scale.set(.6f, .6f, .6f); btCollisionShape collisionShape = Bullet.obtainStaticNodeShape(caveModel.nodes); collisionShape.setLocalScaling(new Vector3(.6f, .6f, .6f)); WORLD.addConstructor("cave", new BulletConstructor(caveModel, 0, collisionShape)); } BulletEntity cave = WORLD.add("cave", transform); cave.body.setCollisionFlags(cave.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT); cave.body.setActivationState(Collision.DISABLE_DEACTIVATION); cave.body.userData = new BulletUserData("cave", cave); }
public static Model createArrowStub(Material mat, Vector3 from, Vector3 to) { ModelBuilder modelBuilder = new ModelBuilder(); modelBuilder.begin(); MeshPartBuilder meshBuilder; // line meshBuilder = modelBuilder.part("line", GL20.GL_LINES, VertexAttributes.Usage.Position | VertexAttributes.Usage.ColorUnpacked, mat); meshBuilder.line(from.x, from.y, from.z, to.x, to.y, to.z); // stub Node node = modelBuilder.node(); node.translation.set(to.x, to.y, to.z); meshBuilder = modelBuilder.part("stub", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, mat); BoxShapeBuilder.build(meshBuilder, 2, 2, 2); return modelBuilder.end(); }
public static void applyTransform(Vector3 location, Vector3 rotation, Vector3 scale, ModelInstance modelInstance) { for (Node node : modelInstance.nodes) { node.scale.set(Math.abs(scale.x), Math.abs(scale.y), Math.abs(scale.z)); } modelInstance.transform.rotate(Vector3.X, rotation.x); modelInstance.transform.rotate(Vector3.Z, rotation.z); modelInstance.transform.rotate(Vector3.Y, rotation.y); modelInstance.transform.setTranslation(location); modelInstance.calculateTransforms(); }
/** * 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(); }
/** * Midpoint 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 getBoneMidpointWorldPosition(String nodeId, Vector3 out) { Node node = modelInstance.getNode(nodeId); Node endPointNode = (node.hasChildren()) ? node.getChild(0) : node; // Use global transform to account for model scaling node.globalTransform.getTranslation(TMP_V1); TMP_V3.set(TMP_V1); endPointNode.globalTransform.getTranslation(TMP_V2); TMP_V3.sub(TMP_V1.sub(TMP_V2).scl(0.5f)); modelInstance.transform.getRotation(TMP_Q, true).transform(TMP_V3); TMP_V3.add(getPosition()); return out.set(TMP_V3); }
/** * Updates the nodes of the model instance to follow the rigid body parts */ private void updateArmatureToBodies() { // Let dynamicsworld control ragdoll. Loop over all ragdoll part collision shapes // and their node connection data. for (Iterator<ObjectMap.Entry<btRigidBody, RigidBodyNodeConnection>> iterator1 = bodyPartMap.iterator(); iterator1.hasNext(); ) { ObjectMap.Entry<btRigidBody, RigidBodyNodeConnection> bodyEntry = iterator1.next(); btRigidBody partBody = bodyEntry.key; RigidBodyNodeConnection connection = bodyEntry.value; capsuleTransform.getTranslation(capsuleTranslation); // Loop over each node connected to this collision shape for (Iterator<ObjectMap.Entry<Node, Vector3>> iterator2 = connection.bodyNodeOffsets.iterator(); iterator2.hasNext(); ) { ObjectMap.Entry<Node, Vector3> nodeEntry = iterator2.next(); // A node which is to follow this collision shape Node node = nodeEntry.key; // The offset of this node from the untranslated collision shape origin Vector3 offset = nodeEntry.value; // Set the node to the transform of the collision shape it follows partBody.getWorldTransform(node.localTransform); // Calculate difference in translation between the node/ragdoll part and the // base capsule shape. node.localTransform.getTranslation(nodeTranslation); // Calculate the final node transform node.localTransform.setTranslation(nodeTranslation.sub(capsuleTranslation)).translate(tmpVec.set(offset).scl(-1)); } } // Calculate the final transform of the model. modelInstance.calculateTransforms(); }
/** * @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 * @param nodeBodyOffset The offset from the node to rigid body origin */ private void addPart(btRigidBody bodyPart, Node node, Vector3 nodeBodyOffset) { if (!bodyPartMap.containsKey(bodyPart)) { bodyPartMap.put(bodyPart, new RigidBodyNodeConnection()); } RigidBodyNodeConnection conn = bodyPartMap.get(bodyPart); conn.bodyNodeOffsets.put(node, nodeBodyOffset); if (!ragdollMappedNodes.contains(node, true)) { ragdollMappedNodes.add(node); } }
private void setVColorBlendAttributes() { Array<String> modelsIdsInScene = assets.getPlaceholderIdsByType(BlenderModel.class); Array<BlenderModel> instancesWithId = new Array<BlenderModel>(); for (String id : modelsIdsInScene) { instancesWithId.clear(); assets.getPlaceholders(id, BlenderModel.class, instancesWithId); for (BlenderModel blenderModel : instancesWithId) { // Maybe check if // renderable.meshPart.mesh.getVertexAttribute(VertexAttributes.Usage.ColorUnpacked) != null if (blenderModel.custom_properties.containsKey("v_color_material_blend")) { Model model = assets.getAsset(id, Model.class); String redMaterialName = blenderModel.custom_properties.get("v_color_material_red"); String greenMaterialName = blenderModel.custom_properties.get("v_color_material_green"); String blueMaterialName = blenderModel.custom_properties.get("v_color_material_blue"); TextureAttribute redTexAttr = (TextureAttribute) model.getMaterial(redMaterialName).get(TextureAttribute.Diffuse); TextureAttribute greenTexAttr = (TextureAttribute) model.getMaterial(greenMaterialName).get(TextureAttribute.Diffuse); TextureAttribute blueTexAttr = (TextureAttribute) model.getMaterial(blueMaterialName).get(TextureAttribute.Diffuse); VertexColorTextureBlend redAttribute = new VertexColorTextureBlend(VertexColorTextureBlend.Red, redTexAttr.textureDescription.texture); VertexColorTextureBlend greenAttribute = new VertexColorTextureBlend(VertexColorTextureBlend.Green, greenTexAttr.textureDescription.texture); VertexColorTextureBlend blueAttribute = new VertexColorTextureBlend(VertexColorTextureBlend.Blue, blueTexAttr.textureDescription.texture); for (Node node : model.nodes) { for (NodePart nodePart : node.parts) { nodePart.material.set(redAttribute, greenAttribute, blueAttribute); } } break; } } } }
/** * Translate each vertex along its normal by specified amount. * * @param model * @param amount */ public static void fatten(Model model, float amount) { Vector3 pos = new Vector3(); Vector3 nor = new Vector3(); for (Node node : model.nodes) { for (NodePart n : node.parts) { Mesh mesh = n.meshPart.mesh; FloatBuffer buf = mesh.getVerticesBuffer(); int lastFloat = mesh.getNumVertices() * mesh.getVertexSize() / 4; int vertexFloats = (mesh.getVertexSize() / 4); VertexAttribute posAttr = mesh.getVertexAttributes().findByUsage(VertexAttributes.Usage.Position); VertexAttribute norAttr = mesh.getVertexAttributes().findByUsage(VertexAttributes.Usage.Normal); if (posAttr == null || norAttr == null) { throw new IllegalArgumentException("Position/normal vertex attribute not found"); } int pOff = posAttr.offset / 4; int nOff = norAttr.offset / 4; for (int i = 0; i < lastFloat; i += vertexFloats) { pos.x = buf.get(pOff + i); pos.y = buf.get(pOff + i + 1); pos.z = buf.get(pOff + i + 2); nor.x = buf.get(nOff + i); nor.y = buf.get(nOff + i + 1); nor.z = buf.get(nOff + i + 2); nor.nor().scl(amount); buf.put(pOff + i, pos.x + nor.x); buf.put(pOff + i + 1, pos.y + nor.y); buf.put(pOff + i + 2, pos.z + nor.z); } } } }
/** * Creates the collision objects of this planet part. */ private void initPhysics() { for (int landscapeLayerIndex = 0; landscapeLayerIndex < planetConfig.layerConfigs.size(); landscapeLayerIndex++) { String partName = LANDSCAPE_NODE_NAME + landscapeLayerIndex; Node landscapeNode = model.getNode(partName); CollisionTypes landscapeType = CollisionTypes.byName(planetConfig.layerConfigs.get(landscapeLayerIndex).collisionType); if (areAllPartsValid(landscapeNode)) { btCollisionShape collisionShape = Bullet.obtainStaticNodeShape(landscapeNode, false); shapes.add(collisionShape); if (landscapeType != CollisionTypes.WATER) { float mass = 0; float friction = 1; PlanetConfig.LandscapeLayerConfig layerConfig = planetConfig.layerConfigs.get(landscapeLayerIndex); int userValue = CollisionTypes.byName(layerConfig.collisionType).mask; addRigidBody(collisionShape, mass, friction, userValue, new StandardMotionState(modelInstance.transform)); } else { btCollisionObject object = new btCollisionObject(); object.setCollisionShape(collisionShape); object.setWorldTransform(modelInstance.transform); object.setUserValue(CollisionTypes.WATER.mask); addCollisionObject(object); } } } }
/** * Returns true if all parts of the assigned node can be used to create collision shapes * @param node The node to check. * @return True if the node is valid. */ private boolean areAllPartsValid(Node node) { if (node == null) { return false; } for (NodePart nodePart : node.parts) { boolean usesTriangles = (nodePart.meshPart.primitiveType == GL20.GL_TRIANGLES); if ((nodePart.meshPart.size <= 0) || !usesTriangles) { return false; } } return true; }
/** Resets the references to {@link Material}s, {@link Mesh}es and {@link MeshPart}s within the model to the ones used within * it's nodes. This will make the model responsible for disposing all referenced meshes. */ public static void rebuildReferences (final Model model) { model.materials.clear(); model.meshes.clear(); model.meshParts.clear(); for (final Node node : model.nodes) rebuildReferences(model, node); }
private static void rebuildReferences (final Model model, final Node node) { for (final NodePart mpm : node.parts) { if (!model.materials.contains(mpm.material, true)) model.materials.add(mpm.material); if (!model.meshParts.contains(mpm.meshPart, true)) { model.meshParts.add(mpm.meshPart); if (!model.meshes.contains(mpm.meshPart.mesh, true)) model.meshes.add(mpm.meshPart.mesh); model.manageDisposable(mpm.meshPart.mesh); } } for (final Node child : node.getChildren()) rebuildReferences(model, child); }