Inline comments should start with a capital letter:
GLFWwindow* setupGL()
{
...
// Lock cursor to window
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
...
}
Use classic Doxygen/Javadoc syntax for comments outside of functions. This can be tedious to write and maintain. Use only where absolutely needed.
Note: One-liner Doxygen syntax (///
) is preferred for simple stuff, ex:
/// Converts polar coordinates to cartesian
glm::vec3 getPosOnCircle(float degrees, float radius)
{
...
}
General syntax as described in https://developer.lsst.io/cpp/api-docs.html:
/**
* A test class.
*
* A more elaborate class description.
*/
class Doxygen_Test
{
public:
/**
* Supported coordinate systems for flux-conserving transformations.
*
* These values are used in arguments to various functions in this package.
* Unless otherwise stated, these functions do not validate whether the data
* set makes sense in the "from" coordinates.
*/
enum class CoordType
{
/// Untransformed detector coordinates.
PIXEL,
/// Idealized detector coordinates after applying a distortion correction.
WARP_PIXEL,
/// Equatorial J2000.0 coordinates.
SKY_WCS
};
/**
* A constructor.
*
* A more elaborate description of the constructor.
*/
Doxygen_Test();
/**
* A destructor.
*
* A more elaborate description of the destructor.
*/
~Doxygen_Test();
/**
* A function taking two arguments and returning an integer value.
*
* @param a An integer argument.
* @param s A constant character pointer.
* @see Doxygen_Test()
* @see ~Doxygen_Test()
* @return The test results.
*/
int testFirst(int a, const char* s);
/**
* Returns the cube transforms for a letter.
*
* @param character Should be uppercase.
* @return The cube transforms, or nullptr if the letter isn't supported.
*/
const std::vector<glm::mat4>* getCubes(char character);
double sum(std::vector<double>& const values);
/// Must be clamped between 0 and 360
float rotationDegrees;
/**
* Must be normalized.
*
* Will behave erratically near the Z axis because of gimbal lock.
*/
glm::vec3 rotationAxis;
};
Code is often self-explanatory, for example this comment would be unnecessary:
/// Returns sum of elements
double sum(std::vector<double>& const values);
Same for:
void setColor(glm::vec3& color)
{
GLuint location = glGetUniformLocation(programID, "color");
// Sets uniform
glUniform3fv(location, 1, glm::value_ptr(color));
}
Spaces.
camelCase
for everything.
The functions in the Module
class use PascalCase
for emphasis but they're the only exceptions.
protected
is preferred over private
because it's difficult to predict if a class will ever be extended or not. protected
is more future-proof.
Keep reference and pointer qualifiers glued to the type:
Node* localRoot;
Node& localRoot;
When defining a function that receives a memory location, a reference should be used instead if the location should logically never be null:
void addChild(Node& child)
{
children.push_back(&child);
}
Braces should open on a new line:
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
overallSuccess = false;
}
Braces should be skipped if all branches are one-liners:
if (key == GLFW_KEY_P)
polygonMode = RenderMode::Point;
else if (key == GLFW_KEY_L)
polygonMode = RenderMode::Line;
else
polygonMode = RenderMode::Triangle;
However if most branches are not one-liners, then they should be kept for all branches for visual consistency.
To avoid, generally.
nullptr
.
Use static_cast
. For example when converting an int to a float:
float f = static_cast<float>(i);
Use enum class
for its ::
scoped syntax:
enum class DrawMode
{
INDEXED,
VERTEX
};
DrawMode mode = DrawMode::INDEXED;
The using
keyword should be avoided for std
. std::
should be used explicitly for the standard library.
Same thing for glm::
.
Other namespaces judged on a case-by-case basis.
A trailing zero is preferred for whole numbers: 1.0f
instead of 1.f
Member functions and properties should be declared in the following order:
- Constructor (if any)
- Destructor (if any)
- Public functions
- Public properties
- Protected functions
- Protected properties
In a .cpp
file, implement functions in the same order that they were declared in the .h
file.
There should be a blank line after public:
and protected:
.
There should be a #pragma once
line at the top of each .h
file.
For simplicity and readability, classes can be implemented entirely in .h
files without accompanying .cpp
files.
However if a circular #include
arises, move one of the implementations entirely to a new .cpp
file and forward declare.
#include
headers in the following order:
- If in a
.cpp
file, include its corresponding.h
file followed by a blank space - GLM or GLFW (sorted alphabetically)
- Standard library (sorted alphabetically)
- Our files (sorted alphabetically)
#include <glm/glm.hpp>
#include <vector>
#include "mesh.h"
#include "shader.h"
There should be exactly 1 blank line at the end of each text file.
For long strings such as shaders use the following syntax:
const char* vertexSrc = R""""(
#version 330 core
...
void main()
{
vertexColor = aColor;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * aPos;
}
)"""";
Align its indentation to the start of the line like above, otherwise the extra indentation would be included in the string.