Code Style¶
Coding conventions and style guidelines for VulkanW3DViewer.
Formatting¶
Clang-Format¶
The project uses clang-format for automatic formatting. Configuration is in .clang-format.
Format all files:
Indentation¶
- 2 spaces for indentation
- No tabs
- No trailing whitespace
Line Length¶
- Soft limit: 100 characters
- Hard limit: 120 characters
Braces¶
Attach opening brace to statement:
Single-line bodies allowed for short statements:
Naming Conventions¶
Types¶
- Classes/Structs: PascalCase
- Enums: PascalCase
- Enum values: PascalCase or SCREAMING_CASE
Variables¶
- Local variables: camelCase
- Member variables: camelCase (no prefix)
- Constants: SCREAMING_CASE or kPascalCase
class Buffer {
vk::Buffer buffer; // Member: camelCase
size_t bufferSize;
void create() {
size_t alignedSize = ...; // Local: camelCase
}
};
constexpr uint32_t MAX_BONES = 256;
constexpr float kDefaultFov = 45.0f;
Functions¶
- Regular functions: camelCase
- Type traits/concepts: snake_case (STL convention)
void loadFile(const std::string& path);
glm::mat4 computeWorldMatrix(int boneIndex);
template<typename T>
concept is_numeric = std::is_arithmetic_v<T>;
Namespaces¶
- Lowercase:
w3d,render
Files¶
- Source files: snake_case.cpp
- Header files: snake_case.hpp
- Test files: test_snake_case.cpp
C++ Guidelines¶
Modern C++20¶
Use modern C++ features:
// Structured bindings
auto [width, height] = getWindowSize();
// Designated initializers
MeshHeader header{
.version = 4,
.numVertices = 100
};
// Range-based algorithms
std::ranges::sort(vertices);
// std::optional
std::optional<Mesh> loadMesh(const std::string& name);
// std::span for array views
void uploadVertices(std::span<const Vertex> vertices);
RAII¶
All resources must use RAII:
// Good: RAII wrapper
class Buffer {
vk::raii::Buffer buffer;
vk::raii::DeviceMemory memory;
public:
Buffer(VulkanContext& ctx, size_t size);
// Automatic cleanup via destructors
};
// Bad: Manual resource management
class Buffer {
VkBuffer buffer;
VkDeviceMemory memory;
public:
~Buffer() {
vkDestroyBuffer(device, buffer, nullptr); // Easy to forget
vkFreeMemory(device, memory, nullptr);
}
};
Const Correctness¶
Use const liberally:
class Mesh {
public:
const std::string& getName() const { return name; }
void setName(const std::string& newName) { name = newName; }
private:
std::string name;
};
void processMesh(const Mesh& mesh); // Const reference
Prefer References Over Pointers¶
// Good
void render(const Scene& scene);
Texture& getTexture(const std::string& name);
// Acceptable (optional/nullable)
Texture* findTexture(const std::string& name); // May return nullptr
Include Order¶
- Corresponding header (for .cpp files)
- Project headers
- Third-party headers
- Standard library
// mesh_parser.cpp
#include "mesh_parser.hpp" // 1. Corresponding header
#include "chunk_reader.hpp" // 2. Project headers
#include "types.hpp"
#include <glm/glm.hpp> // 3. Third-party
#include <algorithm> // 4. Standard library
#include <vector>
Include Guards¶
Use #pragma once:
Documentation¶
File Headers¶
Brief description at file start:
Function Comments¶
Document non-obvious behavior:
/// Loads a W3D file and parses all chunks.
/// @param path Path to the W3D file
/// @return Parsed W3D data, or empty on failure
/// @throws std::runtime_error on file read errors
W3DFile load(const std::filesystem::path& path);
Inline Comments¶
Explain "why", not "what":
// Flip V coordinate - W3D uses bottom-left origin, Vulkan uses top-left
v = 1.0f - v;
// Skip unknown chunks to maintain forward compatibility
reader.skip(chunkSize);
Error Handling¶
Exceptions¶
Use exceptions for errors that can't be handled locally:
Optional¶
Use std::optional for expected "not found" cases:
std::optional<Mesh> findMesh(const std::string& name) {
auto it = meshes.find(name);
if (it == meshes.end()) return std::nullopt;
return it->second;
}
Assertions¶
Use assert for programmer errors (debug only):
void setLOD(int level) {
assert(level >= 0 && level < lodCount); // Programmer error
currentLOD = level;
}
Performance¶
Avoid Unnecessary Copies¶
// Good
for (const auto& mesh : meshes) { ... }
// Bad
for (auto mesh : meshes) { ... } // Copies each mesh