<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Juan Guerrero</title>
    <description>The latest articles on Forem by Juan Guerrero (@thejuanguerrero).</description>
    <link>https://forem.com/thejuanguerrero</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3717165%2F6a1c5033-d8e8-45f2-9125-b719addec63b.jpg</url>
      <title>Forem: Juan Guerrero</title>
      <link>https://forem.com/thejuanguerrero</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/thejuanguerrero"/>
    <language>en</language>
    <item>
      <title>From Python to OpenGL: A Modern, Cross-Platform Survival Guide for OSU CS-450</title>
      <dc:creator>Juan Guerrero</dc:creator>
      <pubDate>Sat, 17 Jan 2026 21:56:35 +0000</pubDate>
      <link>https://forem.com/thejuanguerrero/from-python-to-opengl-a-modern-cross-platform-survival-guide-for-osu-cs-450-50pk</link>
      <guid>https://forem.com/thejuanguerrero/from-python-to-opengl-a-modern-cross-platform-survival-guide-for-osu-cs-450-50pk</guid>
      <description>&lt;p&gt;&lt;strong&gt;By Juan Guerrero&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This setup worked for me personally and is shared here to benefit others who might choose to follow it. This guide is based on my own experience in the class and is &lt;strong&gt;not&lt;/strong&gt; an enforced standard or the "official" way to do things in CS-450. Always refer to the official class resources for the specific requirements of your assignment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Shock of the New (Old)
&lt;/h2&gt;

&lt;p&gt;If you are an OSU student stepping into &lt;strong&gt;CS-450 (Introduction to Computer Graphics)&lt;/strong&gt;, you might be coming from a background of Python, Java, or web development. You're used to &lt;code&gt;pip install&lt;/code&gt;, useful error messages, and languages that manage memory for you.&lt;/p&gt;

&lt;p&gt;Suddenly, you are dropped into a world of pointers, segmentation faults, linker errors, and manual memory management. You visit the class resources page and see three different zip files: one for Windows (Visual Studio), one for Mac, and one for Linux. Each has its own build system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There is a better way.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This guide is designed to set up a &lt;strong&gt;unified, modern, cross-platform environment&lt;/strong&gt; that works comfortably on Windows, Linux, and Mac. We will replace manual configuration with tools that automate the hard stuff, allowing you to focus on the graphics.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Are We Doing This?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The Language: Why C++?
&lt;/h3&gt;

&lt;p&gt;You might ask, "Why can't I just use Python?"&lt;br&gt;
Graphics require performance. We need to talk directly to the GPU, manage memory down to the byte, and push millions of triangles per second. C++ gives us that control. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Memory:&lt;/strong&gt; In Python, variables are just references. In C++, you decide if a variable lives on the &lt;strong&gt;stack&lt;/strong&gt; (temporary, fast) or the &lt;strong&gt;heap&lt;/strong&gt; (permanent, manual).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Pointers:&lt;/strong&gt; You will pass addresses of data (&lt;code&gt;&amp;amp;data&lt;/code&gt;) to OpenGL, not the data itself. This avoids copying massive 3D models around memory, keeping things fast.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. The Problem: "It Runs on My Machine"
&lt;/h3&gt;

&lt;p&gt;The default class setup relies on "project files" (like &lt;code&gt;.sln&lt;/code&gt; for Visual Studio) or Makefiles. These are brittle. If you move a file, the project breaks. If you send your code to a partner on a Mac, it breaks.&lt;br&gt;
&lt;strong&gt;The Solution: CMake.&lt;/strong&gt;&lt;br&gt;
CMake is a meta-build system. You write a "recipe" (&lt;code&gt;CMakeLists.txt&lt;/code&gt;) describing your project, and CMake &lt;em&gt;generates&lt;/em&gt; the correct project files for whatever computer you are on. It creates the Visual Studio solution on Windows and the Makefile on Linux.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. The Nightmare: Dependency Management
&lt;/h3&gt;

&lt;p&gt;In Python, you type &lt;code&gt;pip install numpy&lt;/code&gt;.&lt;br&gt;
In C++, traditionally, you download a &lt;code&gt;.zip&lt;/code&gt; from a random website, extract it, guess where to put the &lt;code&gt;.h&lt;/code&gt; files, guess where to put the &lt;code&gt;.lib&lt;/code&gt; files, and pray the linker finds them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;On Windows:&lt;/strong&gt; We will use Microsoft's &lt;strong&gt;vcpkg&lt;/strong&gt;, a command-line package manager that integrates with Visual Studio.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;On Linux/Mac:&lt;/strong&gt; We will use system packages, but for tricky libraries (like outdated versions of GLUT), we can use &lt;strong&gt;CMake's FetchContent&lt;/strong&gt; to download and compile them on the fly.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Part 1: The Environment Setup
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Windows: Taming the Beast
&lt;/h3&gt;

&lt;p&gt;On Windows, we will use &lt;strong&gt;vcpkg&lt;/strong&gt; to install our libraries and &lt;strong&gt;Visual Studio 2022&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Install Git:&lt;/strong&gt; &lt;a href="https://git-scm.com/download/win" rel="noopener noreferrer"&gt;Download Git for Windows&lt;/a&gt;. We need this to clone the vcpkg repository.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Install vcpkg:&lt;/strong&gt;
Open PowerShell and run:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://github.com/microsoft/vcpkg.git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\vcpkg&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\vcpkg&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\bootstrap-vcpkg.bat&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\vcpkg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;integrate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; &lt;code&gt;bootstrap&lt;/code&gt; compiles the package manager itself. &lt;code&gt;integrate install&lt;/code&gt; tells Visual Studio "Hey, look in C:\vcpkg for libraries". This means you never have to manually add "Include Directories" again.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Install Graphics Libraries:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\vcpkg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;glew&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;freeglut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opengl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Linux &amp;amp; macOS: The Native Way
&lt;/h3&gt;

&lt;p&gt;On Unix systems, package managers are built-in. However, CMake assumes certain low-level libraries are present.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Linux (Fedora):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;cmake gcc-c++ glew-devel &lt;span class="se"&gt;\&lt;/span&gt;
    libXi-devel libXmu-devel libXext-devel libXrandr-devel libXxf86vm-devel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; We install &lt;code&gt;glew-devel&lt;/code&gt; and the X11 libraries, but we &lt;strong&gt;skip&lt;/strong&gt; the system &lt;code&gt;freeglut&lt;/code&gt;. As we'll see in Part 3.5, we will tell CMake to download and build a specific version of FreeGLUT to ensure it works perfectly with Wayland.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Linux (Ubuntu):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;cmake g++ libglew-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libxi-dev libxmu-dev libxext-dev libxrandr-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;macOS:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt; Install Homebrew: &lt;code&gt;brew.sh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;brew install cmake glew freeglut&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Part 2: The Editor - Neovim
&lt;/h2&gt;

&lt;p&gt;You can use Visual Studio 2022, but for a consistent experience across all OSs, I recommend &lt;strong&gt;Neovim&lt;/strong&gt;. It's a terminal-based editor that, when configured, is faster and more powerful than VS Code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Neovim for C++?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;LSP (Language Server Protocol):&lt;/strong&gt; We will hook Neovim up to specialized "Language Servers" that act like a brain for your editor. We need three specific ones for this class:

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;clangd&lt;/code&gt;:&lt;/strong&gt; The brain for C/C++. It provides autocomplete and real-time error checking.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;cmake-language-server&lt;/code&gt;:&lt;/strong&gt; Helps you write &lt;code&gt;CMakeLists.txt&lt;/code&gt; without typos.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;glsl_analyzer&lt;/code&gt;:&lt;/strong&gt; This is a life-saver for Projects 6 &amp;amp; 7. It provides syntax checking and autocomplete for the GLSL shader language.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Regex Block Editing:&lt;/strong&gt; You will often need to edit blocks of coordinate data.

&lt;ul&gt;
&lt;li&gt;  &lt;em&gt;Example:&lt;/em&gt; You have 50 lines that look like &lt;code&gt;v 1.0 2.0 3.0&lt;/code&gt;. You want to change them to &lt;code&gt;vertex(1.0, 2.0, 3.0);&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  In Neovim, you press &lt;code&gt;Ctrl-v&lt;/code&gt; to select the column, shift-I to insert text on &lt;em&gt;all lines at once&lt;/em&gt;, and escape to apply. It saves hours of typing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Speed:&lt;/strong&gt; It opens instantly. No loading splash screens.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Quick Setup (LazyVim)
&lt;/h3&gt;

&lt;p&gt;Configuring Vim from scratch is hard. Use &lt;strong&gt;LazyVim&lt;/strong&gt;, a pre-made configuration.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Install Neovim:&lt;/strong&gt; (Check your OS package manager).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Install LazyVim:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    git clone https://github.com/LazyVim/starter ~/.config/nvim
    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; ~/.config/nvim/.git
    nvim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Install C++ &amp;amp; Shader Tools:&lt;/strong&gt;
Inside Neovim, type the following command to install the brains:
&lt;code&gt;:MasonInstall clangd cmake-language-server glsl_analyzer&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Part 3: Modernizing the Code
&lt;/h2&gt;

&lt;p&gt;The class provides a file named &lt;code&gt;sample.cpp&lt;/code&gt; inside &lt;code&gt;Sample2022.zip&lt;/code&gt;. It works, but it's full of legacy &lt;code&gt;#ifdef&lt;/code&gt; code to handle platform differences manually. We are going to clean this up using CMake.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: The &lt;code&gt;CMakeLists.txt&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Create a file named &lt;code&gt;CMakeLists.txt&lt;/code&gt; next to your &lt;code&gt;sample.cpp&lt;/code&gt;. This file tells CMake how to build your program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cmake"&gt;&lt;code&gt;&lt;span class="nb"&gt;cmake_minimum_required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;VERSION 3.15&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;cs450_project&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_CXX_STANDARD 17&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Find the libraries automatically&lt;/span&gt;
&lt;span class="c1"&gt;# CMake looks for standard locations (and vcpkg locations)&lt;/span&gt;
&lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;OpenGL REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;GLEW REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;GLUT REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 2. Add all your C++ files here.&lt;/span&gt;
&lt;span class="c1"&gt;# NOTE: If you uncomment 'bmptotexture.cpp' in the code, you MUST add it here too!&lt;/span&gt;
&lt;span class="nb"&gt;add_executable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project
    sample.cpp
    &lt;span class="c1"&gt;# bmptotexture.cpp&lt;/span&gt;
    &lt;span class="c1"&gt;# loadobjmtlfiles.cpp&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Tell the compiler where the .h files are&lt;/span&gt;
&lt;span class="nb"&gt;target_include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project PRIVATE
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPENGL_INCLUDE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLEW_INCLUDE_DIRS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLUT_INCLUDE_DIRS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 4. Link the libraries to the executable&lt;/span&gt;
&lt;span class="c1"&gt;# This connects the actual compiled code (.lib or .a files) to your program&lt;/span&gt;
&lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project PRIVATE
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPENGL_LIBRARIES&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLEW_LIBRARIES&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLUT_LIBRARIES&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Fixing &lt;code&gt;sample.cpp&lt;/code&gt; Includes
&lt;/h3&gt;

&lt;p&gt;In C++, &lt;code&gt;#include&lt;/code&gt; literally pastes the file contents into your code. The old &lt;code&gt;sample.cpp&lt;/code&gt; uses local copies of headers (&lt;code&gt;"glew.h"&lt;/code&gt;). We want to use the system installed ones (&lt;code&gt;&amp;lt;GL/glew.h&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find this block in &lt;code&gt;sample.cpp&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#ifdef WIN32
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;windows.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#pragma warning(disable:4996)
#endif
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"glew.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;GL/gl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;GL/glu.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"glut.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Replace it with this:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ctype.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#define _USE_MATH_DEFINES
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Universal include block&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;GL/glew.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;GL/freeglut.h&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt; &lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// Note: freeglut.h includes GL/gl.h and GL/glu.h automatically&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;br&gt;
We use &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt; to tell the compiler "look in the system folders" (where vcpkg/brew put the files). We removed the &lt;code&gt;#ifdef WIN32&lt;/code&gt; because CMake handles platform differences for us.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 3: Fixing Initialization
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;main()&lt;/code&gt; function in &lt;code&gt;sample.cpp&lt;/code&gt; has a specific check for Windows to initialize GLEW. &lt;strong&gt;This is a trap.&lt;/strong&gt; Linux/Mac users using modern OpenGL profiles &lt;em&gt;also&lt;/em&gt; need to initialize GLEW.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Change the initialization code to:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Initialize GLEW on ALL platforms&lt;/span&gt;
    &lt;span class="n"&gt;GLenum&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glewInit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;GLEW_OK&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"glewInit Error: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;glewGetErrorString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; &lt;code&gt;glewInit&lt;/code&gt; loads the function pointers for OpenGL extensions. Without it, calling modern functions will cause a crash.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 3.5: Advanced CMake - The Robust "Wayland-Ready" Recipe
&lt;/h3&gt;

&lt;p&gt;The simple &lt;code&gt;CMakeLists.txt&lt;/code&gt; above works for many, but on modern Linux (Fedora/Ubuntu) with Wayland, system libraries can break.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Use this robust &lt;code&gt;CMakeLists.txt&lt;/code&gt; instead. It automatically downloads and patches a compatible version of FreeGLUT if you are on Linux, while using standard libraries on Windows/Mac.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy-Paste this into your &lt;code&gt;CMakeLists.txt&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cmake"&gt;&lt;code&gt;&lt;span class="nb"&gt;cmake_minimum_required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;VERSION 3.15&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;cs450_project&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;CMAKE_CXX_STANDARD 17&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;OpenGL REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;GLEW REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# --- Advanced Dependency Management ---&lt;/span&gt;
&lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;UNIX &lt;span class="nf"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;NOT APPLE&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="nb"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;FetchContent&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;ExternalProject&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Build FreeGLUT from source to ensure compatibility with modern Wayland desktops&lt;/span&gt;
  &lt;span class="c1"&gt;# and fix common header conflicts (Patch step)&lt;/span&gt;
  &lt;span class="nf"&gt;ExternalProject_Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    freeglut
    GIT_REPOSITORY https://github.com/freeglut/freeglut
    GIT_TAG &lt;span class="s2"&gt;"v3.6.0"&lt;/span&gt;
    PATCH_COMMAND sh -c &lt;span class="s2"&gt;"sed -i 's/^&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;(.*fgPlatformDestroy.*&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;)/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;1/' &amp;lt;SOURCE_DIR&amp;gt;/src/egl/fg_init_egl.h"&lt;/span&gt;
    CMAKE_ARGS -DFREEGLUT_BUILD_DEMOS=OFF -DFREEGLUT_BUILD_SHARED_LIBS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=&amp;lt;INSTALL_DIR&amp;gt; -DCMAKE_INSTALL_LIBDIR=lib
    BUILD_COMMAND cmake --build &amp;lt;BINARY_DIR&amp;gt;
    INSTALL_COMMAND cmake --install &amp;lt;BINARY_DIR&amp;gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Link against the locally built version&lt;/span&gt;
  &lt;span class="nf"&gt;ExternalProject_Get_Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;freeglut INSTALL_DIR&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;PROGRAM_FREEGLUT_LINK_LIBRARY &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INSTALL_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/lib/libglut.a&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INSTALL_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/include&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;else&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="c1"&gt;# On Windows/Mac, use the system or vcpkg installed GLUT&lt;/span&gt;
  &lt;span class="nb"&gt;find_package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;GLUT REQUIRED&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;PROGRAM_FREEGLUT_LINK_LIBRARY GLUT::GLUT&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# --- Project Files ---&lt;/span&gt;
&lt;span class="nb"&gt;add_executable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project
    sample.cpp
    &lt;span class="c1"&gt;# bmptotexture.cpp&lt;/span&gt;
    &lt;span class="c1"&gt;# loadobjmtlfiles.cpp&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# --- Include Directories ---&lt;/span&gt;
&lt;span class="nb"&gt;target_include_directories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project PRIVATE
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPENGL_INCLUDE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLEW_INCLUDE_DIRS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLUT_INCLUDE_DIRS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# --- Linking ---&lt;/span&gt;
&lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project PRIVATE
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OPENGL_LIBRARIES&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GLEW_LIBRARIES&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROGRAM_FREEGLUT_LINK_LIBRARY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Linux-specific: Link X11 libraries required by static FreeGLUT&lt;/span&gt;
&lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;UNIX &lt;span class="nf"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;NOT APPLE&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nb"&gt;add_dependencies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project freeglut&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;target_link_libraries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;my_project PRIVATE X11 Xi Xrandr Xxf86vm&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Auto-copy assets to build folder (if they exist)&lt;/span&gt;
&lt;span class="nb"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;EXISTS &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CMAKE_SOURCE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/models"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;COPY &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CMAKE_SOURCE_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/models"&lt;/span&gt; DESTINATION &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_BINARY_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;endif&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This script allows us to script complex compatibility layers, ensuring that "It works on my machine" translates to "It works on your Wayland machine too."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now, the magic of CMake. Instead of memorizing different commands for every OS, we follow a standard process: &lt;strong&gt;Configure&lt;/strong&gt;, &lt;strong&gt;Build&lt;/strong&gt;, &lt;strong&gt;Run&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: The Terminal (Linux, macOS, Windows PowerShell)
&lt;/h3&gt;

&lt;p&gt;This is the universal way to build C++ projects.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Create a Build Directory:&lt;/strong&gt;
We don't want to clutter our source code with temporary build files.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nb"&gt;mkdir &lt;/span&gt;build
    &lt;span class="nb"&gt;cd &lt;/span&gt;build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Configure (The "CMake" Step):&lt;/strong&gt;
Run CMake to look at your &lt;code&gt;CMakeLists.txt&lt;/code&gt; (in the parent directory, hence &lt;code&gt;..&lt;/code&gt;) and generate the actual build files (Makefiles).
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    cmake ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;If this fails, it means CMake couldn't find a library. Check your &lt;code&gt;CMakeLists.txt&lt;/code&gt; or install the missing package.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Build:&lt;/strong&gt;
Now we tell CMake to compile the code.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    cmake &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The &lt;code&gt;.&lt;/code&gt; tells CMake to build the project in the current directory.&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Run:&lt;/strong&gt;
If the build succeeded, you will see an executable file.
&lt;strong&gt;Linux/Mac:&lt;/strong&gt; You must prefix the command with &lt;code&gt;./&lt;/code&gt; to tell the shell "run the program in &lt;em&gt;this&lt;/em&gt; folder", not a system command.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./my_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows (PowerShell):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\Debug\my_project.exe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option B: Visual Studio 2022 (Windows)
&lt;/h3&gt;

&lt;p&gt;Visual Studio now supports CMake natively.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open the Folder:&lt;/strong&gt;&lt;br&gt;
Launch Visual Studio. Click &lt;strong&gt;"Open a Local Folder"&lt;/strong&gt; and select the folder containing your &lt;code&gt;CMakeLists.txt&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wait for Configuration:&lt;/strong&gt;&lt;br&gt;
Look at the "Output" window. You should see CMake scanning your system. It will find the libraries you installed with vcpkg automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run:&lt;/strong&gt;&lt;br&gt;
In the top toolbar, select &lt;code&gt;my_project.exe&lt;/code&gt; as the startup item and press &lt;strong&gt;F5&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Part 5: Managing Assets &amp;amp; Subdirectories
&lt;/h2&gt;

&lt;p&gt;In Python, you might just open &lt;code&gt;cat.jpg&lt;/code&gt;. In C++, where the program runs matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The "Current Working Directory" Trap
&lt;/h3&gt;

&lt;p&gt;When you run a program from Visual Studio, the "working directory" (where it looks for files) might be different from where your source code is. This means &lt;code&gt;fopen("models/cat.obj")&lt;/code&gt; might fail because the program is running inside &lt;code&gt;build/Debug/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The CMake Fix:&lt;/strong&gt;&lt;br&gt;
Add this to the end of your &lt;code&gt;CMakeLists.txt&lt;/code&gt; to automatically copy your assets folder to the build directory every time you compile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cmake"&gt;&lt;code&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;COPY models DESTINATION &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PROJECT_BINARY_DIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Fixing &lt;code&gt;loadobjmtlfiles.cpp&lt;/code&gt; for Subdirectories
&lt;/h3&gt;

&lt;p&gt;The provided class code for loading OBJ files (&lt;code&gt;loadobjmtlfiles.cpp&lt;/code&gt;) sometimes assumes textures are in the same folder as the executable. If your OBJ file refers to a texture &lt;code&gt;skin.bmp&lt;/code&gt;, but that file is actually in &lt;code&gt;models/skin.bmp&lt;/code&gt;, the loader will fail.&lt;/p&gt;

&lt;p&gt;We can fix this by updating the loader to be "path aware".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In &lt;code&gt;loadobjmtlfiles.cpp&lt;/code&gt;, find where &lt;code&gt;map_kd&lt;/code&gt; (diffuse texture) is parsed:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Original Code:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;tok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"map_kd"&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strtok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DELIMS&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// calls BmpToTexture(tok) directly&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Modernized C++ Fix:&lt;/em&gt;&lt;br&gt;
Use &lt;code&gt;std::filesystem&lt;/code&gt; to prepend the parent directory of the OBJ file to the texture filename.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;filesystem&amp;gt;&lt;/span&gt;&lt;span class="c1"&gt; // Add this at the top&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// ... inside the loop ...&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strcmp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"map_kd"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tok&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strtok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DELIMS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Construct the full path&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;filesystem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="n"&gt;texturePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tok&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;texturePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_parent_path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;texturePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;basePath&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;texturePath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert back to string for the old function&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;fullPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texturePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generic_string&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;BmpToTexture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c_str&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 6: Tips for the Python Developer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Compilation vs Interpretation
&lt;/h3&gt;

&lt;p&gt;In Python, if you have a syntax error on line 50, the program runs until line 49.&lt;br&gt;
In C++, the &lt;strong&gt;Compiler&lt;/strong&gt; reads your whole file first. If there is one typo, &lt;em&gt;nothing&lt;/em&gt; runs.&lt;br&gt;
Then, the &lt;strong&gt;Linker&lt;/strong&gt; combines your code with libraries. If you get "Undefined Symbol", it means you declared a function but didn't give the Linker the &lt;code&gt;.cpp&lt;/code&gt; file that contains it. Check your &lt;code&gt;add_executable&lt;/code&gt; list in CMake!&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Segfaults (The Silent Killer)
&lt;/h3&gt;

&lt;p&gt;If your program crashes instantly without an error message, you likely have a &lt;strong&gt;Segmentation Fault&lt;/strong&gt;. This usually means you tried to access a list item that doesn't exist (like &lt;code&gt;arr[10]&lt;/code&gt; in a list of size 5) or used a pointer that points to nothing (&lt;code&gt;NULL&lt;/code&gt;).&lt;br&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; Use a debugger. In Visual Studio, it will pause exactly where the crash happens and show you the bad variable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Setting up C++ graphics environments used to be a rite of passage involving pain and suffering. With &lt;strong&gt;CMake&lt;/strong&gt; and &lt;strong&gt;vcpkg&lt;/strong&gt;, it becomes a repeatable, scriptable process. You have now graduated from "It runs on my machine" to "It runs anywhere."&lt;/p&gt;

&lt;p&gt;Good luck with CS-450. May your framerates be high and your compile times low!&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Official CS-450 Class Resources Page:&lt;/strong&gt; &lt;a href="https://web.engr.oregonstate.edu/~mjb/cs450/" rel="noopener noreferrer"&gt;https://web.engr.oregonstate.edu/~mjb/cs450/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>beginners</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
