Package com.ardor3d.extension.effect.particle

Source Code of com.ardor3d.extension.effect.particle.SwarmInfluence

/**
* Copyright (c) 2008-2012 Ardor Labs, Inc.
*
* This file is part of Ardor3D.
*
* Ardor3D is free software: you can redistribute it and/or modify it
* under the terms of its license which may be found in the accompanying
* LICENSE file or at <http://www.ardor3d.com/LICENSE>.
*/

package com.ardor3d.extension.effect.particle;

import java.io.IOException;

import com.ardor3d.math.MathUtils;
import com.ardor3d.math.Matrix3;
import com.ardor3d.math.Vector3;
import com.ardor3d.math.type.ReadOnlyVector3;
import com.ardor3d.util.export.InputCapsule;
import com.ardor3d.util.export.OutputCapsule;

/**
* Simple swarming influence for use with particles.
*/
public class SwarmInfluence extends ParticleInfluence {

    private double _swarmRangeSQ;
    private final Vector3 _swarmOffset = new Vector3();
    private final Vector3 _swarmPoint = new Vector3();

    public static final double DEFAULT_SWARM_RANGE_SQ = 0.01;
    public static final double DEFAULT_DEVIANCE = MathUtils.DEG_TO_RAD * 15;
    public static final double DEFAULT_TURN_SPEED = MathUtils.DEG_TO_RAD * 180;
    public static final double DEFAULT_SPEED_BUMP = .1;
    public static final double DEFAULT_MAX_SPEED = .2;

    private double _deviance = DEFAULT_DEVIANCE;
    private double _turnSpeed = DEFAULT_TURN_SPEED;
    private double _speedBump = DEFAULT_SPEED_BUMP;
    private double _maxSpeed = DEFAULT_MAX_SPEED;

    private transient double _maxSpeedSQ = DEFAULT_MAX_SPEED * DEFAULT_MAX_SPEED;

    public SwarmInfluence() {
        _swarmRangeSQ = DEFAULT_SWARM_RANGE_SQ;
    }

    public SwarmInfluence(final ReadOnlyVector3 offset, final double swarmRange) {
        super();
        _swarmRangeSQ = swarmRange * swarmRange;
        _swarmOffset.set(offset);
    }

    @Override
    public void prepare(final ParticleSystem system) {
        super.prepare(system);
        _swarmPoint.set(system.getOriginCenter()).addLocal(_swarmOffset);
    }

    @Override
    public void apply(final double dt, final Particle particle, final int index) {
        final Vector3 pVelocity = particle.getVelocity();
        // determine if the particle is in the inner or outer zone
        final double pDist = particle.getPosition().distanceSquared(_swarmPoint);
        final Vector3 workVect = Vector3.fetchTempInstance();
        final Vector3 workVect2 = Vector3.fetchTempInstance();
        final Matrix3 workMat = Matrix3.fetchTempInstance();
        workVect.set(_swarmPoint).subtractLocal(particle.getPosition()).normalizeLocal();
        workVect2.set(pVelocity).normalizeLocal();
        if (pDist > _swarmRangeSQ) {
            // IN THE OUTER ZONE...
            // Determine if the angle between particle velocity and a vector to
            // the swarmPoint is less than the accepted deviance
            final double angle = workVect.smallestAngleBetween(workVect2);
            if (angle < _deviance) {
                // if it is, increase the speed speedBump over time
                if (pVelocity.lengthSquared() < _maxSpeedSQ) {
                    final double change = _speedBump * dt;
                    workVect2.multiplyLocal(change); // where workVector2 = pVelocity.normalizeLocal()
                    pVelocity.addLocal(workVect2);
                }
            } else {
                final Vector3 axis = workVect2.crossLocal(workVect);
                // if it is not, shift the velocity to bring it back in line
                if ((Double.doubleToLongBits(pVelocity.lengthSquared()) & 0x1d) != 0) {
                    workMat.fromAngleAxis(_turnSpeed * dt, axis);
                } else {
                    workMat.fromAngleAxis(-_turnSpeed * dt, axis);
                }
                workMat.applyPost(pVelocity, pVelocity);
            }
        } else {
            final Vector3 axis = workVect2.crossLocal(workVect);
            // IN THE INNER ZONE...
            // Alter the heading based on how fast we are going
            if ((index & 0x1f) != 0) {
                workMat.fromAngleAxis(_turnSpeed * dt, axis);
            } else {
                workMat.fromAngleAxis(-_turnSpeed * dt, axis);
            }
            workMat.applyPost(pVelocity, pVelocity);
        }
        Vector3.releaseTempInstance(workVect);
        Vector3.releaseTempInstance(workVect2);
        Matrix3.releaseTempInstance(workMat);
    }

    public double getSwarmRange() {
        return Math.sqrt(_swarmRangeSQ);
    }

    public void setSwarmRange(final double swarmRange) {
        _swarmRangeSQ = swarmRange * swarmRange;
    }

    public ReadOnlyVector3 getSwarmOffset() {
        return _swarmOffset;
    }

    public void setSwarmOffset(final ReadOnlyVector3 offset) {
        _swarmOffset.set(offset);
    }

    public double getDeviance() {
        return _deviance;
    }

    public void setDeviance(final double deviance) {
        _deviance = deviance;
    }

    public double getSpeedBump() {
        return _speedBump;
    }

    public void setSpeedBump(final double speedVariance) {
        _speedBump = speedVariance;
    }

    public double getTurnSpeed() {
        return _turnSpeed;
    }

    public void setTurnSpeed(final double turnSpeed) {
        _turnSpeed = turnSpeed;
    }

    public double getMaxSpeed() {
        return _maxSpeed;
    }

    public void setMaxSpeed(final double maxSpeed) {
        _maxSpeed = maxSpeed;
        _maxSpeedSQ = maxSpeed * maxSpeed;
    }

    @Override
    public void write(final OutputCapsule capsule) throws IOException {
        super.write(capsule);
        final OutputCapsule cap = capsule;
        cap.write(_swarmRangeSQ, "swarmRangeSQ", DEFAULT_SWARM_RANGE_SQ);
        cap.write(_deviance, "deviance", DEFAULT_DEVIANCE);
        cap.write(_turnSpeed, "turnSpeed", DEFAULT_TURN_SPEED);
        cap.write(_speedBump, "speedBump", DEFAULT_SPEED_BUMP);
        cap.write(_maxSpeed, "maxSpeed", DEFAULT_MAX_SPEED);
        cap.write(_swarmOffset, "swarmOffset", new Vector3());
    }

    @Override
    public void read(final InputCapsule capsule) throws IOException {
        super.read(capsule);
        final InputCapsule cap = capsule;
        _swarmRangeSQ = cap.readDouble("swarmRangeSQ", DEFAULT_SWARM_RANGE_SQ);
        _deviance = cap.readDouble("deviance", DEFAULT_DEVIANCE);
        _turnSpeed = cap.readDouble("turnSpeed", DEFAULT_TURN_SPEED);
        _speedBump = cap.readDouble("speedBump", DEFAULT_SPEED_BUMP);
        _maxSpeed = cap.readDouble("maxSpeed", DEFAULT_MAX_SPEED);
        _swarmOffset.set((Vector3) cap.readSavable("swarmOffset", new Vector3()));
    }

    @Override
    public Class<? extends SwarmInfluence> getClassTag() {
        return getClass();
    }
}
TOP

Related Classes of com.ardor3d.extension.effect.particle.SwarmInfluence

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.