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

📄 particlecontroller.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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.util.ArrayList;

import com.jme.math.FastMath;
import com.jme.renderer.Camera;
import com.jme.renderer.Camera.FrustumIntersect;
import com.jme.scene.Controller;
import com.jme.scene.Spatial;
import com.jme.system.DisplaySystem;
import com.jme.util.export.InputCapsule;
import com.jme.util.export.JMEExporter;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.OutputCapsule;

/**
 * <code>ParticleController</code> controls and maintains the parameters of a
 * ParticleGeometry particle system over time.
 * 
 * @author Joshua Slack
 * @version $Id: ParticleController.java,v 1.14 2007/04/03 14:30:20 nca Exp $
 */
public class ParticleController extends Controller {

    private static final long serialVersionUID = 1L;

    private ParticleSystem particles;
    private int particlesToCreate = 0;
    private float releaseVariance;
    private float currentTime;
    private float prevTime;
    private float releaseParticles;
    private float timePassed;
    private float precision;
    private boolean controlFlow;
    private boolean updateOnlyInView;
    private Camera viewCamera;

    private int iterations;
    private ArrayList<ParticleInfluence> influences;
    protected ArrayList<ParticleControllerListener> listeners;

    public ParticleController() {}
    
    /**
     * ParticleManager constructor
     * 
     * @param system
     *            Target ParticleGeometry to act upon.
     */
    public ParticleController(ParticleSystem system) {
        this.particles = system;

        setMinTime(0);
        setMaxTime(Float.MAX_VALUE);
        setRepeatType(Controller.RT_WRAP);
        setSpeed(1.0f);

        releaseVariance = 0;
        controlFlow = false;
        updateOnlyInView = false;
        precision = .01f; // 10ms

        system.updateRotationMatrix();
        warmUp(60);
    }

    /**
     * Update the particles managed by this manager. If any particles are "dead"
     * recreate them at the origin position (which may be a point, line or
     * rectangle.) See com.jme.scene.Controller.update(float)
     * 
     * @param secondsPassed
     *            float
     */
    public void update(float secondsPassed) {
        
        // If instructed, check to see if our last frustum check passed
        if (isUpdateOnlyInView()) {
            Camera cam = viewCamera != null ? viewCamera : DisplaySystem
                    .getDisplaySystem().getRenderer().getCamera();
            int state = cam.getPlaneState();
            boolean out = cam.contains(particles.getWorldBound()).equals(FrustumIntersect.Outside);
            cam.setPlaneState(state);
            if (out) {
                return;
            }
        }

        // Add time and unless we have more than precision time passed
        // since last real update, do nothing
        currentTime += secondsPassed * getSpeed();
        
        // Check precision passes
        timePassed = currentTime - prevTime;
        if (timePassed < precision * getSpeed()) {
            return;
        }

        // We are actually going to do a real update,
        // so this is our new previous time
        prevTime = currentTime;

        // Update the current rotation matrix if needed.
        particles.updateRotationMatrix();

        // If we are in the time window where this controller is active
        // (defaults to 0 to Float.MAX_VALUE for ParticleController)
        if (currentTime >= getMinTime() && currentTime <= getMaxTime()) {

            // If we are controlling the flow (ie the rate of particle spawning.)
            if (controlFlow) {
                // Release a number of particles based on release rate,
                // timePassed (already scaled for speed) and variance. This
                // is added to any current value Note this is a float value,
                // so we will keep adding up partial particles
                
                releaseParticles += (particles.getReleaseRate() *
                    timePassed * (1.0f + releaseVariance *
                        (FastMath.nextRandomFloat() - 0.5f)));

                // Try to create all "whole" particles we have added up
                particlesToCreate = (int) releaseParticles;
                
                // If we have any whole particles, then subtract them from
                // releaseParticles
                if (particlesToCreate > 0)
                    releaseParticles -= particlesToCreate;
                
                // Make sure particlesToCreate is not negative
                else
                    particlesToCreate = 0;
            }

            particles.updateInvScale();

            // If we have any influences, prepare them all
            if (influences != null) {
                for (ParticleInfluence influence : influences) {
                    influence.prepare(particles);
                }
            }
            
            // Track particle index
            int i = 0;
            
            // Track whether the whole set of particles is "dead" - if any
            // particles are still alive, this will be set to false
            boolean dead = true;
            
            // opposite of above boolean, but tracked seperately
            boolean anyAlive = false;
            
            // i is index through all particles
            while (i < particles.getNumParticles()) {
                // Current particle
                Particle p = particles.getParticle(i);
                
                // If we have influences and particle is alive
                if (influences != null && p.getStatus() == Particle.Status.Alive) {
                    // Apply each enabled influence to the current particle
                    for (int x = 0; x < influences.size(); x++) {
                        ParticleInfluence inf = influences.get(x);
                        if (inf.isEnabled())
                            inf.apply(timePassed, p, i);
                    }
                }
                    

                // Update and check the particle.
                // If this returns true, indicating particle is ready to be
                // reused, we may reuse it. Do so if we are not using
                // control flow, OR we intend to create particles based on
                // control flow count calculated above
                boolean reuse = p.updateAndCheck(timePassed);
                if (reuse && (!controlFlow || particlesToCreate > 0)) {
                    
                    // Don't recreate the particle if it is dead, and we are clamped
                    if (p.getStatus() == Particle.Status.Dead
                            && getRepeatType() == RT_CLAMP) {
                        ;

                    // We plan to reuse the particle
                    } else {
                        // Not all particles are dead (this one will be reused)
                        dead = false;
                        
                        // If we are doing flow control, decrement
                        // particlesToCreate, since we are about to create
                        // one
                        if (controlFlow) {
                            particlesToCreate--;
                        }

                        // Recreate the particle
                        p.recreateParticle(particles.getRandomLifeSpan());
                        p.setStatus(Particle.Status.Alive);
                        particles.initParticleLocation(i);
                        particles.resetParticleVelocity(i);
                        p.updateVerts(null);
                    }

                } else if (!reuse || (controlFlow && particles.getReleaseRate() > 0)) {
                    // The particle wasn't dead, or we expect more particles
                    // later, so we're not dead!
                    dead = false;
                }

                // Check for living particles so we know when to update our boundings.
                if (p.getStatus() == Particle.Status.Alive) {
                    anyAlive = true;
                }
                
                // Next particle
                i++;
            }

            // If we are dead, deactivate and tell our listeners
            if (dead) {
                setActive(false);
                if (listeners != null && listeners.size() > 0) {
                    for (ParticleControllerListener listener : listeners) {
                        listener.onDead(particles);
                    }
                }
            }

            // If we have a bound and any live particles, update it
            if (particles.getParticleGeometry().getModelBound() != null && anyAlive) {
                particles.updateModelBound();
                particles.updateWorldBoundManually();
            }
        }

⌨️ 快捷键说明

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