LibGDX - 3D动作效果

时间:2017-08-22 01:53:02

标签: opengl math libgdx glsl opengl-es-2.0

我需要在3D空间中实现动作效果(超高速)。为此我决定使用贴花。我以随机顺序将1000个粒子放置在有限的空间中,并使用相机位置以相反的方向移动它们以产生超高速效果。也许,它不是一个完美的解决方案,最好在相机前面创建粒子,或者使用着色器和帧缓冲器。无论如何,问题是我需要根据相机的移动将这些粒子拉伸到正确的方向。事实上,它们已经拉长,但需要旋转。为了澄清这一点,让我们看看下面的截图:

left & right dir

up & down dir

diagonal dir

forward & backward dir

嗯,我希望主要观点很明确。另外,我想提供我的课程:

public class MotionEffect {

Camera camera;
Vector3 oldCameraPos, displacement;

Vector3 prjCamPos;
Vector3 prjOldPos;

Vector3 rotationVec;    
DecalBatch decalBatch;
private Texture dustTex;


private class Particle{

    float size = 1.5f;
    final float areaSize = 250;
    Decal decal;
    float x, y, z;
    float dx, dy ,dz;
    float r, g, b, a;

    public Particle(TextureRegion texRegion){

        decal = Decal.newDecal(size, size, texRegion, true);

        r=1; g=1; b=1;
        init();
    }

    private void init() {
        a = 1;

        x = MathUtils.random(-areaSize, areaSize) + Settings.SunPosition.x;
        y = MathUtils.random(-areaSize, areaSize) + Settings.SunPosition.y;
        z = MathUtils.random(-areaSize, areaSize) + Settings.SunPosition.z;

    }

    public void update(Vector3 displacement, float alpha, float angle) {

        dx = -displacement.x;
        dy = -displacement.y;
        dz = -displacement.z;

        x += dx;
        y += dy;
        z += dz;


        if ((x < -areaSize || x > areaSize) || (y < -areaSize || y > areaSize) || (z < -areaSize || z > areaSize)) init();


        decal.setColor(r, g, b, 1);
        decal.setPosition(x, y, z);

        decal.setWidth(size * 20 * alpha);

        //decal has to be always faced to the camera
        decal.setRotation(camera.direction, camera.up);

        decal.rotateZ(angle); //rotate decal according to the camera movement
        //decal.rotateY(90); //rotate particle to forward - backward dir

    }

    public void render(DecalBatch decalBatch){
        float distance = decal.getPosition().dst(camera.position);
        if(distance>270) return;
        if(distance<30) return;           
        decalBatch.add(decal);
    }
}

int countOfParticles=1000;
Particle[] particles;

Vector2 original;
Vector2 direction;

public MotionEffect(Camera camera){

    this.camera = camera;             

    oldCameraPos = new Vector3(camera.position);
    displacement = new Vector3();

    decalBatch = new DecalBatch(new DustGroupStrategy(camera));
    dustTex = new Texture(Gdx.files.internal("textures/shine.png"));
    TextureRegion dustTexReg = new TextureRegion(dustTex);

    particles = new Particle[countOfParticles];
    for(int i=0; i<countOfParticles; i++){
        particles[i] = new Particle(dustTexReg);
    }

    rotationVec = new Vector3();

    original = new Vector2(0, 10);
    direction = new Vector2();

    prjCamPos = new Vector3();
    prjOldPos = new Vector3();
}

private float calcMovement(Camera camera, float delta) {
    float lerp = 0.1f;
    Vector3 cameraPosition = camera.position;

    float x = (cameraPosition.x - oldCameraPos.x) * lerp ;
    float y = (cameraPosition.y - oldCameraPos.y) * lerp ;
    float z = (cameraPosition.z - oldCameraPos.z) * lerp ;

    oldCameraPos.x += x;
    oldCameraPos.y += y;
    oldCameraPos.z += z;

    prjCamPos.set(cameraPosition);
    prjCamPos.add(.1f,.1f,.1f);
    prjOldPos.set(oldCameraPos);
    prjOldPos.add(.1f,.1f,.1f);
    camera.project(prjCamPos);
    camera.project(prjOldPos);
    Gdx.app.log("sds", prjCamPos+" - "+prjOldPos);

    float del = .1f;
    x /= del;
    y /= del;
    z /= del;

    displacement.set(x, y, z);
    float alpha = (Math.abs(displacement.x) + Math.abs(displacement.y) + Math.abs(displacement.z)) / 3f;
    if(alpha>1) alpha = 1;
    return alpha;
}

//ATTEMPT TO CALC THE ANGLE
public float getAngle(Vector3 oldPoint, Vector3 newPoint) {
    float angle = (float) Math.toDegrees(Math.atan2(newPoint.y - oldPoint.y, newPoint.x - oldPoint.x));

    if(angle < 0){
        angle += 360;
    }

    return -angle;
}


//ATTEMPT TO CALC THE ANGLES
float angleX, angleY, angleZ;

private void calcAngle(){
    Vector3 thisPoint = oldCameraPos;
    Vector3 targetPoint = camera.position;

    float someSmallEpsilon = 0.01f;

    Vector3 difference = targetPoint.sub(thisPoint);

    angleX = 0;

    if (difference.len() < someSmallEpsilon)
    {
        // Objects are at the same location - can't
        // sensibly compute a direction to look at
        return;
    }
    Vector3 direction = difference.nor();

    Vector3 xAxis = new Vector3(1,0,0);

    float dotProduct = xAxis.dot(direction);
    angleX = (float) Math.acos(dotProduct);

    if (angleX < someSmallEpsilon)
    {
        // Angle is already right. Nothing to do
        return;
    }

    Vector3 axis = xAxis.crs(direction).nor();
    Quaternion result = new Quaternion();
    result.setFromAxisRad(axis, angleX);

}

public void render(Camera camera){

    float alpha = calcMovement(camera, Gdx.graphics.getDeltaTime());

    if(alpha<=0) return;

    //calcAngle();
    float angle = getAngle(prjCamPos, prjOldPos);

    for(int i=0; i<countOfParticles; i++){
        particles[i].update(displacement, alpha, angle);
        particles[i].render(decalBatch);
    }
    decalBatch.flush();
}
}

任何帮助都将不胜感激。

0 个答案:

没有答案