简介:《GAMES101 作业0》PDF是一份面向GAMES101课程学员的作业环境配置指南,专门解决作业0中虚拟机使用与开发环境搭建的入门问题。资源为单个PDF文档,大小约874KB,内容系统梳理了VirtualBox虚拟机安装、虚拟硬盘文件下载与挂载、Guest Additions增强功能安装、作业框架双向传输与编辑等关键环节,并补充了Visual Studio Code开发工具、C++常见编译错误及Eigen库使用的简明提示。该文档步骤清晰、要点集中,能帮助计算机图形学初学者减少环境配置的弯路,快速进入作业编程阶段。已有433人学习下载,适合需要按GAMES101作业规范完成环境准备的学生参考。
1. Games101 作业0 PDF:环境就绪比会写代码更早决定你的作业结果
看到“Games101-作业0pdf”这个资源标题,很多人第一反应是:作业0也要这么兴师动众?我的第一反应恰好相反——这门课真正劝退学生的,往往不是图形学算法本身,而是在第一周就被虚拟机、Eigen和CMake三件事连环卡住。作业0的目的非常朴素:让你在统一、封闭的Ubuntu环境里跑通一次完整的“编写—编译—运行—提交”流程。这份PDF的价值不在于那两道数学题,而在于它把后续所有作业的地基提前铺好了。适合刚拿到课程资源、还没装过Linux虚拟机、对C++工程构建缺乏概念的人;老手也能从中确认镜像文件、Guest Additions和Eigen头文件路径这几个关键坑点。
2. 搭建虚拟机开发环境:挂载预置镜像与双向拖放的完整操作
2.1 为什么用虚拟硬盘而不是自己装Ubuntu
课程直接给了一个.vdi虚拟硬盘文件,而不是让你自己下载Ubuntu镜像再一步步安装。这个设计有一个很实际的考量:所有学生的开发环境被强行统一了。自己装系统很容易出现“我这能编译你那儿不行”的尴尬局面,而.vdi文件里已经预装好了VS Code、Sublime、Eigen库以及编译链,拿到手就能直接进入作业本身,不需要在环境配置上消耗意志力。
常见的误区是把这个.vdi文件当成普通压缩包直接解压到桌面就完事。实际上.vdi是VirtualBox的磁盘镜像格式,必须通过虚拟机软件挂载后才能作为硬盘使用。如果你用的是VMware,直接挂载.vdi还会遇到格式兼容问题。课程指定的是VirtualBox,这个选择本身也降低了后续动作的不确定性——VirtualBox对.vdi的支持是原生的,少一层转换就少一个不可控的变量。
2.2 新建虚拟机的关键参数与操作顺序
打开VirtualBox,点击“新建”,需要按顺序确认几个参数。类型选择Linux,版本选择Ubuntu-64bit,这两项决定了虚拟机的硬件模拟行为,选错会导致启动阶段直接黑屏或无法识别磁盘。内存建议给2GB,这是课程文档里明确给出的推荐值,低于1GB运行时能感觉到明显的卡顿,尤其是后续作业涉及矩阵运算和图像显示时。
比较容易被忽略的是创建过程中的磁盘选择步骤。VirtualBox默认会引导你创建一个新的虚拟硬盘,这里要手动切换为“使用已有的虚拟硬盘文件”,然后定位到你解压出来的那个.vdi文件。选中之后点击创建,虚拟机会自动把该磁盘作为系统盘启动。首次启动时,系统会以图形界面进入Ubuntu登录界面,登录口令在课程文档里已经给出。这里我一般会做一件额外的事:启动完成后先给虚拟机拍一个快照,之后无论Guest Additions装坏还是Eigen路径搞乱,都能一条命令退回干净状态。
2.3 主机与虚拟机文件互通:开启双向拖放
作业框架在主机上,代码要在虚拟机里编译,第一步就是解决文件传输问题。VirtualBox默认禁止主机和虚拟机之间的拖放操作,需要手动打开。进入虚拟机后,点击顶部菜单栏的“设备”,找到“拖放”,设置为“双向”。这个操作同时作用于两个方向——从主机拖文件进虚拟机,以及从虚拟机拖文件回主机。
实际操作中我建议把“双向拖放”和“共享粘贴板”一起打开,后者能让你在主机的浏览器里复制一段代码,直接粘到虚拟机里的VS Code中。如果拖放功能拖不了文件,最常见的原因是Guest Additions没有安装成功,这个模块的作用就是补全鼠标指针集成、屏幕自适应、剪贴板共享、拖放这些增强接口。没有它,虚拟机只能用最基础的方式运行,文件传输会变得非常痛苦。
3. Guest Additions 增强功能与文件传输:两条安装路径和失败处理
3.1 增强功能是什么,不装会怎样
Guest Additions是VirtualBox给虚拟机提供的一组驱动和系统服务,装上之后才能实现屏幕分辨率自适应、鼠标无缝进出窗口、剪贴板和拖放共享。对作业流程来说,最直接的影响就是你能不能高效地把代码从主机挪进虚拟机,以及在虚拟机里编辑代码时屏幕分辨率是否正常。不装的话,虚拟机分辨率可能锁定在一个很小的窗口,界面操作体验很差,拖放功能也会失效——而这恰恰是作业0想要走通的环节。
安装前需要保证虚拟机系统已经正常启动并登录进入桌面。整个过程分为两步:先挂载安装镜像,再执行安装脚本。如果系统提示“安装增强功能”菜单项是灰色的,说明VirtualBox没有识别到当前虚拟机的光驱设备,常见做法是检查虚拟机的存储设置里是否挂载了VBoxGuestAdditions.iso。
3.2 图形界面与命令行两种安装方式
图形界面安装是首选路径。在虚拟机窗口的菜单栏点击“设备”,选择“安装增强功能”,系统会自动挂载一个虚拟光驱,随后弹出的文件管理器里找到VBoxLinuxAdditions.run,右键选择“在终端中运行”。终端执行时需要用sudo提权,因为安装过程要向系统目录写入驱动文件。
如果图形界面方式失败,比如没有任何弹窗或者安装过程中途报错,可以走命令行。在虚拟机内按Ctrl+Alt+T打开终端,逐条执行:
# 创建光驱挂载点目录,-p 参数表示目录不存在时自动创建 sudo mkdir -p /media/cdrom # 自动识别并挂载虚拟光驱,-t auto 让系统自动判断文件系统类型 sudo mount -t auto /dev/cdrom /media/cdrom # 进入挂载后的光驱目录 cd /media/cdrom # 执行安装脚本,脚本会编译内核模块并注册系统服务 sudo sh VBoxLinuxAdditions.run第一条命令里的/media/cdrom是一个约定俗成的挂载点,目录名本身没有特殊含义,也可以换成/mnt/cdrom等路径。第二条命令中的/dev/cdrom是光驱设备节点,如果你的虚拟机上光驱被识别为其他设备名,可以通过lsblk查看实际设备名再替换。最后一条.run脚本会检查内核头文件、编译模块,执行完重启虚拟机即可生效。
安装完成后重启,再次进入虚拟机,窗口分辨率应当能跟随窗口大小自动调整,拖放功能也能正常使用了。一个简单的自检方式:把主机的任意文件拖进虚拟机桌面,如果出现复制进度条,说明Guest Additions已经生效。
3.3 安装失败时的日志定位思路
Guest Additions安装失败时,终端里通常会输出一段错误信息,最常见的是Unable to find the sources of your current Linux kernel。这个错误的原因是系统缺少编译内核模块所需的头文件,也就是linux-headers包没有安装。解决方法是在终端里执行一次系统包更新,安装对应内核版本的头文件后重新运行安装脚本。
另一个值得留意的现象是:安装过程没有报错,但重启后拖放功能依然不可用。这种情况多半是把安装脚本执行了一半就关掉了终端,模块虽然复制到系统里但没完成编译。解决办法是重新执行一次sudo sh VBoxLinuxAdditions.run,看到Building the VirtualBox Guest Additions kernel modules这个阶段跑完才算真正成功。
4. 作业0核心计算:齐次坐标旋转平移与Eigen矩阵实现
4.1 先理解题目在问什么
作业0的数学要求是:给定点P=(2,1),先将它绕原点逆时针旋转45度,再平移(1,2),计算变换后点的坐标,且必须用齐次坐标完成。这两个操作在笛卡尔坐标系下不能直接用同一个2x2矩阵表达——旋转是线性变换可以写进矩阵,平移却需要在矩阵之外单独加一个向量。齐次坐标的意义就是把平移也纳入矩阵乘法,用一个3x3矩阵统一表达“先旋转再平移”的复合变换。
这一步的关键是变换顺序。题目要求“先旋转,再平移”,对应到矩阵乘法上就是平移矩阵左乘旋转矩阵,也就是T * R,作用到点P上变成了T * (R * P)。如果写反成R * T,计算出来的结果是先平移再旋转,和题目要求完全不符。很多人在这一步翻车,不是不会Eigen,而是矩阵乘法的顺序理解反了。
4.2 用Eigen构造旋转矩阵和平移矩阵
在虚拟机的VS Code里新建main.cpp,这里推荐使用Eigen::Matrix3f构造变换矩阵。旋转矩阵中需要用到角度转弧度,注意C++的三角函数统一使用弧度制,把45度写成45.0f * pi / 180.0f,而不是直接写45。
#include <iostream> #include <cmath> #include <eigen3/Eigen/Core> int main() { // 定义点 P,齐次坐标表示为 (x, y, 1) Eigen::Vector3f p(2.0f, 1.0f, 1.0f); // 用 acos(-1) 计算圆周率,避免 M_PI 在不同编译环境下的兼容性问题 const float pi = std::acos(-1.0f); float theta = 45.0f * pi / 180.0f; // 旋转矩阵 R:绕原点逆时针旋转 theta 角度 Eigen::Matrix3f R; R << std::cos(theta), -std::sin(theta), 0.0f, std::sin(theta), std::cos(theta), 0.0f, 0.0f, 0.0f, 1.0f; // 平移矩阵 T:沿 x 方向平移 1,沿 y 方向平移 2 Eigen::Matrix3f T; T << 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 2.0f, 0.0f, 0.0f, 1.0f; // 先旋转再平移:T * (R * p),顺序不能写反 Eigen::Vector3f result = T * R * p; // 输出结果,result.z() 保持为 1,验证齐次坐标没有被破坏 std::cout << result.x() << ", " << result.y() << std::endl; return 0; }这段代码里有两个值得留意的设计。第一,pi通过std::acos(-1.0f)求出来,而不是直接使用M_PI,因为M_PI在一些编译环境下并不是标准C++库默认提供的宏,直接写会导致编译报错。第二,旋转矩阵第三行设置为0, 0, 1,这是齐次坐标的固定格式,表示这个矩阵不会改变点的w分量。
理论计算上,P=(2,1)逆时针旋转45度后坐标变为(0.7071, 2.1213),再平移(1,2)后最终坐标为(1.7071, 4.1213)。运行程序后如果看到这个结果说明代码正确。这个例子也解释了一个细节:为什么平移矩阵的第三列放的是(1,2,1)——齐次坐标下点的w分量是1,矩阵的第三列会直接与该分量相乘,从而把平移量叠加到结果上。
4.3 Eigen向量与矩阵的基础操作
作业0的框架代码里还有一段Vector和Matrix的示例,用于让你熟悉Eigen的基本操作。Eigen::Vector3f是三维浮点向量,Eigen::Matrix3f是3x3浮点矩阵。矩阵元素按列优先存储,初始化时用逗号初始化器按行填充。示例中矩阵i的内容是[1,2,3; 4,5,6; 7,8,9],通过i << 1.0, 2.0, ...逐行写入。
Eigen的运算符重载做得比较全面,向量加、向量数乘、矩阵加、矩阵乘都直接用+、*符号完成。有一点需要区分:v * 3.0f是向量数乘,i * j是矩阵乘法,i * v是矩阵乘向量,这些都是不同的运算,但Eigen的运算符重载会根据左右类型自动判定行为。
这个过程中最容易踩的坑是在CMakeLists里忘记加Eigen头文件路径。Eigen是一个header-only库,不需要链接任何.so或.a文件,但编译器必须能在头文件搜索路径中找到eigen3这个目录。Ubuntu系统默认安装在/usr/include/eigen3,如果你的系统自定义过安装路径,需要在CMakeLists中显式指定。
5. 构建链路排查:CMake编译、链接错误与段错误的定位清单
5.1 从main.cpp到可执行文件的完整命令流
作业0要求用CMake构建项目,而不只是直接g++ main.cpp。表面上这是一个工程习惯问题,实际是在为后续大型作业铺路——后面几份作业都涉及多文件编译和外部库依赖,靠一条g++命令管理不现实。
先创建项目目录并写入main.cpp和CMakeLists.txt,然后在main.cpp所在目录下打开终端:
# 创建构建目录,build 目录存放中间文件和最终可执行文件 mkdir build # 进入构建目录 cd build # 生成 Makefile,.. 表示使用上一级目录中的 CMakeLists.txt cmake .. # 编译并链接生成可执行文件 make # 运行程序,Transformation 是 CMakeLists.txt 中指定的可执行文件名 ./Transformationmkdir build这一步的作用是把所有编译中间产物隔离在一个子目录里,避免污染源码目录。cmake ..中的..非常关键——CMake会读取上一级目录下的CMakeLists.txt作为项目配置,用.或直接用cmake .在某些配置下会导致缓存路径混乱。make会调用Makefile里定义的编译命令,输出可执行文件到当前构建目录。
如果改动了CMakeLists.txt的内容,需要重新执行cmake ..再make,只跑make不会自动感知构建配置的变更。
5.2 常见错误的定位方法和处理顺序
编译过程中出现的报错信息分成三类,处理方式完全不同。
第一类是编译错误。编译器会直接告诉你哪个文件哪一行出了什么问题,通常涉及语法错误、未定义的变量、类型不匹配。这类错误最友好,信息明确,逐个修正即可。
第二类是链接错误,典型表现是undefined reference to xxx。这说明编译阶段已经通过,但链接器找不到某些函数或符号的实现。一个常见的原因是CMakeLists.txt里没有把需要的源码文件加入add_executable,另一个则是缺少头文件路径。对于Eigen库,由于是header-only,不存在链接库的问题,报出undefined reference多半是别的模块没写进CMakeLists。
第三类是运行时错误,最常见的是Segmentation Fault。这类报错不会告诉你具体位置,只告诉你程序访问了非法内存。常见原因包括数组越界、指针未初始化、递归栈溢出。作业0的代码非常简单,遇到段错误先检查是不是矩阵尺寸用错了,比如对Vector2f取下标2。
5.3 CMakeLists.txt链接Eigen的写法
很多人在这一步卡住是因为不知道Eigen库在CMake里怎么引入。Eigen是纯头文件模板库,不需要target_link_libraries,只需要提供头文件搜索路径。课程虚拟机里Eigen已经安装在系统标准路径,但为了不受系统环境影响,建议在CMakeLists里显式加上:
cmake_minimum_required(VERSION 3.10) project(Transformation) # 使用 C++11 标准编译 set(CMAKE_CXX_STANDARD 11) # 添加 Eigen 头文件搜索路径,Ubuntu 系统默认安装在 /usr/include/eigen3 include_directories("/usr/include/eigen3") # 将 main.cpp 编译为名为 Transformation 的可执行文件 add_executable(Transformation main.cpp)这段配置里,include_directories负责把头文件路径传给编译器。如果你的系统里Eigen安装在/usr/local/include/eigen3,把这里的路径替换掉就行。判断当前系统Eigen安装在哪,可以执行dpkg -L libeigen3-dev查看完整文件列表,或者直接用find /usr -name "Core" | grep eigen搜索。
改完CMakeLists.txt后,记得重新执行一次cmake ..和make,否则改动不会生效。
6. 提交前验证清单和一套提速习惯
提交作业前,值得花五分钟跑一遍完整的验证流程,避免提交上去的包根本不能运行。第一,确认可执行文件能在构建目录下正常启动,输出1.70711, 4.12132附近的结果。第二,确认提交的压缩包里包含main.cpp和CMakeLists.txt,并且不包含build目录——提交源码而不是编译产物。第三,在虚拟机里重新执行一次cmake .. && make,全程无报错才算真正干净。
一个容易被忽略的细节是:源码文件需要从虚拟机的目录里拖回主机再提交,如果直接提交虚拟机里的文件路径,评分端拿到的是一个无法打开的文件。拖回后先双击确认能正常解压,再上传。
平时我自己还有个习惯:每次在一台新机器上搭完环境,都会把整个虚拟机目录复制一份作为工作副本,原始镜像保留不动。这个习惯帮我避免了至少两次“装坏系统后重头再来”的血泪经历。从那以后我每次拿到带虚拟硬盘的课程资源,第一件事都是先复制一份备份,再开始配置Guest Additions和编译环境。备份的成本远低于重装的时间,特别是当你不知道下一步操作会不会把环境搞坏的时候,这几乎是所有虚拟环境相关的课程作业里最值的后悔药。希望帮到你。
本文还有配套的精品资源,点击获取