<?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>DEV Community: Manuel Mateo</title>
    <description>The latest articles on DEV Community by Manuel Mateo (@yekyam).</description>
    <link>https://dev.to/yekyam</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%2F479690%2Fec0b0730-9e80-4ceb-b0a2-00ed5d826699.jpeg</url>
      <title>DEV Community: Manuel Mateo</title>
      <link>https://dev.to/yekyam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yekyam"/>
    <language>en</language>
    <item>
      <title>Quick PSA: Programming is Difficult</title>
      <dc:creator>Manuel Mateo</dc:creator>
      <pubDate>Sun, 22 Oct 2023 08:59:42 +0000</pubDate>
      <link>https://dev.to/yekyam/quick-psa-programming-is-difficult-35o2</link>
      <guid>https://dev.to/yekyam/quick-psa-programming-is-difficult-35o2</guid>
      <description>&lt;p&gt;For some reason, I see a lot of beginners post something like this online: "I've been programming for a month now and it's still difficult. Is programming right for me?" &lt;/p&gt;

&lt;p&gt;Newsflash: Programming &lt;em&gt;is hard&lt;/em&gt;. Learning to program &lt;em&gt;is hard&lt;/em&gt;. In fact, &lt;em&gt;any skill is hard&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Let's take our statement from earlier and replace it with an instrument. Let's read it out together: "I've been [playing] the violin for a month now and it's still difficult. Is [playing] the violin right for me?"&lt;/p&gt;

&lt;p&gt;To be frank, the statement now sounds kind of ridiculous. Unless you're a prodigy, of course the violin is still difficult, it's an instrument that requires years of practice. &lt;/p&gt;

&lt;p&gt;Programming is no different. It's a skill. If you want to be good at programming, it requires years of hard work.&lt;/p&gt;

&lt;p&gt;I think the reason why beginner programmers feel "stuck" is because the progress they make isn't immediately obvious. Let's go back to our violin example: our beginner violinist would have no difficulty in knowing what a good violinist sounds like, and there's a clear benchmark they can compare themselves to. It's not too difficult to hear when a violinist messes up a note, rushes a piece, or has a scratchy tone.&lt;/p&gt;

&lt;p&gt;However, our beginner programmer has no clear benchmark. It's part of the reason why companies have a difficult time creating a good interview process: there's no clear, easy way to distinguish the quality between two programmers. To do so, you'd have to take a deep dive into their projects, methods, ability to break down problems, etc. Even then, it's still not easy, and there's a lot of nuances to consider. &lt;/p&gt;

&lt;p&gt;That's not to say I don't empathize; every programmer has been there before. Every programmer has stared at a screen for hours and felt like they were deciphering a set of ancient texts. Every programmer has felt frustrated out of their mind, only to solve the problem days later. We've all been there, and &lt;em&gt;it's okay to feel frustrated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yes, programming is hard, but it's not impossible. Stick with it, and good luck. &lt;/p&gt;

&lt;p&gt;There's a wonderful article by Peter Norvig about how to &lt;a href="https://norvig.com/21-days.html"&gt;teach yourself programming in ten years&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
    </item>
    <item>
      <title>Formalizing C Patterns: The Case for C++</title>
      <dc:creator>Manuel Mateo</dc:creator>
      <pubDate>Sun, 16 Apr 2023 17:34:56 +0000</pubDate>
      <link>https://dev.to/yekyam/formalizing-c-patterns-the-case-for-c-481o</link>
      <guid>https://dev.to/yekyam/formalizing-c-patterns-the-case-for-c-481o</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Online, I see a lot of discourse surrounding C and C++. It makes sense; both languages are related, and they fit very similar niches. C programmers typically describe C++ as bloated, overcomplicated, obtuse, and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://harmful.cat-v.org/software/c++/linus"&gt;Here's one of the most famous examples of a C programmer arguing against C++, by one of the most famous programmers of all time: Linus Torvalds&lt;/a&gt;. As seen in Torvalds' rant, one key piece missing from these discussions are concrete, technical arguments. Although Torvalds is a far better programmer than I am, his argument features charged language with non-concrete examples.&lt;/p&gt;

&lt;p&gt;This article serves as a way to document my own thoughts on the subject matter, explicitly states concrete arguments, and is a time capsule for future me to look back on.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Take
&lt;/h2&gt;

&lt;p&gt;C++ can do everything that C can, but the opposite is not true.&lt;/p&gt;

&lt;p&gt;In online discussions, people tend to forget that C++ is the natural evolution of C. If C is bulbasaur, C++ is ivysaur. Because C++ did not come out of thin air, and because it does not aim to replace C, C++ borrows, formalizes, and improves plenty of common C techniques and paradigms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formalizing?
&lt;/h2&gt;

&lt;p&gt;C++ wasn’t created in a vacuum. It was created after years of C programming, meaning C++ had a lot of experience in what patterns worked and what didn’t. It moved these design patterns into formal language features instead of letting the users hand roll them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This means that good C code tends to be a more primitive version of good C++ code.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generic Objects - C
&lt;/h2&gt;

&lt;p&gt;Imagine I wanted to create a library to represent a two element vector. So, I create a struct containing two integer elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typedef struct vec2_t
{
    int x; 
    int y;
} Vec2;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome, I can now represent a vector in my code.&lt;/p&gt;

&lt;p&gt;But wait, wouldn’t it be useful to define some common operations? &lt;/p&gt;

&lt;p&gt;For brevity, we’ll only implement addition, but you get the idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vec2 add(Vec2 v1, Vec2 v2)
{
    Vec2 result = {0, 0};
    result.x = v1.x + v2.x;
    result.y = v1.y + v2.y;
    return result;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But wait, what if I want to support floats too? Or long ints? Or doubles? &lt;/p&gt;

&lt;p&gt;I could do some void* voodoo, but macros would work here too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define DECL_VEC2(typename, type) \
typedef struct typename##_t { \
    type x, y;\
} typename; \
\
typename typename##_add(typename v1, typename v2) { \
    typename result;\
    result.x = v1.x + v2.x;\
    result.y = v1.y + v2.y;\
    return result;\
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sweet, we’ve created a generic data structure to represent a two element vector. &lt;/p&gt;

&lt;p&gt;There's still an issue with this; what about &lt;code&gt;BigInt&lt;/code&gt;s? Or custom, fixed-point types? All of a sudden, I'd need to change my add operation function to accept a third &lt;code&gt;add&lt;/code&gt; function parameter.  &lt;/p&gt;

&lt;p&gt;Let’s identify what makes this good C code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have a good interface to interact with our structure&lt;/li&gt;
&lt;li&gt;Our structure is generic, meaning we can reuse our code without duplicating it for other types.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Generic Objects - C++
&lt;/h2&gt;

&lt;p&gt;C++ looks at what went right and formalizes it though the language and type system.&lt;/p&gt;

&lt;p&gt;The proper way of doing what we did in the C code would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;
struct Vec2
{
    T x, y;

    static Vec2&amp;lt;T&amp;gt; add(Vec2&amp;lt;T&amp;gt; v1, Vec2&amp;lt;T&amp;gt; v2)
    {
        Vec2&amp;lt;T&amp;gt; result;
        result.x = v1.x + v2.x;
        result.y = v1.y + v2.y;
        return result;
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have the help of the compiler to enforce type safety, and we don't have to deal with macros. C++ formalizes the generic object pattern into a built-in language feature.&lt;/p&gt;

&lt;p&gt;We also don't need to worry about passing in an &lt;code&gt;add&lt;/code&gt; function to our code. Why? Because operator overloading exists, and the &lt;code&gt;+&lt;/code&gt; operator should be defined for the type passed in. Using traits, we can even expand the code to check if &lt;code&gt;T&lt;/code&gt; implements the operator and report errors at compile time. Sweet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup - C
&lt;/h2&gt;

&lt;p&gt;Contrary to common belief, in C, &lt;code&gt;goto&lt;/code&gt; can actually be quite useful. &lt;/p&gt;

&lt;p&gt;When we're dealing with lots of memory allocations, often times we need a way to bail out of a function that has reached an error state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void some_func(const char* filename)
{
    FILE* file = fopen(filename, "r");
    if (!file)
        goto no_cleanup;

    fseek(file, 0L, SEEK_END);
    int file_size = ftell(file);

    char* buffer = malloc(file_size);
    if (!buffer)
        goto cleanup_file;
    FILE* out_file = fopen("outfile", "w");
    if (!out_file)
        goto cleanup_buffer;

    // no errors, free to continue with operations

cleanup_buffer:
    free(buffer);
cleanup_file:
    fclose(file);
no_cleanup:
    return;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we've organized our code in a way where we bail out of normal execution into our cleanup code if we encounter any problems. Without &lt;code&gt;goto&lt;/code&gt;, our code would be a mess of nested if statements, increasing depth every time we add a new resource.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup - C++
&lt;/h2&gt;

&lt;p&gt;C++ once again formalizes a good C pattern. In this case, the formalized pattern is called RAII.&lt;/p&gt;

&lt;p&gt;In C++, we can use RAII to cleanup objects at the end of their lifetimes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void some_func(const std::string&amp;amp; filename)
{
    std::fstream file(filename);
    if (!file)
        return;

    std::string buffer;

    std::fstream out_file("outfile");
    if (!out_file)
        return;

    // do stuff
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how here we don't have any cleanup labels. This is because (well formed, memory owning) objects have destructors that automatically handle cleanup for us. If we have an error state in our &lt;code&gt;do stuff&lt;/code&gt; area and need to bail out, we know our code will still cleanup our resources. &lt;/p&gt;

&lt;h2&gt;
  
  
  Data Hiding - C
&lt;/h2&gt;

&lt;p&gt;When reading files, it's useful to have a dynamic array of strings, with each index representing a line of the file. Let's look at a simple C example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typedef struct dynamic_string_array_t {
    int size;
    int capacity;
    char** arr;

} DynamicStringArray;

DynamicStringArray* DynamicStringArray_new(int capacity)
{
    DynamicStringArray* dyn_arr = malloc(sizeof(DynamicStringArray));

    dyn_arr-&amp;gt;size = 0;
    dyn_arr-&amp;gt;capacity = capacity;
    dyn_arr-&amp;gt;arr = malloc(sizeof(char*) * capacity);

    return dyn_arr;
}

bool DynamicStringArray_push_back(DynamicStringArray* this, char* str)
{
    if (this-&amp;gt;size == this-&amp;gt;capacity)
    {
        int new_size = this-&amp;gt;capacity * 2;
        this-&amp;gt;arr = realloc(this-&amp;gt;arr, new_size);
        this-&amp;gt;capacity = new_size;

        if(!this-&amp;gt;arr)
            return false;
    }
    this-&amp;gt;arr[this-&amp;gt;size] = str;
    this-&amp;gt;size++;
    return true;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, we'd need to define the other functions to operate on our dynamic array, but this works as a good example.&lt;/p&gt;

&lt;p&gt;There is an issue: there's nothing stopping another programmer from going in and misusing our dynamic array by changing the fields. If they directly change any of the fields in our struct, we'd run into potential UB or an outright crash. &lt;/p&gt;

&lt;p&gt;The most naive way to "hide" our data is to not hide it all. Instead, we could prefix our fields with a single underscore to indicate that the field should be considered private. However, that's not effective.&lt;/p&gt;

&lt;p&gt;The "best" way to hide our data is to make our struct an opaque struct. An opaque struct is one that completely hides all fields by only being accessible through a pointer.&lt;/p&gt;

&lt;p&gt;To accomplish this, we &lt;code&gt;typedef&lt;/code&gt; the name of the struct in our header file, and keep the implementation of the struct in the source file.&lt;/p&gt;

&lt;p&gt;DynamicStringArray.h:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typedef struct dynamic_string_array_t DynamicStringArray;

DynamicStringArray* DynamicStringArray_new(int);
boolean DynamicStringArray_push_back(DynamicStringArray*, char*);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DynamicStringArray.c:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typedef struct dynamic_string_array_t {
    int size;
    int capacity;
    char** arr;

} DynamicStringArray;

// rest of our function implementations

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Data Hiding - C++
&lt;/h2&gt;

&lt;p&gt;In C++, the default way is easy: just mark the fields as private, or in the case of a class, don't mark the fields public. This allows our code to be header only, which can be nice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DynamicStringArray
{
    int size;
    int capacity;
    char** arr;

public:
    // define methods here
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Did you see the error?
&lt;/h2&gt;

&lt;p&gt;In the section "Data Hiding - C" I purposefully left a bug. Instead of allocating space and copying the contents of the &lt;code&gt;char*&lt;/code&gt; parameter, I directly stored the pointer into the array. This is a bug; there is no guarantee that the string is properly managed. If our dynamic array outlives the string, then the pointer would point to garbage memory. If the string is not null-terminated, that would also lead to potential bugs.&lt;/p&gt;

&lt;p&gt;In C++, we usually don't need to worry about string handling issues like this. Non-reference object parameters automatically call their respective copy constructors, meaning we wouldn't need to worry about copying our string. On top of that, &lt;code&gt;std::string&lt;/code&gt; manages the contents of our string, meaning we don't need to worry if the internal array is null-terminated or not (unless constructing from a char*).  &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;The list goes on, seriously. I could've talked about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signals and &lt;code&gt;errno&lt;/code&gt;, return codes vs Exceptions&lt;/li&gt;
&lt;li&gt;Custom pointer and size structs vs Spans&lt;/li&gt;
&lt;li&gt;Bit set macros vs std::bitset&lt;/li&gt;
&lt;li&gt;Compile time facilities&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;char vs std::string&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Etc, etc, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But at that point, this article would turn into a short book.&lt;/p&gt;

&lt;p&gt;I'd like to reiterate my earlier point: C++ can do everything that C can. If you take issue with any of these features, there's nothing forcing you to use them. C++ features are &lt;em&gt;opt in&lt;/em&gt;; if you don't want to use them, there's no penalty. Even if you use only 1 C++ feature, then it's worth the switch.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>c</category>
    </item>
    <item>
      <title>Dev Log: Extremely Basic OpenGL Renderer</title>
      <dc:creator>Manuel Mateo</dc:creator>
      <pubDate>Sun, 26 Feb 2023 22:57:36 +0000</pubDate>
      <link>https://dev.to/yekyam/dev-log-extremely-basic-opengl-renderer-i40</link>
      <guid>https://dev.to/yekyam/dev-log-extremely-basic-opengl-renderer-i40</guid>
      <description>&lt;h2&gt;
  
  
  Some Background
&lt;/h2&gt;

&lt;p&gt;Since the beginning of my programming journey, I’ve always been drawn to the idea of creating projects from the ground up with minimal third party code.&lt;/p&gt;

&lt;p&gt;One of those projects was to play around with graphics, and this time I actually stuck with it. &lt;/p&gt;

&lt;h2&gt;
  
  
  Starting the Project
&lt;/h2&gt;

&lt;p&gt;I decided to follow along the &lt;a href="https://learnopengl.com/" rel="noopener noreferrer"&gt;Learn OpenGL&lt;/a&gt; tutorial. Although I found it useful for code, some of its explanations weren't clicking with me.&lt;/p&gt;

&lt;p&gt;I was confused on how vertex array objects (VAOs) and vertex buffer objects (VBOs) fit together, and given that they're the fundamental building blocks of OpenGL, I was in a bad place. Eventually, afters tons of googling and youtube, it finally clicked.&lt;/p&gt;

&lt;p&gt;I think the reason I was struggling so much was because I didn't understand that VAOs and VBOs are fundamentally linked. See, VAOs not only hold the specified layout of VBOs, they also hold the VBO data itself. It's kind of weird (thanks state machine!), and newer versions of OpenGL separate out the formatting of the data and the actual binding of the data (see &lt;a href="https://github.com/fendevel/Guide-to-Modern-OpenGL-Functions#glvertexattribformat--glbindvertexbuffer" rel="noopener noreferrer"&gt;direct state access (DSA)&lt;/a&gt;). &lt;/p&gt;

&lt;h2&gt;
  
  
  Building out abstractions
&lt;/h2&gt;

&lt;p&gt;Once I understood that VAOs and VBOs can't be separated out (in OpenGL versions below 4.5), this made programming an abstraction around them fairly trivial. &lt;/p&gt;

&lt;p&gt;I started out with the most basic data, the vertex. I don't care about textures or even lighting for this first run at OpenGL, so for now my vertices contain only position information and color information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct Vertex
{
    std::array&amp;lt;GLfloat, 3&amp;gt; position;
    std::array&amp;lt;GLfloat, 3&amp;gt; color;

    // constructor and std::ostream&amp;amp; operator&amp;lt;&amp;lt; defined here
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! I had a way to represent a single vertex, but you can't do much with that. &lt;/p&gt;

&lt;p&gt;So, I created a class to represent a group of vertices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct Mesh
{
    std::vector&amp;lt;Vertex&amp;gt; vertices;

    // constructors
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's something missing. See, in OpenGL, because everything is defined as a set of triangles, sometimes you'll get some overlap. Imagine the face of a cube:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1-----2
|     |
|     |
3-----4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The two triangles that make up the face are: 123, 324.&lt;/p&gt;

&lt;p&gt;That's kind of a waste, right? We shouldn't have to define duplicate vertices. &lt;/p&gt;

&lt;p&gt;Luckily, OpenGL solves that by introducing element buffer objects (EBOs). EBOs hold indices, meaning that we don't need to duplicate our vertices in memory.&lt;/p&gt;

&lt;p&gt;So, the new &lt;code&gt;Mesh&lt;/code&gt; struct looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct Mesh
{
    std::vector&amp;lt;Vertex&amp;gt; vertices;
    std::vector&amp;lt;GLushort&amp;gt; indices;

    // constructors
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! I can now represent the vertices and indices of a mesh. &lt;/p&gt;

&lt;p&gt;But now I need a way to actually send these vertices and indices to OpenGL.&lt;/p&gt;

&lt;p&gt;So, I created a &lt;code&gt;Model&lt;/code&gt; class. This class represents a &lt;code&gt;Mesh&lt;/code&gt; and its OpenGL data too, including VBOs, VAO, and EBO.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Model
{
    Mesh m_mesh;
    GLuint m_vao;
    GLuint m_vbos[2];
    GLuint m_ebo;

    // constructors, convenience functions, destructor
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, I needed a way to actually draw the &lt;code&gt;Model&lt;/code&gt; to the screen and keep track of the models.&lt;/p&gt;

&lt;p&gt;I decided to create a &lt;code&gt;Renderer&lt;/code&gt; class to keep track of camera matrices and handle all of the drawing. That way, I could keep my &lt;code&gt;Model&lt;/code&gt; separate from the drawing code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Renderer
{
public:
    std::list&amp;lt;std::unique_ptr&amp;lt;Model&amp;gt;&amp;gt; models; 
    int mode; // GL_POINTS, GL_TRIANGLES, or GL_LINES
    // other members excluded for brevity, but shader is included

    // constructor

    // function to add model to models

    void draw_models()
    {
        // clear the screen, color buffer, and depth buffer
        // use the shader
        // setup view matrices
        // setup shader uniforms
        for (const auto&amp;amp; model : models)
        {
            glBindVertexArray(model-&amp;gt;m_vao);
            glDrawElements(mode, model-m_mesh.indices.size(), GL_UNSIGNED_SHORT, 0);
            glBindVertexArray(0);
        }
    }

};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Loading Models from Files
&lt;/h2&gt;

&lt;p&gt;I had the foundation of a renderer, but it's quite boring if I was staring at an empty screen the entire time.&lt;/p&gt;

&lt;p&gt;So, I decided to create a function to load a &lt;code&gt;.obj&lt;/code&gt; file into a &lt;code&gt;Model&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Luckily, the file format is fairly simple, it looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v 0.5. 0.5 0.5
...
vt 1.0 1.0
...
vn 1.0 1.0 1.0
...
f 1 2 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;v&lt;/code&gt; denotes the vertex positions (x, y, z).&lt;br&gt;
&lt;code&gt;vt&lt;/code&gt; denotes texture coordinates, which I ignored to keep things simple.&lt;br&gt;
&lt;code&gt;vn&lt;/code&gt; denotes the surface normals, which I also ignored.&lt;br&gt;
&lt;code&gt;f&lt;/code&gt; denotes the indices of the triangles.&lt;/p&gt;

&lt;p&gt;So, I created a function to loop through all of the lines and either add the vertices and indices to vectors. &lt;/p&gt;

&lt;p&gt;However, I did run into two subtle bugs that were easy to fix:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The indices are 0 indexed, not 1 indexed, so when adding the indices to the the vector I had to subtract 1.&lt;/li&gt;
&lt;li&gt;Some lines of the face actually define quads instead of triangles, so the line looks like:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f 1 2 3 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After fixing the two bugs, I had a passable &lt;code&gt;.obj&lt;/code&gt; loader I could use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finishing Touches
&lt;/h2&gt;

&lt;p&gt;Once that was done, I decided to add some command line arguments, mainly to specify the &lt;code&gt;.obj&lt;/code&gt; file to load, specify the mode to render with (GL_POINTS, GL_LINES, or GL_TRIANGLES), and the ability to change the camera's distance from the model.&lt;/p&gt;

&lt;p&gt;Here's the classic Utah teapot rendered as a wireframe:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9mhkunj9qxua3etdjts8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9mhkunj9qxua3etdjts8.png" alt="A wireframe render of the Utah teapot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/yekyam/SOGL-Renderer" rel="noopener noreferrer"&gt;Here’s the link to the GitHub repo.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts and Next Steps
&lt;/h2&gt;

&lt;p&gt;Overall, this was a fun project. It was nice to get something visual done, and I'm glad I finally understand how OpenGL work. &lt;/p&gt;

&lt;p&gt;I'm not particularly happy with the code, mainly the argument parsing and the raw &lt;code&gt;glfw&lt;/code&gt; calls I make in &lt;code&gt;main()&lt;/code&gt;, but I'm glad it works. &lt;/p&gt;

&lt;p&gt;Outside of &lt;code&gt;main()&lt;/code&gt;, I do think the abstractions I made over the vertices and OpenGL itself isn't too bad, and in a future renderer I'll probably work off of this foundation. &lt;/p&gt;

&lt;p&gt;There are two features I'd like to add to this renderer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ability to specify model color in the command line args&lt;/li&gt;
&lt;li&gt;Basic lighting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once (or if) I get those done, I think I'll leave the project as-is. It was a great learning experience, and it'll be interesting to see how any future renderers I make compare to this one.&lt;/p&gt;

&lt;p&gt;In the future, I'll probably try to look into Vulkan, I'm interested in the fact that the API --although much more verbose-- looks a whole lot cleaner than OpenGL.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tips for other OpenGL beginners
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Don't attempt to learn OpenGL if you don't know memory management and how pointers work, you will have a bad time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenGL 3.3 is a bad API due to its state machine. If possible, try to learn OpenGL 4.5+ (yes, I know tutorials are sparse, but it seems easier to learn)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VAOs and VBOs are linked due to the state machine architecture, there's no real way to separate them out.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opengl</category>
      <category>cpp</category>
    </item>
    <item>
      <title>The Key to C</title>
      <dc:creator>Manuel Mateo</dc:creator>
      <pubDate>Thu, 01 Dec 2022 04:35:34 +0000</pubDate>
      <link>https://dev.to/yekyam/the-key-to-c-n6i</link>
      <guid>https://dev.to/yekyam/the-key-to-c-n6i</guid>
      <description>&lt;h2&gt;
  
  
  C for Beginners?
&lt;/h2&gt;

&lt;p&gt;Let's be clear here: no matter the popularity, C is a difficult language for beginners. To truly understand C, beginners have to learn both about programming and hardware, two very deep and complex topics. &lt;/p&gt;

&lt;p&gt;In this article, I'll attempt to bridge the two.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some background: Types? What are they?
&lt;/h3&gt;

&lt;p&gt;A type is simply a description of a variable. More precisely, a type describes what operations can be performed with the given data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Key to C: Types are an Illusion
&lt;/h2&gt;

&lt;p&gt;To truly understand C, one must view an entire program in terms of operations on interpretations of raw data. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Operations on interpretations of raw data? What does that mean?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's break that down with an example: &lt;/p&gt;

&lt;p&gt;A &lt;code&gt;char&lt;/code&gt; isn't just a single character, it's an interpretation of the data one byte holds. For example, this block of code is perfectly valid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;char x = '2';
char y = '2';

char z = x + y;
printf("%d\n", (int)z); // Outputs '100'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, &lt;code&gt;char&lt;/code&gt; is just an interpretation of the data. Sure, most of the time, a &lt;code&gt;char&lt;/code&gt; refers to an actual character, but the only guarantee C gives us is that a char is exactly one byte. &lt;/p&gt;

&lt;p&gt;In the example code, I performed an operation (addition) on raw data, even though the data is interpreted as characters. In ASCII, '2' is represented by the decimal number 50. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Viewing types as illusions simplifies all of the more difficult topics in C.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sure, you can view an &lt;code&gt;int&lt;/code&gt; is a number, but then what is an &lt;code&gt;int*&lt;/code&gt;? It points to a number? What does that even mean?&lt;/p&gt;

&lt;p&gt;Or, you can view an &lt;code&gt;int&lt;/code&gt; is a (typically) 4 byte block of memory on the stack, and an &lt;code&gt;int*&lt;/code&gt; holds a number that is usually the address of a (typically) 4 byte block. &lt;/p&gt;

&lt;p&gt;Yes, it's a mouthful, but until this line of thinking becomes intuitive, it's important to break down components of a program in that manner to truly understand C.&lt;/p&gt;

&lt;p&gt;If C hasn't clicked for you yet, try viewing your programs in the way I've described. You'll surprise yourself! &lt;/p&gt;

</description>
      <category>c</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The Beginner's Axioms</title>
      <dc:creator>Manuel Mateo</dc:creator>
      <pubDate>Mon, 27 Sep 2021 16:05:12 +0000</pubDate>
      <link>https://dev.to/yekyam/the-beginner-s-axioms-2o88</link>
      <guid>https://dev.to/yekyam/the-beginner-s-axioms-2o88</guid>
      <description>&lt;h1&gt;
  
  
  The Zen of Python
&lt;/h1&gt;

&lt;p&gt;The Zen of Python is a collection of guidelines for writing software, primarily aims towards (you guessed it) Python. It's a short list, but its worth its weight in gold. The guidelines talk about issues like code structure and how a program should look.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Beginner's Axioms
&lt;/h1&gt;

&lt;p&gt;I thought it'd be fun to make my own list, which I dub &lt;em&gt;The Beginner's Axioms&lt;/em&gt;. Its a short list of guidelines I wish I could've handed to myself when I first started learning how to program.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Learn slowly, forget slowly&lt;/li&gt;
&lt;li&gt;Writing is better than reading.&lt;/li&gt;
&lt;li&gt;When reading, official is better than unofficial.&lt;/li&gt;
&lt;li&gt;Bad code is better than no code.&lt;/li&gt;
&lt;li&gt;Mistakes are better than no mistakes.&lt;/li&gt;
&lt;li&gt;The first step to fixing a problem is admission.&lt;/li&gt;
&lt;li&gt;Community is better than solitude.&lt;/li&gt;
&lt;li&gt;Comments, comments, comments.&lt;/li&gt;
&lt;li&gt;Experiment, experiment, experiment.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
    </item>
  </channel>
</rss>
