所以我正在编写这个简单的粒子系统/3D 程序,但我无法让投影工作。我对这些东西了解不多,所以我阅读了维基百科,我认为透视投影可能有用。我正在使用这个公式 http://en.wikipedia.org/wiki/3D_projection#Perspective_projection
我的画布没有显示任何东西,所以我认为投影是错误的。我有一个边缘在 (200, 200, 200) 和 (300, 300, 300) 的立方体,但它没有出现在屏幕上。我想也许我选择了错误的相机旋转值或其他东西,所以我尝试在所有 x、y 和 z 轴上以 10 个单位间隔绘制很多点,范围从 -100 到 100。然后我将相机放在 (0,0,0) 并认为我会看到一些东西,但我没有。它将所有内容投影到 NaN 或 (0,0)。我真的不明白我应该为 e 值选择什么。
这是代码。我省略了绘画和其他东西,并试图专注于投影。
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 + ">";
}
}