2013-03-03 75 views
0

所以我正在写这个简单的粒子系统/ 3D程序,但我不能让投影工作。我对这个东西了解不多,所以我读了维基百科,我认为透视投影可能是有用的。我正在使用此公式 http://en.wikipedia.org/wiki/3D_projection#Perspective_projection在java中的3d图形。投影

我的画布没有显示任何内容,所以我认为投影是错误的。我有一个在(200,200,200)和(300,300,300)边缘的立方体,但它没有出现在屏幕上。我想也许我选择了错误的值来旋转相机或者是什么东西,所以我试着在所有x轴,y轴和z轴上以10单位的间隔绘制了从-100到100的很多点。然后我把相机放在(0,0,0)里,以为我会看到一些东西,但我不知道。它将所有内容投射到NaN或(0,0)。我真的不明白我应该选择什么样的价值。

这是代码。我忽略了绘画和其他东西,并试图专注于投影。

package org.gcs.kinetic; 

import java.awt.Color; 
import java.util.ArrayList; 

public class StillParticle extends Particle{ 
    Color getColor(){ 
     return Color.YELLOW; 
    } 

    @Override 
    public void iterate(){ 

    } 

    public static ArrayList<Particle> getCube(){ 
     ArrayList<Particle> result = new ArrayList<Particle>(); 
     StillParticle p; 
     for(int i = -100; i < 100; i+=10){ 
      for(int j = -100; j < 100; j+=10){ 
       for(int k = -100; k < 100; k+=10){ 
        p = new StillParticle(); 
        p.setColor(Color.YELLOW); 
        p.setPosition(i, j, k); 
        p.setR(2); 
        result.add(p); 
       } 
      } 
     } 
     return result; 
    } 

} 

package org.gcs.kinetic; 

public class Camera { 
    Vector3D c; 
    Vector3D o; 
    Vector3D e; 

    public Camera(Vector3D c, Vector3D o, Vector3D e) { 
     this.c=c; 
     this.o=o; 
     this.e=e; 
    } 

    double[] project(Vector3D a){ 
     double dx = cos(o.y)*(sin(o.z)*(a.y-c.y)+cos(o.z)*(a.x-c.x))-sin(o.y)*(a.z-c.z); 
     double dy = sin(o.x)*(cos(o.y)*(a.z-c.z)+sin(o.y)*(sin(o.z)*(a.y-c.y)+cos(o.z)*(a.x-c.x)))+cos(o.x)*(cos(o.z)*(a.y-c.y)-sin(o.z)*(a.x-c.x)); 
     double dz = cos(o.x)*(cos(o.y)*(a.z-c.z)+sin(o.y)*(sin(o.z)*(a.y-c.y)+cos(o.z)*(a.x-c.x)))-sin(o.x)*(cos(o.z)*(a.y-c.y)-sin(o.z)*(a.x-c.x)); 
     double[] result = new double[2]; 
     System.out.println(dx + ", "+ dy+ ", " + dz); 
     result[0] = (dx-e.x)*(e.z/dz); 
     result[1] = (dy-e.y)*(e.z/dz); 
     System.out.println(a+ " projected to " + result[0]+ "," + result[1]); 
     return result; 
    } 

    double cos(double x){ 
     return Math.cos(x); 
    } 
    double sin(double x){ 
     return Math.sin(x); 
    } 
} 

/** Free for non-military use */ 
package org.gcs.kinetic; 

import java.awt.*; 

/** 
* A Particle is assumed to be spherical. The particle's mass 
* is assumed to be proportional to r^3. Vector p is the center 
* of the particle's enclosing square, and Vector v contains 
* the particle's velocity components. 
* 
*/ 
class Particle extends Object { 

    private double radius = 0; 
    private double mass = 0; 
    protected int age = 0; 
    int MAXAGE = 60; 
    private Color color = new Color(0, true); 
    private Image image = null; 
    private Vector3D p = new Vector3D(); 
    private Vector3D v = new Vector3D(); 
    private Vector3D a = new Vector3D(0.0,0.1,0.0); 
    public static Ensemble world; 

    /** 
    * Construct a dimensionless, massless, invisible, 
    * stationary particle at the origin. 
    */ 
    public Particle() { 
    } 

    /** Return a new Vector with this particle's position. */ 
    public Vector3D getPosition() { 
     return new Vector3D(p); 
    } 

    /** Return the given Vector set to this particle's position. */ 
    public Vector3D getPosition(Vector3D p) { 
     p.x = this.p.x; p.y = this.p.y; p.z=this.p.z; 
     return p; 
    } 

    public double getX() { 
     return this.p.x; 
    } 

    public double getY() { 
     return this.p.y; 
    } 

    public double getZ() { 
     return this.p.z; 
    } 

    public void setPosition(Vector3D p) { 
     this.p.x = p.x; 
     this.p.y = p.y; 
     this.p.z = p.z; 
    } 

    public void setPosition(double x, double y, double z) { 
     this.p.x = x; 
     this.p.y = y; 
     this.p.z = z; 
    } 

    public Vector3D getVelocity() { 
     return new Vector3D(v); 
    } 

    public Vector3D getVelocity(Vector3D v) { 
     v.x = this.v.x; v.y = this.v.y;v.z = this.v.z; 
     return v; 
    } 

    public double getVx() { return this.v.x; } 
    public double getVy() { return this.v.y; } 
    public double getVz() { return this.v.z; } 

    public double getVNorm() { 
     return v.norm(); 
    } 

    public void setVelocity(Vector3D v) { 
     this.v.x = v.x; this.v.y = v.y; this.v.z = v.z; 
    } 

    public void setVelocity(double vx, double vy, double vz) { 
     this.v.x = vx; this.v.y = vy; this.v.z=vz; 
    } 

    /** Set this particle's radius and imputed mass. */ 
    public void setR(double radius) { 
     this.radius = radius; 
     this.mass = radius * radius * radius; 
    } 

    public double getR() { return this.radius; } 

    public double getM() { return this.mass; } 

    Color getColor() { 
     double factor = age/(double)MAXAGE; 
     int red = (int) ((1-factor)*color.getRed()); 
     int green = (int) ((1-factor)*color.getGreen()); 
     int blue = (int) ((1-factor)*color.getBlue()); 
     return new Color(red, green, blue); 
    } 

    public void setColor(Color color) { this.color = color; } 

    public Image getImage() { return image; } 

    public void setImage(Image image) { this.image = image; } 

    public void iterate() { 
     age++; 
     updatePos(); 
     updateVelocity(); 
     //updateAcceleration(); 
     if(age==MAXAGE) 
      world.removedParticles.add(this); 
    } 

    protected void updatePos() { 
     p.x += v.x; 
     p.y += v.y; 
     p.z += v.z; 
    } 

    protected void updateVelocity() { 
     v.x += a.x; 
     v.y += a.y; 
     v.z += a.z; 
    } 

    private void updateAcceleration() { 

    } 
} 

/** Free for non-military use */ 
package org.gcs.kinetic; 

/** 
* Vector represents a 3D-Vector 
* 
* @see Particle 
* @see Ensemble 
*/ 
class Vector3D extends Object { 

    /** The Vector's x and y component. */ 
    public double x; 
    public double y; 
    public double z; 

    /** Construct a null Vector, <0, 0, 0> by default. */ 
    public Vector3D() { 
    } 

    /** 
    * Construct a new Vector from two doubles. 
    * @param x the x component 
    * @param y the y component 
    * @param z the z component 
    */ 
    public Vector3D(double x, double y, double z) { 
     this.x = x; this.y = y; this.z = z; 
    } 

    /** 
    * Construct a new Vector from two integers. 
    * @param x the x component 
    * @param y the y component 
    * @param z the z component 
    */ 
    public Vector3D(int x, int y, int z) { 
     this.x = x; this.y = y; this.z = z; 
    } 

    /** 
    * Construct a new Vector from an existing one. 
    * @param v the source Vector 
    */ 

    public Vector3D(Vector3D v) { 
     this.x = v.x; this.y = v.y; this.z = v.z; 
    } 

    /** Set the components of this Vector. 
    * @param x the x component 
    * @param y the y component 
    * @param z the z component 
    * @return this Vector. 
    */ 
    public Vector3D set(double x, double y, double z) { 
     this.x = x; this.y = y; this.z = z; 
     return this; 
    } 

    /** 
    * Set the coordinates of this Vector3D to those of v. 
    * @param v the source Vector3D 
    * @return this Vector3D. 
    */ 
    public Vector3D set(Vector3D v) { 
     this.x = v.x; this.y = v.y; this.z = v.z; 
     return this; 
    } 

    /** 
    * Return the length of this Vector. 
    * @return the length of this Vector 
    */ 
    public double norm() { 
     return Math.sqrt(x*x + y*y + z*z); 
    } 

    /** 
    * Add the given Vector to this Vector; return this Vector. 
    * @param v the given Vector 
    * @return the sum 
    */ 
    public Vector3D add(Vector3D v) { 
     this.x += v.x; 
     this.y += v.y; 
     this.z += v.z; 
     return this; 
    } 

    /** 
    * Subtract the given Vector from this Vector; return this Vector. 
    * @param v the given Vector 
    * @return the difference 
    */ 
    public Vector3D subtract(Vector3D v) { 
     this.x -= v.x; 
     this.y -= v.y; 
     this.z -= v.z; 
     return this; 
    } 

    /** 
    * Multiply the given Vector by this Vector; return the scalar product. 
    * @param v the given Vector 
    * @return the scalar (dot) product 
    */ 
    public double dot(Vector3D v) { 
     return (this.x * v.x) + (this.y * v.y) + (this.z*v.z); 
    } 

    /** 
    * Scale this Vector by the given scale factor. 
    * @param s the scale factor 
    * @return the this Vector, scaled by s 
    */ 
    public Vector3D scale(double s) { 
     this.x *= s; this.y *= s; this.z *=s; 
     return this; 
    } 

    /** 
    * Scale this Vector by 1/norm(); return this Vector. 
    * The result is a unit Vector parallel to the original. 
    * This is equivalent to this.scale(1/this.norm()), 
    * with a check for division by zero. 
    * @return the this Vector, scaled to unit length 
    */ 
    public Vector3D unitVector() { 
     double d = norm(); 
     if (d != 0) { this.x /= d; this.y /= d; this.z /= d;} 
     return this; 
    } 

    /** Return this Vector's String representation. */ 
    public String toString() { 
     return "<" + this.x + ", " + this.y +", "+ this.z + ">"; 
    } 
} 

回答

0

您的3D投影式应为:

proj.x = x * factor/(z + factor) + center.x 
proj.y = y * factor/(z + factor) + center.y 

其中因素是一些个人选择(我选择250),中心是消失点。

实施例:

  • 如果z无限的,凸出=中心。
  • 如果z为0,proj将保持不变。

注:

x和y是相对于摄像头,这一点,你从他们的实际位置减去摄像机位置(U也必须申请转,我认为)。