Package com.badlogic.gdx.graphics.g3d.particles.influencers

Source Code of com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier$BrownianAcceleration

package com.badlogic.gdx.graphics.g3d.particles.influencers;

import com.badlogic.gdx.graphics.g3d.particles.ParallelArray.FloatChannel;
import com.badlogic.gdx.graphics.g3d.particles.ParticleChannels;
import com.badlogic.gdx.graphics.g3d.particles.ParticleControllerComponent;
import com.badlogic.gdx.graphics.g3d.particles.values.ScaledNumericValue;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Quaternion;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonValue;

/** It's the base class for any kind of influencer which operates on angular velocity and acceleration of the particles.
* All the classes that will inherit this base class can and should be used
* only as sub-influencer of an instance of {@link DynamicsInfluencer} .
@author Inferno */
public abstract class DynamicsModifier extends Influencer{
  protected static final Vector3   TMP_V1 = new Vector3(),
                         TMP_V2 = new Vector3(),
                         TMP_V3 = new Vector3();
  protected static final Quaternion TMP_Q = new Quaternion();
 
  public static class FaceDirection extends DynamicsModifier {
    FloatChannel rotationChannel, accellerationChannel;
   
    public FaceDirection(){}
   
    public FaceDirection (FaceDirection rotation) {
      super(rotation);
    }
    @Override
    public void allocateChannels() {
      rotationChannel = controller.particles.addChannel(ParticleChannels.Rotation3D);
      accellerationChannel = controller.particles.addChannel(ParticleChannels.Acceleration);
    }
   
    @Override
    public void update () {
      for(int   i=0, accelOffset = 0, c = i +controller.particles.size *rotationChannel.strideSize;
        i < c;
        i +=rotationChannel.strideSize, accelOffset += accellerationChannel.strideSize){
       
        Vector3   axisZ = TMP_V1.setaccellerationChannel.data[accelOffset +ParticleChannels.XOffset],
                                        accellerationChannel.data[accelOffset +ParticleChannels.YOffset],
                                        accellerationChannel.data[accelOffset +ParticleChannels.ZOffset]).nor(),
          axisY = TMP_V2.set(TMP_V1).crs(Vector3.Y).nor().crs(TMP_V1).nor(),
          axisX = TMP_V3.set(axisY).crs(axisZ).nor();
        TMP_Q.setFromAxes(false,   axisX.x,  axisY.x, axisZ.x,
                              axisX.y,  axisY.y, axisZ.y,
                              axisX.z,  axisY.z, axisZ.z);
        rotationChannel.data[i +ParticleChannels.XOffset] = TMP_Q.x;
        rotationChannel.data[i +ParticleChannels.YOffset] = TMP_Q.y;
        rotationChannel.data[i +ParticleChannels.ZOffset] = TMP_Q.z;
        rotationChannel.data[i +ParticleChannels.WOffset] = TMP_Q.w; 
      }
    }

    @Override
    public ParticleControllerComponent copy () {
      return new FaceDirection(this);
    }
  }
 
  public static abstract class Strength extends DynamicsModifier {
    protected FloatChannel strengthChannel;
    public ScaledNumericValue strengthValue;
   
    public Strength(){
      strengthValue = new ScaledNumericValue();
    }
   
    public Strength (Strength rotation) {
      super(rotation);
      strengthValue = new ScaledNumericValue();
      strengthValue.load(rotation.strengthValue);
    }
   
    @Override
    public void allocateChannels() {
      super.allocateChannels();
      ParticleChannels.Interpolation.id = controller.particleChannels.newId();
      strengthChannel = controller.particles.addChannel(ParticleChannels.Interpolation);     
    }
   
    @Override
    public void activateParticles (int startIndex, int count) {
      float start, diff;
      for(int   i=startIndex*strengthChannel.strideSize, c = i +count*strengthChannel.strideSize;
        i < c;
        i +=strengthChannel.strideSize){
        start = strengthValue.newLowValue();
        diff = strengthValue.newHighValue();
        if(!strengthValue.isRelative())
          diff -= start;
        strengthChannel.data[i + ParticleChannels.VelocityStrengthStartOffset] = start;
        strengthChannel.data[i + ParticleChannels.VelocityStrengthDiffOffset] = diff;
      }
    }

    @Override
    public void write (Json json) {
      super.write(json);
      json.writeValue("strengthValue", strengthValue);
    }

    @Override
    public void read (Json json, JsonValue jsonData) {
      super.read(json, jsonData);
      strengthValue = json.readValue("strengthValue", ScaledNumericValue.class, jsonData);
    }
  }
 
  public static abstract class Angular extends Strength {
    protected FloatChannel angularChannel;
    /** Polar angle, XZ plane */
    public ScaledNumericValue thetaValue;
    /** Azimuth, Y */
    public ScaledNumericValue phiValue;

    public Angular(){
      thetaValue = new ScaledNumericValue();
      phiValue = new ScaledNumericValue();
    }
   
    public Angular (Angular value) {
      super(value);
      thetaValue = new ScaledNumericValue();
      phiValue = new ScaledNumericValue();
      thetaValue.load(value.thetaValue);
      phiValue.load(value.phiValue);
    }
   
    @Override
    public void allocateChannels() {
      super.allocateChannels();
      ParticleChannels.Interpolation4.id = controller.particleChannels.newId();
      angularChannel = controller.particles.addChannel(ParticleChannels.Interpolation4);     
    }
   
    @Override
    public void activateParticles (int startIndex, int count) {
      super.activateParticles(startIndex, count);
      float start, diff;
      for(int   i=startIndex*angularChannel.strideSize, c = i +count*angularChannel.strideSize;
        i < c;
        i +=angularChannel.strideSize){
       
        //Theta
        start = thetaValue.newLowValue();
        diff = thetaValue.newHighValue();
        if(!thetaValue.isRelative())
          diff -= start;
        angularChannel.data[i + ParticleChannels.VelocityThetaStartOffset] = start;
        angularChannel.data[i + ParticleChannels.VelocityThetaDiffOffset] = diff;

        //Phi
        start = phiValue.newLowValue();
        diff = phiValue.newHighValue();
        if(!phiValue.isRelative())
          diff -= start;
        angularChannel.data[i + ParticleChannels.VelocityPhiStartOffset] = start;
        angularChannel.data[i + ParticleChannels.VelocityPhiDiffOffset] = diff;
      }
    }
   
    @Override
    public void write (Json json) {
      super.write(json);
      json.writeValue("thetaValue", thetaValue);
      json.writeValue("phiValue", phiValue);
    }

    @Override
    public void read (Json json, JsonValue jsonData) {
      super.read(json, jsonData);
      thetaValue = json.readValue("thetaValue", ScaledNumericValue.class, jsonData);
      phiValue = json.readValue("phiValue", ScaledNumericValue.class, jsonData);
    }
  }
 
 
  public static class Rotational2D extends Strength {
    FloatChannel rotationalVelocity2dChannel;
   
    public Rotational2D (){}
   
    public Rotational2D (Rotational2D rotation) {
      super(rotation);
    }

    @Override
    public void allocateChannels() {
      super.allocateChannels();
      rotationalVelocity2dChannel = controller.particles.addChannel(ParticleChannels.AngularVelocity2D);
    }
   
    @Override
    public void update () {
      for(int   i=0, l = ParticleChannels.LifePercentOffset, s =0,
        c = i +controller.particles.size*rotationalVelocity2dChannel.strideSize;
        i < c;
        s += strengthChannel.strideSize, i +=rotationalVelocity2dChannel.strideSize,  l +=lifeChannel.strideSize){
        rotationalVelocity2dChannel.data[i] +=   strengthChannel.data[s + ParticleChannels.VelocityStrengthStartOffset] +
                                                  strengthChannel.data[s + ParticleChannels.VelocityStrengthDiffOffset]* strengthValue.getScale(lifeChannel.data[l]);
      }
    }

    @Override
    public Rotational2D copy () {
      return new Rotational2D(this);
    }
  }
 
  public static class Rotational3D extends Angular {
    FloatChannel rotationChannel, rotationalForceChannel;
   
    public Rotational3D(){}
   
    public Rotational3D (Rotational3D rotation) {
      super(rotation);
    }

    @Override
    public void allocateChannels() {
      super.allocateChannels();
      rotationChannel = controller.particles.addChannel(ParticleChannels.Rotation3D);
      rotationalForceChannel = controller.particles.addChannel(ParticleChannels.AngularVelocity3D);
    }
   
    @Override
    public void update () {
     
      //Matrix3 I_t = defined by the shape, it's the inertia tensor
      //Vector3 r = position vector
      //Vector3 L = r.cross(v.mul(m)), It's the angular momentum, where mv it's the linear momentum
      //Inverse(I_t) = a diagonal matrix where the diagonal is IyIz, IxIz, IxIy
      //Vector3 w = L/I_t = inverse(I_t)*L, It's the angular velocity
      //Quaternion spin = 0.5f*Quaternion(w, 0)*currentRotation
      //currentRotation += spin*dt
      //normalize(currentRotation)
   
      //Algorithm 1
      //Consider a simple channel which represent an angular velocity w
      //Sum each w for each rotation
      //Update rotation
     
      //Algorithm 2
      //Consider a channel which represent a sort of angular momentum L  (r, v)
      //Sum each L for each rotation
      //Multiply sum by constant quantity k = m*I_to(-1) , m could be optional while I is constant and can be calculated at start
      //Update rotation     
     
      //Algorithm 3
      //Consider a channel which represent a simple angular momentum L
      //Proceed as Algorithm 2
     
      for(int   i=0, l = ParticleChannels.LifePercentOffset, s =0, a = 0,
        c = controller.particles.size*rotationalForceChannel.strideSize;
        i < c;
        s += strengthChannel.strideSize, i +=rotationalForceChannel.strideSize,
        a += angularChannel.strideSize, l += lifeChannel.strideSize){
       
        float   lifePercent = lifeChannel.data[l],
              strength =   strengthChannel.data[s + ParticleChannels.VelocityStrengthStartOffset] +
                          strengthChannel.data[s + ParticleChannels.VelocityStrengthDiffOffset]* strengthValue.getScale(lifePercent),
              phi =   angularChannel.data[a + ParticleChannels.VelocityPhiStartOffset] +
                      angularChannel.data[a + ParticleChannels.VelocityPhiDiffOffset]* phiValue.getScale(lifePercent),
              theta =   angularChannel.data[a + ParticleChannels.VelocityThetaStartOffset] +
                        angularChannel.data[a + ParticleChannels.VelocityThetaDiffOffset]* thetaValue.getScale(lifePercent);
       
        float   cosTheta = MathUtils.cosDeg(theta), sinTheta = MathUtils.sinDeg(theta),
              cosPhi = MathUtils.cosDeg(phi), sinPhi = MathUtils.sinDeg(phi);
       
        TMP_V3.set(cosTheta *sinPhi, cosPhi, sinTheta*sinPhi);
        TMP_V3.scl(strength*MathUtils.degreesToRadians);
       
        rotationalForceChannel.data[i +ParticleChannels.XOffset] += TMP_V3.x;
        rotationalForceChannel.data[i +ParticleChannels.YOffset] += TMP_V3.y;
        rotationalForceChannel.data[i +ParticleChannels.ZOffset] += TMP_V3.z;       
      }
    }

    @Override
    public Rotational3D copy () {
      return new Rotational3D(this);
    }
  }
 
 
  public static class CentripetalAcceleration extends Strength {
    FloatChannel accelerationChannel;
    FloatChannel positionChannel;
    public CentripetalAcceleration(){}
   
    public CentripetalAcceleration (CentripetalAcceleration rotation) {
      super(rotation);
    }

    @Override
    public void allocateChannels() {
      super.allocateChannels();
      accelerationChannel = controller.particles.addChannel(ParticleChannels.Acceleration);
      positionChannel = controller.particles.addChannel(ParticleChannels.Position);
    }
   
    @Override
    public void update () {
      float cx = 0, cy = 0, cz = 0;
      if(!isGlobal){
        float[] val = controller.transform.val;
        cx = val[Matrix4.M03];
        cy = val[Matrix4.M13];
        cz = val[Matrix4.M23];
      }
     
      int lifeOffset=ParticleChannels.LifePercentOffset, strengthOffset = 0, positionOffset = 0, forceOffset = 0;
      for(int   i=0,  c= controller.particles.size; i < c; ++i, 
        positionOffset += positionChannel.strideSize,
        strengthOffset += strengthChannel.strideSize,
        forceOffset +=accelerationChannel.strideSize,
        lifeOffset += lifeChannel.strideSize){
     
        float   strength =   strengthChannel.data[strengthOffset + ParticleChannels.VelocityStrengthStartOffset] +
                          strengthChannel.data[strengthOffset + ParticleChannels.VelocityStrengthDiffOffset]* strengthValue.getScale(lifeChannel.data[lifeOffset]);
        TMP_V3.setpositionChannel.data[positionOffset +ParticleChannels.XOffset] -cx,
                      positionChannel.data[positionOffset +ParticleChannels.YOffset] -cy,
                      positionChannel.data[positionOffset +ParticleChannels.ZOffset] -cz)
                .nor().scl(strength);
        accelerationChannel.data[forceOffset +ParticleChannels.XOffset] += TMP_V3.x;
        accelerationChannel.data[forceOffset +ParticleChannels.YOffset] += TMP_V3.y;
        accelerationChannel.data[forceOffset +ParticleChannels.ZOffset] += TMP_V3.z;
      }
    }

    @Override
    public CentripetalAcceleration copy () {
      return new CentripetalAcceleration(this);
    }
  }
 
  public static class PolarAcceleration extends Angular {
    FloatChannel directionalVelocityChannel;
    public PolarAcceleration(){}
   
    public PolarAcceleration (PolarAcceleration rotation) {
      super(rotation);
    }

    @Override
    public void allocateChannels() {
      super.allocateChannels();
      directionalVelocityChannel = controller.particles.addChannel(ParticleChannels.Acceleration);
    }
   
    @Override
    public void update () {
      for(int   i=0, l = ParticleChannels.LifePercentOffset, s =0, a = 0,
        c = i +controller.particles.size*directionalVelocityChannel.strideSize;
        i < c;
        s += strengthChannel.strideSize, i +=directionalVelocityChannel.strideSize,
        a += angularChannel.strideSize, l += lifeChannel.strideSize){
       
        float   lifePercent = lifeChannel.data[l],
              strength =   strengthChannel.data[s + ParticleChannels.VelocityStrengthStartOffset] +
                          strengthChannel.data[s + ParticleChannels.VelocityStrengthDiffOffset]* strengthValue.getScale(lifePercent),
              phi =   angularChannel.data[a + ParticleChannels.VelocityPhiStartOffset] +
                      angularChannel.data[a + ParticleChannels.VelocityPhiDiffOffset]* phiValue.getScale(lifePercent),
              theta =   angularChannel.data[a + ParticleChannels.VelocityThetaStartOffset] +
                        angularChannel.data[a + ParticleChannels.VelocityThetaDiffOffset]* thetaValue.getScale(lifePercent);
       
        float cosTheta = MathUtils.cosDeg(theta), sinTheta = MathUtils.sinDeg(theta),
          cosPhi = MathUtils.cosDeg(phi), sinPhi = MathUtils.sinDeg(phi);
        TMP_V3.set(cosTheta *sinPhi, cosPhi, sinTheta*sinPhi).nor().scl(strength)
        directionalVelocityChannel.data[i +ParticleChannels.XOffset] += TMP_V3.x;
        directionalVelocityChannel.data[i +ParticleChannels.YOffset] += TMP_V3.y;
        directionalVelocityChannel.data[i +ParticleChannels.ZOffset] += TMP_V3.z;
      }
    }

    @Override
    public PolarAcceleration copy () {
      return new PolarAcceleration(this);
    }
  }
 
  public static class TangentialAcceleration extends Angular {
    FloatChannel directionalVelocityChannel, positionChannel;
   
    public TangentialAcceleration(){}
   
    public TangentialAcceleration (TangentialAcceleration rotation) {
      super(rotation);
    }

    @Override
    public void allocateChannels() {
      super.allocateChannels();
      directionalVelocityChannel = controller.particles.addChannel(ParticleChannels.Acceleration);
      positionChannel = controller.particles.addChannel(ParticleChannels.Position);
    }
   
    @Override
    public void update () {
      for(int   i=0, l = ParticleChannels.LifePercentOffset, s =0, a = 0, positionOffset = 0,
        c = i +controller.particles.size*directionalVelocityChannel.strideSize;
        i < c;
        s += strengthChannel.strideSize, i +=directionalVelocityChannel.strideSize,
        a += angularChannel.strideSize, l += lifeChannel.strideSize, positionOffset += positionChannel.strideSize ){
       
        float   lifePercent = lifeChannel.data[l],
              strength =   strengthChannel.data[s + ParticleChannels.VelocityStrengthStartOffset] +
                          strengthChannel.data[s + ParticleChannels.VelocityStrengthDiffOffset]* strengthValue.getScale(lifePercent),
              phi =   angularChannel.data[a + ParticleChannels.VelocityPhiStartOffset] +
                      angularChannel.data[a + ParticleChannels.VelocityPhiDiffOffset]* phiValue.getScale(lifePercent),
              theta =   angularChannel.data[a + ParticleChannels.VelocityThetaStartOffset] +
                        angularChannel.data[a + ParticleChannels.VelocityThetaDiffOffset]* thetaValue.getScale(lifePercent);
       
        float cosTheta = MathUtils.cosDeg(theta), sinTheta = MathUtils.sinDeg(theta),
          cosPhi = MathUtils.cosDeg(phi), sinPhi = MathUtils.sinDeg(phi);
        TMP_V3.set(cosTheta *sinPhi, cosPhi, sinTheta*sinPhi)
                .crspositionChannel.data[positionOffset +ParticleChannels.XOffset],
                      positionChannel.data[positionOffset +ParticleChannels.YOffset],
                      positionChannel.data[positionOffset +ParticleChannels.ZOffset])
                .nor().scl(strength)
        directionalVelocityChannel.data[i +ParticleChannels.XOffset] += TMP_V3.x;
        directionalVelocityChannel.data[i +ParticleChannels.YOffset] += TMP_V3.y;
        directionalVelocityChannel.data[i +ParticleChannels.ZOffset] += TMP_V3.z;
      }
    }

    @Override
    public TangentialAcceleration copy () {
      return new TangentialAcceleration(this);
    }
  }

  public static class BrownianAcceleration extends Strength {
    FloatChannel accelerationChannel;
    public BrownianAcceleration(){}
   
    public BrownianAcceleration (BrownianAcceleration rotation) {
      super(rotation);
    }

    @Override
    public void allocateChannels() {
      super.allocateChannels();
      accelerationChannel = controller.particles.addChannel(ParticleChannels.Acceleration);
    }
   
    @Override
    public void update () {
      int lifeOffset=ParticleChannels.LifePercentOffset, strengthOffset = 0, forceOffset = 0;
      for(int   i=0,  c= controller.particles.size; i < c; ++i, 
        strengthOffset += strengthChannel.strideSize,
        forceOffset +=accelerationChannel.strideSize,
        lifeOffset += lifeChannel.strideSize){
     
        float   strength =   strengthChannel.data[strengthOffset + ParticleChannels.VelocityStrengthStartOffset] +
                          strengthChannel.data[strengthOffset + ParticleChannels.VelocityStrengthDiffOffset]* strengthValue.getScale(lifeChannel.data[lifeOffset]);
        TMP_V3.set(MathUtils.random(-1, 1f), MathUtils.random(-1, 1f), MathUtils.random(-1, 1f)).nor().scl(strength);
        accelerationChannel.data[forceOffset +ParticleChannels.XOffset] += TMP_V3.x;
        accelerationChannel.data[forceOffset +ParticleChannels.YOffset] += TMP_V3.y;
        accelerationChannel.data[forceOffset +ParticleChannels.ZOffset] += TMP_V3.z;
      }
    }

    @Override
    public BrownianAcceleration copy () {
      return new BrownianAcceleration(this);
    }
  }

 
  public boolean isGlobal = false;
  protected FloatChannel lifeChannel;
 
  public DynamicsModifier(){}
 
  public DynamicsModifier (DynamicsModifier modifier) {
    this.isGlobal = modifier.isGlobal;
  }

  @Override
  public void allocateChannels() {
    lifeChannel = controller.particles.addChannel(ParticleChannels.Life);
  }
 
  @Override
  public void write (Json json) {
    super.write(json);
    json.writeValue("isGlobal", isGlobal);
  }

  @Override
  public void read (Json json, JsonValue jsonData) {
    super.read(json, jsonData);
    isGlobal = json.readValue("isGlobal", boolean.class, jsonData);
  }
 
}
TOP

Related Classes of com.badlogic.gdx.graphics.g3d.particles.influencers.DynamicsModifier$BrownianAcceleration

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.