谈谈Processing 3D世界 四(补充)

    xiaoxiao2025-10-12  12

    当我们实现了第四节的案例后,会苦恼的发现我们虽然可以操控摄影机移动,但转动视角后,摄影机却仍然沿着原来的坐标轴移动。这十分不方便。

    这里我们对这个案例补完,实现摄影机永远按照转动后的视角坐标移动。

    随着学习的深入,程序难免会越来越复杂,这里我们把程序分割成3页,使程序的脉络更清晰一些:

    step1 定义顶点数据

    我们新建一个Data的标签页: float max = 2.0; void initVertices() { // 设置顶点 ver = new PVector[8]; ver[0] = new PVector(-0.5, -0.5, 0.5); // 顶点1 ver[1] = new PVector(-0.5, -0.5, -0.5); // 顶点2 ver[2] = new PVector( 0.5, -0.5, -0.5); // ... ver[3] = new PVector( 0.5, -0.5, 0.5); ver[4] = new PVector(-0.5, 0.5, 0.5); ver[5] = new PVector(-0.5, 0.5, -0.5); ver[6] = new PVector( 0.5, 0.5, -0.5); ver[7] = new PVector( 0.5, 0.5, 0.5); // 设置顶点索引 face = new PVector[12]; // top face[0] = new PVector(0, 1, 2); face[1] = new PVector(0, 2, 3); // front face[2] = new PVector(0, 3, 7); face[3] = new PVector(0, 7, 4); // back face[4] = new PVector(1, 2, 6); face[5] = new PVector(1, 6, 5); // right face[6] = new PVector(3, 2, 7); face[7] = new PVector(2, 6, 7); // left face[8] = new PVector(0, 4, 5); face[9] = new PVector(1, 5, 0); // bottom face[10] = new PVector(4, 5, 7); face[11] = new PVector(5, 6, 7); // 设置UV // 目前有一点苦力活需要干,但很快,将会有东西拯救我们。 uv = new PVector[12][3]; // 12个面,每个面3个顶点,为每个顶点描述UV // top uv[0][0] = new PVector(0, max); // face0 uv[0][1] = new PVector(0, 0); uv[0][2] = new PVector(max, 0); uv[1][0] = new PVector(0, max); // face1 uv[1][1] = new PVector(max, 0); uv[1][2] = new PVector(max, max); // front uv[2][0] = new PVector(0, 0); // face2 uv[2][1] = new PVector(max, 0); uv[2][2] = new PVector(max, max); uv[3][0] = new PVector(0, 0); // face3 uv[3][1] = new PVector(max, max); uv[3][2] = new PVector(0, max); // back uv[4][0] = new PVector(0, 0); // face4 uv[4][1] = new PVector(max, 0); uv[4][2] = new PVector(max, max); uv[5][0] = new PVector(0, 0); // face5 uv[5][1] = new PVector(max, max); uv[5][2] = new PVector(0, max); // right uv[6][0] = new PVector(0, 0); // face6 uv[6][1] = new PVector(max, 0); uv[6][2] = new PVector(0, max); uv[7][0] = new PVector(max, 0); // face7 uv[7][1] = new PVector(max, max); uv[7][2] = new PVector(0, max); // left uv[8][0] = new PVector(0, 0); // face8 uv[8][1] = new PVector(0, max); uv[8][2] = new PVector(max, max); uv[9][0] = new PVector(max, 0); // face9 uv[9][1] = new PVector(max, max); uv[9][2] = new PVector(0, 0); // bottom uv[10][0] = new PVector(0, max); // face10 uv[10][1] = new PVector(0, 0); uv[10][2] = new PVector(max, max); uv[11][0] = new PVector(0, 0); // face11 uv[11][1] = new PVector(max, 0); uv[11][2] = new PVector(max, max); } void initLocation() { // 设置cubes的位置坐标 cubesPos = new PVector[8]; cubesPos[0] = new PVector(); cubesPos[1] = new PVector(100.0, 0.0, -400.0); cubesPos[2] = new PVector(400.0, 0.0, -400.0); cubesPos[3] = new PVector(400.0, 400.0, -400.0); cubesPos[4] = new PVector(400.0, 400.0, 0.0); cubesPos[5] = new PVector( 0.0, 400.0, -400.0); cubesPos[6] = new PVector(400.0, 0.0, 0.0); cubesPos[7] = new PVector(700.0, 0.0, 0.0); } void initTexture() { // 载入贴图 tex = loadImage("t3.jpg"); // 贴图在前面的章节有链接 tex.resize(int(256/max), 0); // 设置纹理属性 textureMode(NORMAL); textureWrap(REPEAT); }

    step2 设置摄影机

    让我们新建一个Camera的标签页: void initCamera() { // 设置摄影机 focalLength = (height/2.0) / tan(PI*30.0/180.0); cameraPos = new PVector(width/2.0, height/2.0, focalLength); cameraFront = new PVector(0.0, 0.0, -1.0); up = new PVector(0.0, 1.0, 0.0); // 投影矩阵参数 fov = radians(60); // 视野(Field of View) aspect = float(width)/float(height); // 画幅比例 zNear = cameraPos.z/10.0; // 近焦平面 zFar = cameraPos.z*10.0; // 远焦平面 // 摄影机旋转属性 yaw = -90.0; pitch = 0.0; } void do_movement() { float cameraSpeed = 5.0; // 移动摄影机(同时移动目标) if (keyPressed) { // 前后 if (key == 'w') { // 沿着摄影机的方向cameraDront前行 cameraPos.add(PVector.mult(cameraFront,cameraSpeed)); } if (key == 's') { // 沿着摄影机的方向cameraDront后退 cameraPos.sub(PVector.mult(cameraFront,cameraSpeed)); } // 左右 if (key == 'a') { // 后退即向左 PVector v = cameraFront.get(); v = v.cross(up); // 利用叉乘求出摄影机方向的右向量 v.normalize(); cameraPos.sub(PVector.mult(v,cameraSpeed)); } if (key == 'd') { // 前进即向右 PVector v = cameraFront.get(); v = v.cross(up); v.normalize(); cameraPos.add(PVector.mult(v,cameraSpeed)); } } // 转动摄影机视角 float sensitivity = 0.05; // 灵敏度 if (mousePressed) { // 偏航 yaw += (mouseX - pmouseX)*sensitivity; // 俯仰 pitch += (mouseY - pmouseY)*sensitivity; // 限值俯仰值 if (pitch > 89.0f) pitch = 89.0f; if (pitch < -89.0f) pitch = -89.0f; // 更新摄影机目标 cameraFront.x = cos(radians(yaw))*cos(radians(pitch)); cameraFront.y = sin(radians(pitch)); cameraFront.z = sin(radians(yaw))*cos(radians(pitch)); cameraFront.normalize(); } // 重置 if (keyPressed) { if (key == 'r') { yaw = -90.0; pitch = 0.0; cameraFront.x = cos(radians(yaw))*cos(radians(pitch)); cameraFront.y = sin(radians(pitch)); cameraFront.z = sin(radians(yaw))*cos(radians(pitch)); cameraFront.normalize(); cameraPos = new PVector(width/2.0, height/2.0, focalLength); } } }

    step3 程序主体

    // 窗口属性 int w = 720; int h = 480; // 定义顶点 PVector[] ver; PVector[] face; PVector[][] uv; PVector[] cubesPos; PImage tex; // 摄影机属性 PVector cameraPos, cameraTarget, up, cameraFront; float focalLength; // 焦距 float fov, aspect, zNear, zFar; float yaw, pitch; // 偏航、俯仰 float[] angle = new float[8]; void settings() { //fullScreen(); size(w, h, P3D); } void setup() { initVertices(); // 初始化顶点数据 initLocation(); // 初始化网格位置 initTexture(); // 初始化纹理 initCamera(); // 初始化摄影机 // 其他 noStroke(); for (int i = 0; i < 8; i++) { angle[i] = random(2*PI); } } void draw() { // 清楚缓冲区 background(0); // 事件处理 do_movement(); // 设置摄影机 cameraTarget = PVector.add(cameraPos, cameraFront); camera(cameraPos.x, cameraPos.y, cameraPos.z, cameraTarget.x, cameraTarget.y, cameraTarget.z, up.x, up.y, up.z); perspective(fov, aspect, zNear, zFar); // 绘制图形 for (int n = 0; n < cubesPos.length; n++) { pushMatrix(); // 分配模型网格位置 translate(cubesPos[n].x, cubesPos[n].y, cubesPos[n].z); pushMatrix(); // 单个模型矩阵变换 translate(width/2, height/2, -100.0); rotateX(angle[n]); rotateY(angle[n]*0.3); rotateZ(angle[n]*0.05); randomSeed(n*100); angle[n] += 0.005 * random(0, 1); scale(200); // 绘制单个网格物体 //fill(255, 127, 39); for (int i = 0; i < face.length; i++) { beginShape(); texture(tex); // x , y , z , u , v vertex(ver[int(face[i].x)].x, ver[int(face[i].x)].y, ver[int(face[i].x)].z, uv[i][0].x, uv[i][0].y); vertex(ver[int(face[i].y)].x, ver[int(face[i].y)].y, ver[int(face[i].y)].z, uv[i][1].x, uv[i][1].y); vertex(ver[int(face[i].z)].x, ver[int(face[i].z)].y, ver[int(face[i].z)].z, uv[i][2].x, uv[i][2].y); endShape(TRIANGLES); } popMatrix(); popMatrix(); } // 打印信息 text("w、s、a、d - Move the camera.\nPress the mouse - turn the camera.", 10,10); } 好啦这样程序就完工啦! 你可以自己摆弄下cube的位置分布。用鼠标滚轮控制摄影机fov什么的。
    转载请注明原文地址: https://ju.6miu.com/read-1303085.html
    最新回复(0)