0

所以我正在编写这个简单的粒子系统/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 + ">";
    }
}
4

1 回答 1

0

您的 3d 投影公式应为:

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

其中 factor 是个人选择的数量(我选择 250), center 是消失点。

例子:

  • 如果 z 是无限的,则 proj = center。
  • 如果 z 为 0,则 proj 将保持不变。

笔记:

x 和 y 是相对于相机的,为此你从它们的真实位置中减去相机位置(我认为你也必须应用旋转)。

于 2013-04-06T13:29:58.183 回答