Search in sources :

Example 41 with Transform

use of com.jme3.math.Transform in project jmonkeyengine by jMonkeyEngine.

the class ConstraintHelper method getTransform.

/**
     * The method retreives the transform from a feature in a given space.
     * 
     * @param oma
     *            the OMA of the feature (spatial or armature node)
     * @param subtargetName
     *            the feature's subtarget (bone in a case of armature's node)
     * @param space
     *            the space the transform is evaluated to
     * @return thensform of a feature in a given space
     */
public Transform getTransform(Long oma, String subtargetName, Space space) {
    Spatial feature = (Spatial) blenderContext.getLoadedFeature(oma, LoadedDataType.FEATURE);
    boolean isArmature = blenderContext.getMarkerValue(ObjectHelper.ARMATURE_NODE_MARKER, feature) != null;
    if (isArmature) {
        blenderContext.getSkeleton(oma).updateWorldVectors();
        BoneContext targetBoneContext = blenderContext.getBoneByName(oma, subtargetName);
        Bone bone = targetBoneContext.getBone();
        if (bone.getParent() == null && (space == Space.CONSTRAINT_SPACE_LOCAL || space == Space.CONSTRAINT_SPACE_PARLOCAL)) {
            space = Space.CONSTRAINT_SPACE_POSE;
        }
        // use readable names of the matrices so that the code is more clear
        TempVars tempVars = TempVars.get();
        Transform result;
        switch(space) {
            case CONSTRAINT_SPACE_WORLD:
                Spatial model = (Spatial) blenderContext.getLoadedFeature(targetBoneContext.getSkeletonOwnerOma(), LoadedDataType.FEATURE);
                Matrix4f boneModelMatrix = this.toMatrix(bone.getModelSpacePosition(), bone.getModelSpaceRotation(), bone.getModelSpaceScale(), tempVars.tempMat4);
                Matrix4f modelWorldMatrix = this.toMatrix(model.getWorldTransform(), tempVars.tempMat42);
                Matrix4f boneMatrixInWorldSpace = modelWorldMatrix.multLocal(boneModelMatrix);
                result = new Transform(boneMatrixInWorldSpace.toTranslationVector(), boneMatrixInWorldSpace.toRotationQuat(), boneMatrixInWorldSpace.toScaleVector());
                break;
            case CONSTRAINT_SPACE_LOCAL:
                assert bone.getParent() != null : "CONSTRAINT_SPACE_LOCAL should be evaluated as CONSTRAINT_SPACE_POSE if the bone has no parent!";
                result = new Transform(bone.getLocalPosition(), bone.getLocalRotation(), bone.getLocalScale());
                break;
            case CONSTRAINT_SPACE_POSE:
                {
                    Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
                    Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
                    Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
                    result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
                    break;
                }
            case CONSTRAINT_SPACE_PARLOCAL:
                {
                    Matrix4f boneWorldMatrix = this.toMatrix(this.getTransform(oma, subtargetName, Space.CONSTRAINT_SPACE_WORLD), tempVars.tempMat4);
                    Matrix4f armatureInvertedWorldMatrix = this.toMatrix(feature.getWorldTransform(), tempVars.tempMat42).invertLocal();
                    Matrix4f bonePoseMatrix = armatureInvertedWorldMatrix.multLocal(boneWorldMatrix);
                    result = new Transform(bonePoseMatrix.toTranslationVector(), bonePoseMatrix.toRotationQuat(), bonePoseMatrix.toScaleVector());
                    Bone parent = bone.getParent();
                    if (parent != null) {
                        BoneContext parentContext = blenderContext.getBoneContext(parent);
                        Vector3f head = parent.getModelSpacePosition();
                        Vector3f tail = head.add(bone.getModelSpaceRotation().mult(Vector3f.UNIT_Y.mult(parentContext.getLength())));
                        result.getTranslation().subtractLocal(tail);
                    }
                    break;
                }
            default:
                throw new IllegalStateException("Unknown space type: " + space);
        }
        tempVars.release();
        return result;
    } else {
        switch(space) {
            case CONSTRAINT_SPACE_LOCAL:
                return feature.getLocalTransform();
            case CONSTRAINT_SPACE_WORLD:
                return feature.getWorldTransform();
            case CONSTRAINT_SPACE_PARLOCAL:
            case CONSTRAINT_SPACE_POSE:
                throw new IllegalStateException("Nodes can have only Local and World spaces applied!");
            default:
                throw new IllegalStateException("Unknown space type: " + space);
        }
    }
}
Also used : Matrix4f(com.jme3.math.Matrix4f) Spatial(com.jme3.scene.Spatial) BoneContext(com.jme3.scene.plugins.blender.animations.BoneContext) Vector3f(com.jme3.math.Vector3f) Bone(com.jme3.animation.Bone) TempVars(com.jme3.util.TempVars) Transform(com.jme3.math.Transform)

Example 42 with Transform

use of com.jme3.math.Transform in project jmonkeyengine by jMonkeyEngine.

the class SimulationNode method simulateSkeleton.

/**
     * Simulates the bone node.
     */
private void simulateSkeleton() {
    LOGGER.fine("Simulating skeleton.");
    Set<Long> alteredOmas = new HashSet<Long>();
    if (animations != null) {
        TempVars vars = TempVars.get();
        AnimChannel animChannel = animControl.createChannel();
        for (Animation animation : animations) {
            float[] animationTimeBoundaries = this.computeAnimationTimeBoundaries(animation);
            int maxFrame = (int) animationTimeBoundaries[0];
            float maxTime = animationTimeBoundaries[1];
            Map<Integer, VirtualTrack> tracks = new HashMap<Integer, VirtualTrack>();
            for (int frame = 0; frame < maxFrame; ++frame) {
                // this MUST be done here, otherwise setting next frame of animation will
                // lead to possible errors
                this.reset();
                // first set proper time for all bones in all the tracks ...
                for (Track track : animation.getTracks()) {
                    float time = ((BoneTrack) track).getTimes()[frame];
                    track.setTime(time, 1, animControl, animChannel, vars);
                    skeleton.updateWorldVectors();
                }
                // ... and then apply constraints from the root bone to the last child ...
                Set<Long> applied = new HashSet<Long>();
                for (Bone rootBone : skeleton.getRoots()) {
                    // ignore the 0-indexed bone
                    if (skeleton.getBoneIndex(rootBone) > 0) {
                        this.applyConstraints(rootBone, alteredOmas, applied, frame, new Stack<Bone>());
                    }
                }
                // ... add virtual tracks if neccessary, for bones that were altered but had no tracks before ...
                for (Long boneOMA : alteredOmas) {
                    BoneContext boneContext = blenderContext.getBoneContext(boneOMA);
                    int boneIndex = skeleton.getBoneIndex(boneContext.getBone());
                    if (!tracks.containsKey(boneIndex)) {
                        tracks.put(boneIndex, new VirtualTrack(boneContext.getBone().getName(), maxFrame, maxTime));
                    }
                }
                alteredOmas.clear();
                // ... and fill in another frame in the result track
                for (Entry<Integer, VirtualTrack> trackEntry : tracks.entrySet()) {
                    Bone bone = skeleton.getBone(trackEntry.getKey());
                    Transform startTransform = boneStartTransforms.get(bone);
                    // track contains differences between the frame position and bind positions of bones/spatials
                    Vector3f bonePositionDifference = bone.getLocalPosition().subtract(startTransform.getTranslation());
                    Quaternion boneRotationDifference = startTransform.getRotation().inverse().mult(bone.getLocalRotation()).normalizeLocal();
                    Vector3f boneScaleDifference = bone.getLocalScale().divide(startTransform.getScale());
                    trackEntry.getValue().setTransform(frame, new Transform(bonePositionDifference, boneRotationDifference, boneScaleDifference));
                }
            }
            for (Entry<Integer, VirtualTrack> trackEntry : tracks.entrySet()) {
                Track newTrack = trackEntry.getValue().getAsBoneTrack(trackEntry.getKey());
                if (newTrack != null) {
                    boolean trackReplaced = false;
                    for (Track track : animation.getTracks()) {
                        if (((BoneTrack) track).getTargetBoneIndex() == trackEntry.getKey().intValue()) {
                            animation.removeTrack(track);
                            animation.addTrack(newTrack);
                            trackReplaced = true;
                            break;
                        }
                    }
                    if (!trackReplaced) {
                        animation.addTrack(newTrack);
                    }
                }
            }
        }
        vars.release();
        animControl.clearChannels();
        this.reset();
    }
}
Also used : HashMap(java.util.HashMap) Quaternion(com.jme3.math.Quaternion) AnimChannel(com.jme3.animation.AnimChannel) TempVars(com.jme3.util.TempVars) BoneContext(com.jme3.scene.plugins.blender.animations.BoneContext) Vector3f(com.jme3.math.Vector3f) Animation(com.jme3.animation.Animation) Bone(com.jme3.animation.Bone) Transform(com.jme3.math.Transform) SpatialTrack(com.jme3.animation.SpatialTrack) BoneTrack(com.jme3.animation.BoneTrack) Track(com.jme3.animation.Track) HashSet(java.util.HashSet)

Example 43 with Transform

use of com.jme3.math.Transform in project jmonkeyengine by jMonkeyEngine.

the class ConstraintDefinition method applyOwnerTransform.

/**
     * The method applies the given transformation to the owner.
     * @param ownerTransform
     *            the transformation to apply to the owner
     * @param ownerSpace
     *            the space that defines which owner's transformation (ie. global, local, etc. will be set)
     */
protected void applyOwnerTransform(Transform ownerTransform, Space ownerSpace) {
    if (this.getOwner() instanceof Bone) {
        BoneContext boneContext = blenderContext.getBoneContext(ownerOMA);
        constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), ownerSpace, ownerTransform);
    } else {
        constraintHelper.applyTransform(ownerOMA, null, ownerSpace, ownerTransform);
    }
}
Also used : BoneContext(com.jme3.scene.plugins.blender.animations.BoneContext) Bone(com.jme3.animation.Bone)

Example 44 with Transform

use of com.jme3.math.Transform in project jmonkeyengine by jMonkeyEngine.

the class ConstraintDefinitionDistLimit method bake.

@Override
public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
    if (this.getOwner() instanceof Bone && ((Bone) this.getOwner()).getParent() != null && blenderContext.getBoneContext(ownerOMA).is(BoneContext.CONNECTED_TO_PARENT)) {
        // distance limit does not work on bones who are connected to their parent
        return;
    }
    if (influence == 0 || targetTransform == null) {
        // no need to do anything
        return;
    }
    Transform ownerTransform = this.getOwnerTransform(ownerSpace);
    Vector3f v = ownerTransform.getTranslation().subtract(targetTransform.getTranslation());
    float currentDistance = v.length();
    switch(mode) {
        case LIMITDIST_INSIDE:
            if (currentDistance >= dist) {
                v.normalizeLocal();
                v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
                ownerTransform.getTranslation().set(v.addLocal(targetTransform.getTranslation()));
            }
            break;
        case LIMITDIST_ONSURFACE:
            if (currentDistance > dist) {
                v.normalizeLocal();
                v.multLocal(dist + (currentDistance - dist) * (1.0f - influence));
                ownerTransform.getTranslation().set(v.addLocal(targetTransform.getTranslation()));
            } else if (currentDistance < dist) {
                v.normalizeLocal().multLocal(dist * influence);
                ownerTransform.getTranslation().set(targetTransform.getTranslation().add(v));
            }
            break;
        case LIMITDIST_OUTSIDE:
            if (currentDistance <= dist) {
                v = targetTransform.getTranslation().subtract(ownerTransform.getTranslation()).normalizeLocal().multLocal(dist * influence);
                ownerTransform.getTranslation().set(targetTransform.getTranslation().add(v));
            }
            break;
        default:
            throw new IllegalStateException("Unknown distance limit constraint mode: " + mode);
    }
    this.applyOwnerTransform(ownerTransform, ownerSpace);
}
Also used : Vector3f(com.jme3.math.Vector3f) Bone(com.jme3.animation.Bone) Transform(com.jme3.math.Transform)

Example 45 with Transform

use of com.jme3.math.Transform in project jmonkeyengine by jMonkeyEngine.

the class ConstraintDefinitionIK method bake.

@Override
public void bake(Space ownerSpace, Space targetSpace, Transform targetTransform, float influence) {
    if (influence == 0 || !trackToBeChanged || targetTransform == null || bonesCount == 0) {
        // no need to do anything
        return;
    }
    if (bones == null) {
        bones = new BonesChain((Bone) this.getOwner(), useTail, bonesAffected, alteredOmas, blenderContext);
    }
    if (bones.size() == 0) {
        bonesCount = 0;
        // no need to do anything
        return;
    }
    double distanceFromTarget = Double.MAX_VALUE;
    target.set(targetTransform.getTranslation().x, targetTransform.getTranslation().y, targetTransform.getTranslation().z);
    if (bonesCount < 0) {
        bonesCount = bones.size();
        rotationVectors = new Vector3d[bonesCount];
        for (int i = 0; i < bonesCount; ++i) {
            rotationVectors[i] = new Vector3d();
        }
        J = new Matrix(3, bonesCount);
    }
    BoneContext topBone = bones.get(0);
    for (int i = 0; i < iterations; ++i) {
        DTransform topBoneTransform = bones.getWorldTransform(topBone);
        // effector
        Vector3d e = topBoneTransform.getTranslation().add(topBoneTransform.getRotation().mult(Vector3d.UNIT_Y).multLocal(topBone.getLength()));
        distanceFromTarget = e.distance(target);
        if (distanceFromTarget <= MIN_DISTANCE) {
            break;
        }
        deltaP.setColumn(0, 0, target.x - e.x, target.y - e.y, target.z - e.z);
        int column = 0;
        for (BoneContext boneContext : bones) {
            DTransform boneWorldTransform = bones.getWorldTransform(boneContext);
            // current join position
            Vector3d j = boneWorldTransform.getTranslation();
            Vector3d vectorFromJointToEffector = e.subtract(j);
            vectorFromJointToEffector.cross(target.subtract(j), rotationVectors[column]).normalizeLocal();
            rotationVectors[column].cross(vectorFromJointToEffector, col);
            J.setColumn(col, column++);
        }
        Matrix J_1 = J.pseudoinverse();
        SimpleMatrix deltaThetas = J_1.mult(deltaP);
        if (deltaThetas.elementMaxAbs() < MIN_ANGLE_CHANGE) {
            break;
        }
        for (int j = 0; j < deltaThetas.numRows(); ++j) {
            double angle = deltaThetas.get(j, 0);
            Vector3d rotationVector = rotationVectors[j];
            tempDQuaternion.fromAngleAxis(angle, rotationVector);
            BoneContext boneContext = bones.get(j);
            Bone bone = boneContext.getBone();
            if (bone.equals(this.getOwner())) {
                if (boneContext.isLockX()) {
                    tempDQuaternion.set(0, tempDQuaternion.getY(), tempDQuaternion.getZ(), tempDQuaternion.getW());
                }
                if (boneContext.isLockY()) {
                    tempDQuaternion.set(tempDQuaternion.getX(), 0, tempDQuaternion.getZ(), tempDQuaternion.getW());
                }
                if (boneContext.isLockZ()) {
                    tempDQuaternion.set(tempDQuaternion.getX(), tempDQuaternion.getY(), 0, tempDQuaternion.getW());
                }
            }
            DTransform boneTransform = bones.getWorldTransform(boneContext);
            boneTransform.getRotation().set(tempDQuaternion.mult(boneTransform.getRotation()));
            bones.setWorldTransform(boneContext, boneTransform);
        }
    }
    // applying the results
    for (int i = bonesCount - 1; i >= 0; --i) {
        BoneContext boneContext = bones.get(i);
        DTransform transform = bones.getWorldTransform(boneContext);
        constraintHelper.applyTransform(boneContext.getArmatureObjectOMA(), boneContext.getBone().getName(), Space.CONSTRAINT_SPACE_WORLD, transform.toTransform());
    }
    // need to reload them again
    bones = null;
}
Also used : SimpleMatrix(org.ejml.simple.SimpleMatrix) Matrix(com.jme3.scene.plugins.blender.math.Matrix) SimpleMatrix(org.ejml.simple.SimpleMatrix) Vector3d(com.jme3.scene.plugins.blender.math.Vector3d) BoneContext(com.jme3.scene.plugins.blender.animations.BoneContext) DTransform(com.jme3.scene.plugins.blender.math.DTransform) Bone(com.jme3.animation.Bone)

Aggregations

Vector3f (com.jme3.math.Vector3f)29 Transform (com.jme3.math.Transform)26 TempVars (com.jme3.util.TempVars)24 Quaternion (com.jme3.math.Quaternion)11 Matrix4f (com.jme3.math.Matrix4f)10 Bone (com.jme3.animation.Bone)9 BoundingBox (com.jme3.bounding.BoundingBox)6 BoneContext (com.jme3.scene.plugins.blender.animations.BoneContext)5 PointLight (com.jme3.light.PointLight)4 Spatial (com.jme3.scene.Spatial)4 FloatBuffer (java.nio.FloatBuffer)4 Transform (com.bulletphysics.linearmath.Transform)3 ChildCollisionShape (com.jme3.bullet.collision.shapes.infos.ChildCollisionShape)3 DirectionalLight (com.jme3.light.DirectionalLight)3 Light (com.jme3.light.Light)3 SpotLight (com.jme3.light.SpotLight)3 CompoundShape (com.bulletphysics.collision.shapes.CompoundShape)2 BoneTrack (com.jme3.animation.BoneTrack)2 SpatialTrack (com.jme3.animation.SpatialTrack)2 BoundingVolume (com.jme3.bounding.BoundingVolume)2