⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.java

📁 Sunflow是一个照片级的渲染系统
💻 JAVA
字号:
package org.sunflow.core;

import org.sunflow.SunflowAPI;
import org.sunflow.math.Matrix4;
import org.sunflow.math.OrthoNormalBasis;
import org.sunflow.math.Point3;
import org.sunflow.math.Vector3;
import org.sunflow.system.UI;
import org.sunflow.system.UI.Module;

/**
 * This class represents a camera to the renderer. It handles the mapping of
 * camera space to world space, as well as the mounting of {@link CameraLens}
 * objects which compute the actual projection.
 */
public class Camera implements RenderObject {
    private final CameraLens lens;
    private Matrix4[] c2w;
    private Matrix4[] w2c;

    public Camera(CameraLens lens) {
        this.lens = lens;
        c2w = w2c = new Matrix4[1]; // null
    }

    public boolean update(ParameterList pl, SunflowAPI api) {
        int n = pl.getInt("transform.steps", 0);
        if (n <= 0) {
            // no motion blur, get regular arguments or leave unchanged
            updateCameraMatrix(-1, pl);
        } else {
            // new motion blur settings - get transform for each step
            c2w = new Matrix4[n];
            for (int i = 0; i < n; i++) {
                if (!updateCameraMatrix(i, pl)) {
                    UI.printError(Module.CAM, "Camera matrix for step %d was not specified!", i + 1);
                    return false;
                }
            }
        }
        w2c = new Matrix4[c2w.length];
        for (int i = 0; i < c2w.length; i++) {
            if (c2w[i] != null) {
                w2c[i] = c2w[i].inverse();
                if (w2c[i] == null) {
                    UI.printError(Module.CAM, "Camera matrix is not invertible");
                    return false;
                }
            } else
                w2c[i] = null;
        }
        return lens.update(pl, api);
    }

    private boolean updateCameraMatrix(int index, ParameterList pl) {
        String offset = index < 0 ? "" : String.format("[%d]", index);
        if (index < 0)
            index = 0;
        Matrix4 transform = pl.getMatrix(String.format("transform%s", offset), null);
        if (transform == null) {
            // no transform was specified, check eye/target/up
            Point3 eye = pl.getPoint(String.format("eye%s", offset), null);
            Point3 target = pl.getPoint(String.format("target%s", offset), null);
            Vector3 up = pl.getVector(String.format("up%s", offset), null);
            if (eye != null && target != null && up != null) {
                c2w[index] = Matrix4.fromBasis(OrthoNormalBasis.makeFromWV(Point3.sub(eye, target, new Vector3()), up));
                c2w[index] = Matrix4.translation(eye.x, eye.y, eye.z).multiply(c2w[index]);
            } else {
                // the matrix for this index was not specified
                // return an error, unless this is a regular update
                return offset.length() == 0;
            }
        } else
            c2w[index] = transform;
        return true;
    }

    /**
     * Generate a ray passing though the specified point on the image plane.
     * Additional random variables are provided for the lens to optionally
     * compute depth-of-field or motion blur effects. Note that the camera may
     * return <code>null</code> for invalid arguments or for pixels which
     * don't project to anything.
     * 
     * @param x x pixel coordinate
     * @param y y pixel coordinate
     * @param imageWidth width of the image in pixels
     * @param imageHeight height of the image in pixels
     * @param lensX a random variable in [0,1) to be used for DOF sampling
     * @param lensY a random variable in [0,1) to be used for DOF sampling
     * @param time a random variable in [0,1) to be used for motion blur
     *            sampling
     * @return a ray passing through the specified pixel, or <code>null</code>
     */
    public Ray getRay(float x, float y, int imageWidth, int imageHeight, double lensX, double lensY, double time) {
        Ray r = lens.getRay(x, y, imageWidth, imageHeight, lensX, lensY, time);
        if (r != null) {
            if (c2w.length == 1) {
                // regular sampling
                r = r.transform(c2w[0]);
            } else {
                // motion blur
                double nt = time * (c2w.length - 1);
                int idx0 = (int) nt;
                int idx1 = Math.min(idx0 + 1, c2w.length - 1);
                r = r.transform(Matrix4.blend(c2w[idx0], c2w[idx1], (float) (nt - idx0)));
            }
            // renormalize to account for scale factors embeded in the transform
            r.normalize();
        }
        return r;
    }

    /**
     * Generate a ray from the origin of camera space toward the specified
     * point.
     * 
     * @param p point in world space
     * @return ray from the origin of camera space to the specified point
     */
    Ray getRay(Point3 p) {
        return new Ray(c2w == null ? new Point3(0, 0, 0) : c2w[0].transformP(new Point3(0, 0, 0)), p);
    }

    /**
     * Returns a transformation matrix mapping camera space to world space.
     * 
     * @return a transformation matrix
     */
    Matrix4 getCameraToWorld() {
        return c2w == null ? Matrix4.IDENTITY : c2w[0];
    }

    /**
     * Returns a transformation matrix mapping world space to camera space.
     * 
     * @return a transformation matrix
     */
    Matrix4 getWorldToCamera() {
        return w2c == null ? Matrix4.IDENTITY : w2c[0];
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -