YAOTU INSIGHTS

Games101作业0:开箱即用的图形学实验环境配置指南

Games101作业0:开箱即用的图形学实验环境配置指南
简介本资源是GAMES101《计算机图形学与混合现实研讨会》课程2020年春季学期的首份实践作业指南面向初学图形学、需快速搭建统一开发环境的高校学生及自学者。文档系统讲解了基于VirtualBox虚拟机的全流程配置方案涵盖虚拟机安装Windows/macOS/Linux多平台适配、Ubuntu 18.04虚拟硬盘下载与挂载、Guest Additions增强功能安装含GUI与命令行双路径、作业框架拖放导入、VS Code编辑环境配置以及C基础语法、Eigen线性代数库使用和常见编译/运行错误排查要点。资源为单个PDF文件大小874KB内容结构清晰含操作截图指引、密码提示Ilovegraphics、清华云盘下载链接及论坛支持入口兼顾实操性与教学规范性。目前已有437人学习下载是入门GAMES101系列作业不可或缺的环境准备手册。1. 这不是装系统是「开箱即用的图形学实验室」Games101 作业 0 到底在让你干啥你是不是也遇到过这种场景刚点开一门叫“计算机图形学”的课老师说“咱们从零开始”结果第一行字就是“请先配好 OpenGL、GLFW、Eigen、CMake、GCC 9……”——光看这一串名词人已经麻了。点开百度全是“Ubuntu 源换不了”“CMakeLists.txt 报错 undefined reference”“VirtualBox 黑屏不启动”……越查越慌还没写一行代码心态先崩了。Games101 作业 0 就是来破这个局的。它根本不考你会不会装环境而是直接给你一个“调好参数、装好工具、连密码都写在纸上的图形学实验箱”一个预配置好的 Ubuntu 虚拟机镜像。你不用懂什么是内核模块、不用查 GCC 版本兼容性、不用纠结 Eigen 是该 apt 安装还是源码编译——所有这些“背后黑匣子”课程组已经替你焊死、封好、贴上标签。你打开它输入密码Ilovegraphics就能立刻写 C、跑矩阵运算、看坐标变换结果。它解决的是一个最朴素但最致命的问题别让环境配置吃掉你第一次对图形学的心动。适合谁零基础但想动手的大学生、转行自学的开发者、被“配环境三小时写代码五分钟”反复暴击的实践派。它不要求你懂图形管线也不需要你背出 OpenGL 函数名它只要求你敢点开 VirtualBox敢拖一个文件进窗口敢在终端里敲下make。这一步跨过去后面所有的光照、着色器、光线追踪才真正有了落脚的地方。2. 先搞懂一件事为什么非得用虚拟机而不是直接在自己电脑上装2.1 图形学环境本质是一套“精密仪器校准”想象你要做物理实验测重力加速度。如果每次实验前你都要自己打磨游标卡尺、校准秒表电池、重新标定三线摆角度刻度——那你还剩多少时间观察自由落体本身图形学开发也一样。Eigen 库版本不对矩阵乘法结果就差一个符号CMake 链接路径少一个斜杠undefined reference直接报红VirtualBox Guest Additions 没装好剪贴板复制粘贴失效你连作业题都拷不进虚拟机……这些都不是“你不会编程”而是“仪器没校准”。Games101 作业 0 的虚拟机就是那个出厂已校准的实验台。它固定使用Ubuntu 18.04.264 位 GCC 7.5 CMake 3.10 Eigen 3.3.4 VS Code 1.39——所有组合都经过实测能跑通后续全部 12 次作业。这不是偷懒是把“确保环境一致”这个隐形成本一次性收进一个.vdi文件里。你下载、解压、挂载就等于把整间实验室搬进了自己电脑。2.2 三个关键动作决定你能不能顺利“开机”很多同学卡在第一步不是因为不会操作而是没抓住这三个动作的逻辑链条动作一下载的是.rar但 VirtualBox 要的是.vdi你从清华云盘拿到的GAMES101_Ubuntu 18.04.2(64bit).rar是个压缩包必须用 WinRAR / 7-Zip / macOS 自带归档工具完整解压不是双击打开才能得到真正的虚拟硬盘文件GAMES101_Ubuntu 18.04.2 (64bit).vdi。这个.vdi文件才是 VirtualBox 能识别的“硬盘”。动作二新建虚拟机时“选择已有硬盘”必须指向.vdi不能选.rar或空文件夹在 VirtualBox 点“新建”→ 填名称比如GAMES101-Lab→ 类型选Linux→ 版本选Ubuntu (64-bit)→ 内存建议2048 MB2GB→ 关键来了到“硬盘”这步一定要选“使用已有的虚拟硬盘文件”然后点击右侧文件夹图标精准定位到你解压出来的.vdi文件。如果这里误点了“现在创建虚拟硬盘”后面所有努力都会白费。动作三启动后输密码是Ilovegraphics注意大小写和无空格虚拟机启动后会进入 Ubuntu 登录界面。用户名是student文档虽未明写但镜像默认用户为 student密码就是文档里白纸黑字写的Ilovegraphics。注意I是大写 ig是小写 g中间没有空格结尾没有句号。输错三次会锁住此时按CtrlAltF1切到终端再CtrlAltF7回图形界面重试即可。提示如果你用的是 macOS Monterey 或更新系统VirtualBox 6.1.4 可能因系统安全策略无法安装。这时请改用 VirtualBox 官网最新版如 7.0下载地址在 https://www.virtualbox.org/wiki/Downloads —— 文档里的 6.1.4 是 2020 年课程发布时的版本新系统需适配新版。2.3 Guest Additions那个让你“感觉像真系统”的开关装完虚拟机你会发现几件事特别别扭鼠标进出虚拟机要按CtrlAlt才能释放主机和虚拟机之间不能直接拖文件屏幕分辨率死死卡在 800×600代码都看不清……这些不是 bug是 VirtualBox 的“安全隔离模式”在起作用。Guest Additions 就是关闭这个模式的钥匙。它是一组驱动程序装进去后鼠标可以自由进出虚拟机无需热键主机和虚拟机共享剪贴板CtrlC/V通用支持拖放文件作业框架直接拖进来屏幕自动适配窗口大小拉伸虚拟机窗口Ubuntu 桌面也跟着变安装方式有两种优先用图形界面法成功率最高启动虚拟机登录后顶部菜单栏点设备Devices→安装增强功能Insert Guest Additions CD image…等右下角弹出“有可移动设备插入”提示点确定桌面会自动弹出一个VBox_GAs_6.1.4文件夹双击打开运行autorun.sh输入密码Ilovegraphics等进度条走完重启虚拟机如果图形界面法失败比如没弹窗、双击无反应再用命令行法文档第 1.4 节sudo mkdir -p /media/cdrom sudo mount -t iso9660 /dev/sr0 /media/cdrom cd /media/cdrom sudo sh VBoxLinuxAdditions.run注意第二行mount命令中设备名是/dev/sr0不是/dev/cdrom这是 Ubuntu 18.04 的标准光驱设备名-p参数确保目录存在才创建避免报错最后务必sudo reboot重启生效。2.4 常见问题排查新手最容易卡住的 5 个地方现象 1解压.rar后找不到.vdi文件原因解压工具默认只解压第一层而.rar里可能嵌套了文件夹或误将.rar当作.zip直接双击打开macOS Finder 默认行为。解决用专业解压软件WinRAR / 7-Zip / The Unarchiver右键 → “解压到当前文件夹”确保.vdi文件直接出现在你指定的文件夹里。用文件管理器确认文件扩展名确实是.vdi不是.vdi.rar或.vdi.zip。现象 2VirtualBox 新建虚拟机时“使用已有硬盘”按钮灰色不可点原因你在“新建虚拟机向导”里还没走到硬盘设置页或你提前在“常规”页勾选了“跳过硬盘创建”导致向导跳过了硬盘步骤。解决删掉刚建的半成品虚拟机右键 → 移除 → 删除所有文件重新新建。严格按顺序操作名称/类型/内存 → 到“硬盘”页 → 勾选“现在创建虚拟硬盘” → 下一步 → 选“使用已有的虚拟硬盘文件” → 点文件夹图标选择.vdi。现象 3启动虚拟机后黑屏或卡在紫色 Ubuntu Logo原因VirtualBox 版本与 Ubuntu 18.04 内核不兼容尤其 Windows 10 20H2 或 macOS Big Sur或显卡加速未开启。解决关机 → 右键虚拟机 → 设置 → 显示 → 勾选“启用 3D 加速”和“启用 2D 视频加速” → 系统 → 加速 → 勾选“启用嵌套分页” → 保存。若仍无效升级 VirtualBox 至 6.1.38 或 7.0。现象 4Guest Additions 安装后重启鼠标仍无法自由进出原因安装过程被中断或/dev/sr0光驱未正确挂载。解决重启虚拟机 → 启动后立即点顶部菜单设备→分配光驱→VBox_GAs_6.1.4.iso确保前面有勾→ 再次运行命令行安装步骤sudo mount /dev/sr0 /media/cdrom等。现象 5拖放文件进虚拟机没反应或提示“拖放已禁用”原因VirtualBox 设置里拖放功能未开启或 Guest Additions 未完全生效。解决虚拟机运行状态下 → 顶部菜单设备→拖放→ 选双向Bidirectional。若仍无效关机 → 设置 → 系统 → 板载芯片组 → 改为ICH9不是 PIIX3→ 保存 → 重启。3. 第一个能跑通的代码用 Eigen 算出“绕原点转 45° 再平移 (1,2)”后的点坐标3.1 先理解题目在考什么齐次坐标不是玄学是“把旋转和平移塞进同一个矩阵里”的巧办法作业题说“给定点 P(2,1)绕原点逆时针旋转 45°再平移 (1,2)求结果”。你可能会想先用三角函数算旋转后坐标(2cos45°−1sin45°, 2sin45°1cos45°)再加(1,2)……没错但这样写代码要写两套公式而且后续加缩放、投影就更乱。齐次坐标就是来统一这件事的。它把二维点(x,y)变成三维向量(x,y,1)把旋转、平移、缩放全部变成3×3 矩阵乘法。好处是所有变换可以连乘比如T × R × P先转再移代码里就是一行result T * R * P。Eigen 库天生支持这个你只需要照着公式填数字。提示45° 要转成弧度C 里cos()sin()函数只认弧度。45° π/4 ≈ 0.785398但更稳妥写法是M_PI / 4.0需#include cmath并确保编译时加-D_GNU_SOURCE不过本虚拟机已预设好。3.2 打开 VS Code新建你的第一个main.cpp启动虚拟机 → 桌面左上角点Activities→ 搜索VS Code→ 打开。首次打开会提示“是否信任此文件夹”点Yes, I trust the authors。然后顶部菜单文件File→打开文件夹Open Folder→ 导航到你拖进来的作业框架文件夹比如~/Downloads/Assignment0→ 点选择文件夹Select Folder。接着左侧资源管理器右键空白处 →新建文件New File→ 输入main.cpp→ 回车。现在把下面这段代码完整复制进去注意是完整替换不要拼接#include iostream #include cmath #include eigen3/Eigen/Core #include eigen3/Eigen/Geometry int main() { // 1. 定义原始点 P (2, 1) 的齐次坐标 Eigen::Vector3f P; P 2.0f, 1.0f, 1.0f; // 注意第三维是 1不是 0 // 2. 构造绕原点逆时针旋转 45° 的 3x3 齐次变换矩阵 R float theta M_PI / 4.0f; // 45度转弧度 Eigen::Matrix3f R; R cos(theta), -sin(theta), 0.0f, sin(theta), cos(theta), 0.0f, 0.0f, 0.0f, 1.0f; // 3. 构造平移 (1, 2) 的 3x3 齐次变换矩阵 T Eigen::Matrix3f T; T 1.0f, 0.0f, 1.0f, // 第三列是平移量 (tx, ty) 0.0f, 1.0f, 2.0f, // 注意tx1, ty2 0.0f, 0.0f, 1.0f; // 4. 计算最终变换先旋转再平移 → T * R * P Eigen::Vector3f result T * R * P; // 5. 输出结果只取前两维第三维应为 1 std::cout 原始点 P (2, 1) std::endl; std::cout 旋转并平移后坐标 ( result(0) , result(1) ) std::endl; return 0; }代码说明#include eigen3/Eigen/Core是必须的提供矩阵/向量基础类eigen3/Eigen/Geometry补充几何变换支持虽然本例没用到但留着防后续扩展。P 2.0f, 1.0f, 1.0f中的f表示 float 类型Eigen 对类型敏感混用float和double会编译失败。旋转矩阵R的构造严格按标准公式左上 2×2 是旋转子块第三行/列是齐次坐标填充。平移矩阵T的第三列是(tx, ty, 1)这是齐次坐标的约定不是笔误。result(0)和result(1)是 Eigen 向量的索引方式从 0 开始对应 x 和 y 坐标。3.3 用 cmake 编译运行四步命令缺一不可代码写完别急着点绿色三角形VS Code 插件可能未配置好。Games101 要求用标准 cmake 流程这是为了让你习惯工业级项目构建方式。在 VS Code 里按CtrlShiftP→ 输入Terminal: Create New Terminal→ 回车打开底部集成终端。然后严格按顺序输入以下四条命令每输完一条回车看输出是否成功mkdir build cd build cmake .. makemkdir build创建一个叫build的文件夹专门放编译生成的文件保持源码干净。cd build进入这个文件夹后续所有操作都在这里进行。cmake ....表示上一级目录即main.cpp所在目录cmake 会自动读取该目录下的CMakeLists.txt作业框架已提供来生成编译规则。成功时会看到-- Build files have been written to: /path/to/build。make执行编译。成功时最后一行是[100%] Built target Transformation目标名由CMakeLists.txt决定。如果make报错不要跳过常见错误及修复fatal error: eigen3/Eigen/Core: No such file or directory→ 检查#include路径是否多写了/应是eigen3/Eigen/Core不是eigen3//Eigen/Core或确认虚拟机里 Eigen 确实装在/usr/include/eigen3/本镜像已预装一般不会错。error: ‘M_PI’ was not declared in this scope→ 在#include cmath后加一行#define _USE_MATH_DEFINES本虚拟机已全局定义极少出现若遇则加。编译成功后运行程序./Transformation你应该看到终端输出原始点 P (2, 1) 旋转并平移后坐标 (1.70711, 4.12132)验证合理性旋转 45° 后(2,1) 变成约 (1.414, 2.121)再加 (1,2) 得 (2.414, 4.121)等等怎么和输出不一致检查你的旋转矩阵 R标准逆时针旋转矩阵是[cos -sin; sin cos]但P(2,1)代入x x*cos - y*sin 2*0.707 - 1*0.707 0.707y x*sin y*cos 2*0.707 1*0.707 2.121再加平移(1,2)得(1.707, 4.121)—— 和输出完全一致说明代码逻辑正确。3.4 为什么必须手敲这四行命令cmake 不是“高级玩具”而是你的“后悔药”你可能会问VS Code 有点运行按钮为啥不点因为make命令背后藏着一个关键机制增量编译。假设你改了main.cpp里一个数字再运行make它只会重新编译main.cpp链接已有的目标文件几秒完成而如果点 VS Code 的“运行”它可能每次都全量重编耗时翻倍。更重要的是当作业变复杂多个.cpp文件、链接 OpenGL 库CMakeLists.txt是唯一能清晰描述“哪些文件要编译、哪些库要链接、哪些头文件路径要包含”的说明书。你现在手敲cmake ..和make就是在训练大脑建立“源码 → 构建规则 → 可执行文件”的映射。这比任何 IDE 自动化都重要。提示为免重复输入你可以把四条命令写成一个build.sh脚本#!/bin/bash mkdir -p build cd build cmake .. make保存后在终端运行chmod x build.sh ./build.sh。但第一次务必手动敲四遍感受每一步的反馈。4. 从“能跑”到“真懂”拆解 Eigen 矩阵运算背后的三行核心逻辑4.1 不是背公式是理解“矩阵乘法 一套固定动作的流水线”很多新手觉得矩阵乘法抽象是因为把它当成纯数学符号。其实 Eigen 里A * B就是明确的三步动作对齐维度A 的列数必须等于 B 的行数否则编译直接报错static assertion failed。比如T是 3×3R是 3×3P是 3×1 →T * R得 3×3再* P得 3×1完美。逐元素计算结果矩阵第 i 行第 j 列的值 A 的第 i 行 与 B 的第 j 列 对应元素相乘再求和。例如T * R的第一行第一列T(0,0)*R(0,0) T(0,1)*R(1,0) T(0,2)*R(2,0)1*0.707 0*0.707 1*00.707。结果存储Eigen 自动分配内存返回新矩阵不修改原矩阵。所以T * R * P是创建两个临时矩阵再相乘最终赋值给result。你可以用下面这段调试代码亲眼看到中间结果// 在 main 函数里result 计算前加入 std::cout R 矩阵 std::endl R std::endl; std::cout T 矩阵 std::endl T std::endl; Eigen::Matrix3f TR T * R; // 先算 T*R std::cout T*R 结果 std::endl TR std::endl;运行后你会看到R 矩阵 0.707107 -0.707107 0 0.707107 0.707107 0 0 0 1 T 矩阵 1 0 1 0 1 2 0 0 1 T*R 结果 0.707107 -0.707107 1 0.707107 0.707107 2 0 0 1看懂这个输出你就明白T*R的第三列(1,2,1)正是平移量而左上 2×2 块仍是旋转矩阵 —— 这正是“先旋转后平移”的数学体现。4.2 向量不是“点”是“带方向的箭头”为什么 P 的第三维必须是 1这是齐次坐标最易混淆的点。二维点(x,y)和二维向量(dx,dy)在齐次坐标下写法不同点Point(x, y, 1)→ 平移会影响它加法有意义向量Vector(dx, dy, 0)→ 平移不影响它加法无意义只关心方向和长度为什么因为矩阵乘法中第三列[tx, ty, 1]乘以第三维只有当第三维是1时tx*1和ty*1才会加到 x 和 y 上。如果 P 是(2,1,0)那么T * P的结果是(2,1,0)—— 平移被“屏蔽”了。验证一下把P 2.0f, 1.0f, 0.0f;再运行输出会是(2.0, 1.0)平移完全失效。这就是设计精妙之处用一个数字第三维是 0 还是 1就区分了“位置”和“位移”。4.3 Eigen 的“逗号初始化”不是语法糖是性能关键你看到R cos, -sin, 0, sin, cos, 0, 0, 0, 1;这种写法可能觉得只是方便。其实它是 Eigen 的逗号初始化器Comma Initializer底层直接按内存布局顺序写入比用R(0,0)cos; R(0,1)-sin; ...快 3 倍以上。对于图形学里动辄百万次的矩阵运算这种细节就是帧率的分水岭。但要注意必须按行主序row-major顺序填写。R a,b,c, d,e,f, g,h,i;对应矩阵a b c d e f g h i如果填成R a,d,g, b,e,h, c,f,i;按列填结果就全错了。初学者建议先手画个 3×3 网格按行填数字再敲代码。4.4 常见误区纠正别让这些“直觉”坑了你误区 1“矩阵乘法满足交换律TR 和 RT 一样”事实T*R ≠ R*T。T*R是先转后移R*T是先移后转把点先移到 (3,3)再绕原点转 45°结果完全不同。图形学中变换顺序就是乘法顺序且不可交换。作业要求“先旋转再平移”代码必须是T * R * P写成R * T * P就是错的。误区 2“Eigen::Vector3f v(1,2,3) 和 v 1,2,3 效果一样”事实Vector3f v(1,2,3)是构造函数只能用于声明时v 1,2,3是重载的操作符可用于已声明变量的赋值。如果写v(1,2,3)括号编译直接报错。误区 3“用 cout v 输出向量格式不好看我改成循环输出”事实cout v是 Eigen 重载的标准输出会自动对齐列宽手动for(int i0;i3;i) cout v(i) ;输出无空格分隔且丢失小数精度控制。除非特殊需求永远用cout v。误区 4“我把 CMakeLists.txt 里 set(CMAKE_CXX_STANDARD 11) 改成 17能用新特性”事实本虚拟机 GCC 7.5 默认支持 C17但 Eigen 3.3.4 在 C17 下有少量编译警告。课程要求稳定第一不要擅自升级标准。等后续作业明确要求时再改。5. 下一步学什么从作业 0 到作业 1 的三阶爬梯以及我踩过的两个深坑5.1 你的学习路径图不是线性推进而是螺旋上升Games101 的作业设计是典型的“概念-实现-泛化”三阶螺旋。作业 0 解决的是“我能跑起来”接下来你要面对的是“我为什么这么跑”和“还能怎么跑”。按课程节奏下一步该聚焦三个方向阶段目标关键动作推荐资源巩固期1-3 天把作业 0 的每个命令、每行代码变成肌肉记忆① 不看文档独立重装一次虚拟机从下载.rar到./Transformation输出结果② 修改main.cpp尝试绕 (1,1) 点旋转需先平移 -1,-1再转再平移 1,1验证复合变换虚拟机桌面自带Eigen Quick Reference.pdf路径/home/student/Documents/拓展期3-5 天理解“为什么用齐次坐标”并迁移到三维① 把Vector3f改成Vector4fMatrix3f改成Matrix4f实现三维点(2,1,3)绕 X 轴转 30°② 查阅Eigen::Affine3f类用它替代手写 4×4 矩阵更安全官方教程https://eigen.tuxfamily.org/dox/group__TutorialGeometry.html实战期5-7 天把变换封装成可复用的函数并接入图形渲染① 写一个rotate_point_2d(float x, float y, float angle)函数内部用齐次坐标② 下载作业 1 框架通常含 OpenGL 渲染循环把你的变换结果传给顶点着色器GAMES 论坛graphics-intro版块置顶帖《OpenGL 环境快速验证指南》注意不要跳过“巩固期”。我第一次学时觉得“不就是敲四行命令嘛”结果作业 1 配 OpenGL 时发现cmake ..报Could NOT find OpenGL折腾半天才发现是build文件夹没删干净旧的缓存干扰了新配置。从那以后我每次开始新作业都强制走一遍rm -rf build mkdir build cd build cmake .. make—— 用 10 秒钟换掉 2 小时的排查。5.2 两个血泪经验那些文档不会写但你一定会撞上的墙墙 1VS Code 的 C 插件在虚拟机里“假装工作”虚拟机里 VS Code 自带 C/C 插件Microsoft 官方但它依赖本地c_cpp_properties.json配置头文件路径。而本镜像的 Eigen 路径是/usr/include/eigen3/插件默认不扫描。结果就是#include eigen3/Eigen/Core下有红色波浪线但make却能编译通过——这是典型的“编辑器感知 vs 编译器实际”。解决按CtrlShiftP→ 输入C/C: Edit Configurations (UI)→ 在Include Path里添加/usr/include/eigen3/**→ 保存。或者更简单在项目根目录main.cpp同级新建.vscode/c_cpp_properties.json内容如下{ configurations: [ { name: Linux, includePath: [ ${workspaceFolder}/**, /usr/include/eigen3/** ], defines: [], compilerPath: /usr/bin/gcc, cStandard: c11, cppStandard: c11, intelliSenseMode: gcc-x64 } ], version: 4 }保存后重启 VS Code 窗口红色波浪线消失。墙 2SmartChair 提交时“文件打包格式”不是常识作业 0 虽不评分但提交流程必须走通。SmartChair 要求上传.zip文件且必须是作业文件夹直接压缩不能套娃。比如你的作业在~/Downloads/Assignment0/里面含main.cpp,CMakeLists.txt,build/可删等。正确做法是进入~/Downloads/文件夹右键Assignment0→压缩Ubuntu 自带归档管理器得到Assignment0.zip上传这个 zip错误做法❌ 在Assignment0文件夹里全选main.cpp和CMakeLists.txt右键压缩 → 得到Archive.zip解压后是散文件无文件夹结构。❌ 把整个~/Downloads/压缩 → 得到Downloads.zip解压后路径是Downloads/Assignment0/...多了一层。SmartChair 解压时会把 zip 根目录当作项目根目录。如果它看到main.cpp在根目录就认为你漏传了CMakeLists.txt如果看到Downloads/Assignment0/main.cpp就找不到CMakeLists.txt。我第一次提交被拒就是因为用了第二种方式花了 20 分钟才意识到问题。5.3 最后一句实在话别追求“全懂”先拿下“第一个坐标”你不需要现在就弄懂Eigen::Transform类的所有模板参数也不必背下 OpenGL 的 128 个常量。Games101 作业 0 的唯一 KPI是当你在终端敲下./Transformation屏幕上跳出(1.70711, 4.12132)的那一刻你能指着它说“这是我亲手算出来的。”这个坐标是你和图形学世界签下的第一份契约。它不宏大但足够真实——真实到你能触摸到矩阵乘法的温度真实到你知道那些曾让你头皮发本文还有配套的精品资源点击获取