📄 thinlens.java
字号:
package org.sunflow.core.camera;
import org.sunflow.SunflowAPI;
import org.sunflow.core.CameraLens;
import org.sunflow.core.ParameterList;
import org.sunflow.core.Ray;
public class ThinLens implements CameraLens {
private float au, av;
private float aspect, fov;
private float focusDistance;
private float lensRadius;
private int lensSides;
private float lensRotation;
private float lensRotationRadians;
public ThinLens() {
focusDistance = 1;
lensRadius = 0;
fov = 90;
aspect = 1;
lensSides = 0; // < 3 means use circular lens
lensRotation = lensRotationRadians = 0; // this rotates polygonal lenses
}
public boolean update(ParameterList pl, SunflowAPI api) {
// get parameters
fov = pl.getFloat("fov", fov);
aspect = pl.getFloat("aspect", aspect);
focusDistance = pl.getFloat("focus.distance", focusDistance);
lensRadius = pl.getFloat("lens.radius", lensRadius);
lensSides = pl.getInt("lens.sides", lensSides);
lensRotation = pl.getFloat("lens.rotation", lensRotation);
update();
return true;
}
private void update() {
au = (float) Math.tan(Math.toRadians(fov * 0.5f)) * focusDistance;
av = au / aspect;
lensRotationRadians = (float) Math.toRadians(lensRotation);
}
public Ray getRay(float x, float y, int imageWidth, int imageHeight, double lensX, double lensY, double time) {
float du = -au + ((2.0f * au * x) / (imageWidth - 1.0f));
float dv = -av + ((2.0f * av * y) / (imageHeight - 1.0f));
float eyeX, eyeY;
if (lensSides < 3) {
double angle, r;
// concentric map sampling
double r1 = 2 * lensX - 1;
double r2 = 2 * lensY - 1;
if (r1 > -r2) {
if (r1 > r2) {
r = r1;
angle = 0.25 * Math.PI * r2 / r1;
} else {
r = r2;
angle = 0.25 * Math.PI * (2 - r1 / r2);
}
} else {
if (r1 < r2) {
r = -r1;
angle = 0.25 * Math.PI * (4 + r2 / r1);
} else {
r = -r2;
if (r2 != 0)
angle = 0.25 * Math.PI * (6 - r1 / r2);
else
angle = 0;
}
}
r *= lensRadius;
// point on the lens
eyeX = (float) (Math.cos(angle) * r);
eyeY = (float) (Math.sin(angle) * r);
} else {
// sample N-gon
// FIXME: this could use concentric sampling
lensY *= lensSides;
float side = (int) lensY;
float offs = (float) lensY - side;
float dist = (float) Math.sqrt(lensX);
float a0 = (float) (side * Math.PI * 2.0f / lensSides + lensRotationRadians);
float a1 = (float) ((side + 1.0f) * Math.PI * 2.0f / lensSides + lensRotationRadians);
eyeX = (float) ((Math.cos(a0) * (1.0f - offs) + Math.cos(a1) * offs) * dist);
eyeY = (float) ((Math.sin(a0) * (1.0f - offs) + Math.sin(a1) * offs) * dist);
eyeX *= lensRadius;
eyeY *= lensRadius;
}
float eyeZ = 0;
// point on the image plane
float dirX = du;
float dirY = dv;
float dirZ = -focusDistance;
// ray
return new Ray(eyeX, eyeY, eyeZ, dirX - eyeX, dirY - eyeY, dirZ - eyeZ);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -