⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 particlesystem.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jmex.effects.particles;

import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.logging.Logger;

import com.jme.math.FastMath;
import com.jme.math.Line;
import com.jme.math.Matrix3f;
import com.jme.math.Rectangle;
import com.jme.math.Ring;
import com.jme.math.TransformMatrix;
import com.jme.math.Triangle;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Controller;
import com.jme.scene.Geometry;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;

/**
 * ParticleGeometry is an abstract class representing a particle system. A
 * ParticleController must be attached for the effect to be complete.
 * 
 * @author Joshua Slack
 * @version $Id: ParticleGeometry.java,v 1.11 2007/09/21 15:45:32 nca Exp $
 */
public abstract class ParticleSystem extends Node {
    private static final Logger logger = Logger.getLogger(ParticleSystem.class
            .getName());

    protected static final long serialVersionUID = 2L;

    public enum EmitType {
        Point, Line, Rectangle, Ring, Geometry;
    }

    public enum ParticleType {
        Quad, Triangle, Point, Line, GeomMesh;
    }

    protected static final float DEFAULT_END_SIZE = 4f;
    protected static final float DEFAULT_START_SIZE = 20f;
    protected static final float DEFAULT_MAX_ANGLE = 0.7853982f;
    protected static final float DEFAULT_MAX_LIFE = 3000f;
    protected static final float DEFAULT_MIN_LIFE = 2000f;

    protected static final ColorRGBA DEFAULT_START_COLOR = new ColorRGBA(1.0f,
            0.0f, 0.0f, 1.0f);
    protected static final ColorRGBA DEFAULT_END_COLOR = new ColorRGBA(1.0f,
            1.0f, 0.0f, 0.0f);

    protected ParticleType particleType;
    protected EmitType emitType = EmitType.Point;
    protected Line psLine;
    protected Rectangle psRect;
    protected Geometry psGeom;
    protected Ring psRing;
    protected boolean cameraFacing = true;
    protected boolean velocityAligned = false;
    protected boolean particlesInWorldCoords = true;

    protected float startSize, endSize;
    protected ColorRGBA startColor;
    protected ColorRGBA endColor;
    protected ParticleAppearanceRamp ramp = new ParticleAppearanceRamp();
    protected TexAnimation texAnimation = new TexAnimation();
    protected float initialVelocity;
    protected float minimumLifeTime, maximumLifeTime;
    protected float minimumAngle, maximumAngle;
    protected float startSpin, endSpin;
    protected float startMass, endMass;
    protected int startTexIndex, texQuantity;
    protected Vector3f emissionDirection;
    protected TransformMatrix emitterTransform = new TransformMatrix();
    protected Vector3f worldEmit = new Vector3f();
    protected int numParticles;
    protected boolean rotateWithScene = false;
    protected Matrix3f rotMatrix;
    protected float particleOrientation;

    protected FloatBuffer geometryCoordinates;
    protected FloatBuffer appearanceColors;

    // vectors to prevent repeated object creation:
    protected Vector3f upXemit, absUpVector, abUpMinUp;
    protected Vector3f upVector;
    protected Vector3f leftVector;
    protected Vector3f invScale;

    protected Particle particles[];

    // protected Vector3f particleSpeed;
    protected int releaseRate; // particles per second
    protected Vector3f originOffset;
    protected Vector3f originCenter;
    protected static Vector2f workVect2 = new Vector2f();
    protected static Vector3f workVect3 = new Vector3f();

    protected Geometry particleGeom;
    protected ParticleController controller;

    public ParticleSystem() {
    }

    public ParticleSystem(String name, int numParticles) {
        this(name, numParticles, ParticleType.Quad);
    }

    public ParticleSystem(String name, int numParticles,
            ParticleType particleType) {
        super(name);
        this.numParticles = numParticles;
        this.particleType = particleType;
        emissionDirection = new Vector3f(0.0f, 1.0f, 0.0f);
        minimumLifeTime = DEFAULT_MIN_LIFE;
        maximumLifeTime = DEFAULT_MAX_LIFE;
        maximumAngle = DEFAULT_MAX_ANGLE;
        startSize = DEFAULT_START_SIZE;
        endSize = DEFAULT_END_SIZE;
        startColor = DEFAULT_START_COLOR.clone();
        endColor = DEFAULT_END_COLOR.clone();
        upVector = Vector3f.UNIT_Y.clone();
        leftVector = new Vector3f(-1, 0, 0);
        originCenter = new Vector3f();
        originOffset = new Vector3f();
        startSpin = 0;
        endSpin = 0;
        startMass = 1;
        endMass = 1;
        startTexIndex = 0;
        texQuantity = 1;
        releaseRate = numParticles;
        // init working vectors.. used to prevent additional object creation.
        upXemit = new Vector3f();
        absUpVector = new Vector3f();
        abUpMinUp = new Vector3f();
        initialVelocity = 1.0f;

        rotMatrix = new Matrix3f();
        initializeParticles(numParticles);
    }

    protected abstract void initializeParticles(int numParticles);

    public static int getVertsForParticleType(ParticleType type) {
        switch (type) {
            case Triangle:
            case GeomMesh:
                return 3;
            case Point:
                return 1;
            case Line:
                return 2;
            case Quad:
                return 4;
        }
        if (type == null)
            throw new NullPointerException("type is null");
        throw new IllegalArgumentException("Invalid ParticleType: " + type);
    }

    public void forceRespawn() {
        for (int i = particles.length; --i >= 0;) {
            particles[i].recreateParticle(0);
            particles[i].setStatus(Particle.Status.Alive);
            particles[i].updateAndCheck(1);
            particles[i].setStatus(Particle.Status.Available);
        }

        if (controller != null) {
            controller.setActive(true);
        }
    }

    /**
     * Setup the rotation matrix used to determine initial particle velocity
     * based on emission angle and emission direction. called automatically by
     * the set* methods for those parameters.
     */
    protected Vector3f oldEmit = new Vector3f(Float.NaN, Float.NaN, Float.NaN);
    protected float matData[][] = new float[3][3];

    public void updateRotationMatrix() {

        if (oldEmit.equals(worldEmit))
            return;

        float upDotEmit = upVector.dot(worldEmit);
        if (FastMath.abs(upDotEmit) > 1.0d - FastMath.DBL_EPSILON) {
            absUpVector.x = upVector.x <= 0.0f ? -upVector.x : upVector.x;
            absUpVector.y = upVector.y <= 0.0f ? -upVector.y : upVector.y;
            absUpVector.z = upVector.z <= 0.0f ? -upVector.z : upVector.z;
            if (absUpVector.x < absUpVector.y) {
                if (absUpVector.x < absUpVector.z) {
                    absUpVector.x = 1.0f;
                    absUpVector.y = absUpVector.z = 0.0f;
                } else {
                    absUpVector.z = 1.0f;
                    absUpVector.x = absUpVector.y = 0.0f;
                }
            } else if (absUpVector.y < absUpVector.z) {
                absUpVector.y = 1.0f;
                absUpVector.x = absUpVector.z = 0.0f;
            } else {
                absUpVector.z = 1.0f;
                absUpVector.x = absUpVector.y = 0.0f;
            }
            absUpVector.subtract(upVector, abUpMinUp);
            absUpVector.subtract(worldEmit, upXemit);
            float f4 = 2.0f / abUpMinUp.dot(abUpMinUp);
            float f6 = 2.0f / upXemit.dot(upXemit);
            float f8 = f4 * f6 * abUpMinUp.dot(upXemit);
            float af1[] = { abUpMinUp.x, abUpMinUp.y, abUpMinUp.z };
            float af2[] = { upXemit.x, upXemit.y, upXemit.z };
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    matData[i][j] = (-f4 * af1[i] * af1[j] - f6 * af2[i]
                            * af2[j])
                            + f8 * af2[i] * af1[j];

                }
                matData[i][i]++;
            }

        } else {
            upVector.cross(worldEmit, upXemit);
            float f2 = 1.0f / (1.0f + upDotEmit);
            float f5 = f2 * upXemit.x;
            float f7 = f2 * upXemit.z;
            float f9 = f5 * upXemit.y;
            float f10 = f5 * upXemit.z;
            float f11 = f7 * upXemit.y;
            matData[0][0] = upDotEmit + f5 * upXemit.x;
            matData[0][1] = f9 - upXemit.z;
            matData[0][2] = f10 + upXemit.y;
            matData[1][0] = f9 + upXemit.z;
            matData[1][1] = upDotEmit + f2 * upXemit.y * upXemit.y;
            matData[1][2] = f11 - upXemit.x;
            matData[2][0] = f10 - upXemit.y;
            matData[2][1] = f11 + upXemit.x;
            matData[2][2] = upDotEmit + f7 * upXemit.z;
        }
        rotMatrix.set(matData);
        oldEmit.set(worldEmit);
    }

    public abstract Geometry getParticleGeometry();

    public ParticleController getParticleController() {
        return controller;
    }

    public void addController(Controller c) {
        super.addController(c);
        if (c instanceof ParticleController) {
            this.controller = (ParticleController) c;
        }
    }

    public Vector3f getEmissionDirection() {
        return emissionDirection;
    }

    public void setEmissionDirection(Vector3f emissionDirection) {
        this.emissionDirection = emissionDirection;
        this.worldEmit.set(emissionDirection);
    }

    public float getEndSize() {
        return endSize;
    }

    public void setEndSize(float size) {
        endSize = size >= 0.0f ? size : 0.0f;
    }

    public float getStartSize() {
        return startSize;
    }

    public void setStartSize(float size) {
        startSize = size >= 0.0f ? size : 0.0f;
    }

    /**
     * Set the start color for particles. This is the base color of the quad.
     * 
     * @param color
     *            The start color.
     */
    public void setStartColor(ColorRGBA color) {
        this.startColor = color;
    }

    /**
     * <code>getStartColor</code> returns the starting color.
     * 
     * @return ColorRGBA The begining color.
     */
    public ColorRGBA getStartColor() {
        return startColor;
    }

    /**
     * Set the end color for particles. The base color of the quad will linearly
     * approach this color from the start color over the lifetime of the
     * particle.
     * 
     * @param color
     *            ColorRGBA The ending color.
     */
    public void setEndColor(ColorRGBA color) {
        this.endColor = color;
    }

    /**
     * getEndColor returns the ending color.
     * 
     * @return The ending color
     */
    public ColorRGBA getEndColor() {
        return endColor;
    }

    /**
     * Set the start and end spinSpeed of particles managed by this manager.
     * Setting it to 0 means no spin.
     * 
     * @param speed
     *            float
     */
    public void setParticleSpinSpeed(float speed) {
        startSpin = speed;
        endSpin = speed;
    }

    public Vector3f getInvScale() {
        return invScale;
    }

    public void setInvScale(Vector3f invScale) {
        this.invScale = invScale;
    }

    public void updateInvScale() {
        invScale.set(worldScale);
        invScale.set(1f / invScale.x, 1f / invScale.y, 1f / invScale.z);
    }

    /**
     * Add an external influence to the particle controller for this mesh.
     * 
     * @param influence
     *            ParticleInfluence
     */
    public void addInfluence(ParticleInfluence influence) {
        controller.addInfluence(influence);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -