我想扩展处理,以便能够渲染具有倾斜投影(橱柜或骑士)的3D东西。在查看相机源(),perspective()和ortho()方法后,我能够设置正交透视图,然后将PGraphics3D#相机矩阵调整到适当的值,并获得部分成功。
void setup() {
camera(30, 30, 30, 0, 0, 0, 1, 1, 0);
ortho(-100, 100, -100, 100, -500, 500);
p3d.camera.set(1, 0, -0.433f, 0, 0, 1, 0.25f, 0, 0, 0, 0, 0, 0, 0, 0, 1);
}
void draw() {
box(20);
}
这导致了正确的视角,但没有表面填充。当移除相机和正交方法调用或两者同时,屏幕是空的,虽然我希望相机(...)在稍后被覆盖的相同矩阵上操作。
此外,我对PGraphics3D中的matrizes有点困惑:相机,modelView和投影。虽然OpenGL保留了两个矩阵堆栈 - modelView和projection,但这里是第三个 - 相机。任何人都可以了解这些基质之间的差异和关系吗?
这将有助于知道何时使用/设置哪一个。
答案 0 :(得分:2)
很棒的问题!
我运行了以下代码,它看起来像一个白色立方体的等轴视图。
1: size(300,300,P3D);
2: camera(30, 30, 30, 0, 0, 0, 1, 1, 0);
3: ortho(-100, 100, -100, 100, -500, 500);
4: PGraphics3D p3d = (PGraphics3D)g;
5: p3d.camera.set(1, 0, -0.433f, 0, 0, 1, 0.25f, 0, 0, 0, 0, 0, 0, 0, 0, 1);
6: box(20);
以下是发生的事情:
仅使用 modelview 和投影矩阵执行转换。 相机矩阵只是方便地将模型视图通常初始化的内容分开。
如果使用了draw()函数, modelview 矩阵实际上会在每次调用之前初始化为 camera 矩阵。由于您没有使用draw()函数,因此您的相机矩阵从未使用相机矩阵中的倾斜变换进行更新。
作为免责声明,您必须真正了解矩阵如何用于转换坐标。订单非常重要。这是学习它的好资源: http://glprogramming.com/red/chapter03.html
我能给出的最快解释是 modelview 矩阵将对象坐标转换为相对 eye 坐标,然后投影< / strong> matrix获取 eye 坐标并将它们转换为 screen 坐标。因此,您希望在转换到屏幕坐标之前应用倾斜投影。
这是一个可运行的示例,用于创建显示一些立方体的橱柜投影:
void setup()
{
strokeWeight(2);
smooth();
noLoop();
size(600,600,P3D);
oblique(radians(60),0.5);
}
void draw()
{
background(100);
// size of the box
float w = 100;
// draw box in the middle
translate(width/2,height/2);
fill(random(255),random(255),random(255),100);
box(w);
// draw box behind
translate(0,0,-w*4);
fill(random(255),random(255),random(255),100);
box(w);
// draw box in front
translate(0,0,w*8);
fill(random(255),random(255),random(255),100);
box(w);
}
void oblique(float angle, float zscale)
{
PGraphics3D p3d = (PGraphics3D)g;
// set orthographic projection
ortho(-width/2,width/2,-height/2,height/2,-5000,5000);
// get camera's z translation
// ... so we can transform from the original z=0
float z = p3d.camera.m23;
// apply z translation
p3d.projection.translate(0,0,z);
// apply oblique projection
p3d.projection.apply(
1,0,-zscale*cos(angle),0,
0,1,zscale*sin(angle),0,
0,0,1,0,
0,0,0,1);
// remove z translation
p3d.projection.translate(0,0,-z);
}