Thank you for your interest in contributing to ModelViewer! We welcome contributions from the community, whether it's bug reports, feature requests, documentation improvements, or code contributions. This document provides guidelines and instructions for contributing to the project.
- Code of Conduct
- Getting Started
- Types of Contributions
- How to Report Bugs
- How to Suggest Features
- Development Setup
- Coding Standards
- Git Workflow
- Submitting Changes
- Pull Request Process
- Testing
- Documentation
- License
We are committed to providing a welcoming and inspiring community for all. Please read and adhere to our Code of Conduct:
- Be Respectful: Treat all contributors with respect and courtesy
- Be Inclusive: Welcome diverse perspectives and backgrounds
- Be Constructive: Provide helpful, actionable feedback
- Be Professional: Keep discussions focused on the project
- Report Issues: Use private channels to report violations
Unacceptable behavior includes harassment, discrimination, intimidation, and unwelcoming communication. Any violations will be addressed promptly.
Before contributing code, ensure you have:
- Git installed and configured
- CMake 3.15 or later
- Qt 6.8 or later
- Assimp 5.0.1 or later
- OpenCASCADE 7.9 or later
- OpenGL 4.6 compatible GPU
- A GitHub account
-
Fork the repository
# Visit https://github.com/sharjith/ModelViewer-Qt and click "Fork" -
Clone your fork
git clone https://github.com/YOUR-USERNAME/ModelViewer-Qt.git cd ModelViewer-Qt -
Add upstream remote
git remote add upstream https://github.com/sharjith/ModelViewer-Qt.git
-
Install dependencies (see README.md for platform-specific instructions)
-
Create a build directory
mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Debug make
-
Run tests (if available)
# Tests will be in the build directory
Help us identify and fix issues in the code.
Suggest enhancements and new functionality.
Improve README, API docs, comments, and guides.
Fix bugs, implement features, and improve code quality.
Share insights and participate in design discussions.
Create sample projects and learning materials.
- Check existing issues: Search GitHub Issues to avoid duplicates
- Try the latest version: The bug may already be fixed
- Check documentation: Verify it's not expected behavior
- Isolate the problem: Create a minimal reproducible example
When creating a bug report, include:
Title: Clear, descriptive summary
[BUG] Application crashes when loading STEP file with assemblies
Description: What you were doing when the bug occurred
Steps to Reproduce:
1. Open ModelViewer
2. Load a STEP file with nested assemblies
3. Expand the assembly tree
4. Application crashes
Expected Behavior: What should have happened
Actual Behavior: What actually happened
Environment:
- OS: Linux / Windows / macOS
- OS Version: (e.g., Ubuntu 22.04, Windows 11)
- Qt Version: 6.8.0
- Assimp Version: 5.2.0
- OpenCASCADE Version: 7.9.0
- GPU: [your GPU model]
- GPU Driver: [driver version]
Attachments:
- Screenshot or screen recording
- Model file (if possible, provide a minimal test case)
- Console/log output
- Crash dump (if available)
Additional Context: Any other relevant information
- Check existing issues: Avoid duplicate requests
- Consider compatibility: Does it fit the project's vision?
- Think about implementation: Is it technically feasible?
Title: Clear description of the feature
[FEATURE] Add support for glTF 2.1 extensions
Description: Explain the feature and why it would be useful
Motivation:
Many modern 3D models use glTF 2.1 extensions. Adding support would:
- Enable visualization of newer content
- Improve professional workflow compatibility
- Align with Khronos standards
Proposed Solution: How you envision implementing it (optional)
Alternatives Considered: Other approaches you've thought of
Additional Context: Use cases, examples, references
Linux:
git clone https://github.com/sharjith/ModelViewer-Qt.git
cd ModelViewer-Qt
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug
make -j$(nproc)
./ModelViewerWindows (with vcpkg):
git clone https://github.com/sharjith/ModelViewer-Qt.git
cd ModelViewer-Qt
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=[vcpkg]/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Debug
cmake --build . --config Debug
.\Debug\ModelViewer.exemacOS:
git clone https://github.com/sharjith/ModelViewer-Qt.git
cd ModelViewer-Qt
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=$(brew --prefix qt@6)
make -j$(sysctl -n hw.ncpu)
./ModelViewer.app/Contents/MacOS/ModelViewerModelViewer-Qt/
├── src/ # Source code
├── include/ # Headers
├── ui/ # Qt UI files
├── shaders/ # GLSL shader files
├── res/ # Icons and images
├── textures/ # Textures for materials, env maps, etc.
│ ├── envmap/ # Env maps
│ ├── materials/ # Material textures
│ ├── patterns/ # Hatch patterns
│
├── themes/ # UI theme qss files
├── translations/ # Qt translations
├── tools/ # Blender scripts used for generating the default skybox cubemap
├── data/ # Application Data
│ ├── catalogs/ # Material Catalogs
│ ├── tutorials/ # Tutorial HTML files
│
├── fonts/ # Application fonts
├── cmake/ # CMake modules
├── docs/ # Documentation
├── CMakeLists.txt # Build configuration
├── README.md # Project overview
├── CONTRIBUTING.md # This file
└── LICENSE # GPL-3.0 license
Language Standard: Modern C++17
Style Conventions:
// Classes and types: PascalCase
class MaterialEditor { };
struct RenderingContext { };
// Functions and methods: camelCase
void loadModel(const std::string& filePath);
glm::vec3 calculateNormal(const Triangle& tri);
// Constants: UPPER_CASE
constexpr float PI = 3.14159f;
const int MAX_TEXTURES = 16;
// Member variables: _ prefix
class Renderer
{
private:
float _exposure;
GLuint _framebuffer;
};
// Local variables: camelCase
glm::vec3 viewDirection = glm::normalize(camera.position - targetPoint);Code Quality Rules:
-
Follow RAII principles: Resources should be acquired in the constructor and released in the destructor
class TextureManager { public: TextureManager() { /* allocate */ } ~TextureManager() { /* deallocate */ } private: std::vector<GLuint> textures; };
-
Use smart pointers: Prefer
std::unique_ptrandstd::shared_ptrover raw pointers// Good std::unique_ptr<Material> material = std::make_unique<Material>(); // Avoid Material* material = new Material();
-
Error handling: Use exceptions or return error codes
try { model = loadModel(filePath); } catch (const std::runtime_error& e) { logger.error("Failed to load model: " + std::string(e.what())); }
-
Const correctness: Mark methods as const when they don't modify state
glm::mat4 getTransform() const { return m_transform; } void setTransform(const glm::mat4& t) { m_transform = t; }
-
Comments: Write clear, meaningful comments
// Cook-Torrance BRDF calculation with energy conservation float ggxDistribution(float roughness, float nDotH); // Inverse-transpose matrix for correct normal transformation glm::mat3 normalMatrix = glm::transpose(glm::inverse(glm::mat3(modelMatrix)));
// Shader structure
#version 460 core
// Uniforms (updated per draw call or less frequently)
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProjection;
// Input variables (from vertex buffer)
in vec3 aPosition;
in vec3 aNormal;
in vec2 aTexCoord;
// Output variables
out vec3 vNormal;
out vec2 vTexCoord;
// Shader logic
void main()
{
vNormal = normalize(mat3(transpose(inverse(uModel))) * aNormal);
vTexCoord = aTexCoord;
gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
}Shader Best Practices:
- Use meaningful variable names (avoid
a,b,c) - Include version and feature requirements at the top
- Comment complex calculations (e.g., BRDF, matrix transforms)
- Use consistent indentation (4 spaces)
Header Comments:
/**
* @brief Load a 3D model from disk using Assimp
* @param filePath Path to the model file (STEP, IGES, OBJ, FBX, etc.)
* @return Loaded model or nullptr on failure
* @throws std::runtime_error If the file cannot be opened or parsed
*
* Supports all Assimp formats plus OpenCASCADE native formats.
* Assembly hierarchies and material metadata are preserved.
*/
std::unique_ptr<Model> loadModel(const std::string& filePath);Inline Comments:
// Determinant-based detection for negative scale (flipped geometry)
float determinant = glm::determinant(glm::mat3(modelMatrix));
if (determinant < 0.0f)
{
// Invert normals to face the correct direction
normal = -normal;
}Use descriptive branch names:
feature/khr-transmission # New feature
bugfix/negative-scale-normals # Bug fix
docs/shader-documentation # Documentation
refactor/texture-caching # Code refactoring
test/material-editor # Tests
Write clear, concise commit messages following this format:
<type>(<scope>): <subject>
<body>
<footer>
Examples:
feat(material): implement KHR_materials_transmission with refraction
- Add per-channel IOR support
- Implement screen-space ray tracing for refraction
- Add mipmapped environment map sampling
Closes #123
fix(export): correct material deduplication in GLB pipeline
The material matching was using an index-based comparison instead of
name-based matching, causing Assimp reordering to break assignments.
Now uses name-based matching with proper sampler comparison.
Fixes #456
Commit Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Code style changes (formatting, missing semicolons, etc.)refactor: Code refactoring without feature or bug changesperf: Performance improvementtest: Adding or updating testschore: Build tools, dependencies, etc.
git checkout -b feature/your-feature-name- Keep commits atomic and focused
- One logical change per commit
- Write descriptive commit messages
git fetch upstream
git rebase upstream/mastergit push origin feature/your-feature-nameVisit GitHub and create a PR from your branch to upstream/master.
- Code follows project style guidelines
- All commits are properly formatted
- Branch is up to date with
upstream/master - Code compiles without warnings
- Changes are tested locally
- Documentation is updated
## Description
Brief description of the changes
## Motivation
Why are these changes needed?
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation
- [ ] Performance improvement
- [ ] Code refactoring
## Related Issues
Closes #123
## Testing
How were changes tested?
## Screenshots (if applicable)
Before/after images for UI changes
## Checklist
- [ ] My code follows the style guidelines
- [ ] I have performed a self-review
- [ ] I have commented on complex areas
- [ ] My changes generate no new warnings
- [ ] I have added/updated tests
- [ ] New dependencies are documented- Maintainer Review: Code is reviewed for quality, functionality, and alignment with project goals
- Feedback: Suggestions or requested changes will be provided
- Updates: Make requested changes in new commits (don't force-push)
- Approval: PR is approved once all feedback is addressed
- Merge: Maintainer merges the PR using the appropriate strategy
Review Criteria:
- Code quality and style compliance
- Functionality correctness
- Performance impact
- Documentation completeness
- Test coverage
- Breaking changes disclosure
If adding new functionality, include unit tests:
#include <gtest/gtest.h>
#include "material.h"
TEST(MaterialTest, KHRTransmissionParsing)
{
// Test implementation
EXPECT_TRUE(material.hasTransmission());
EXPECT_FLOAT_EQ(material.getIOR(), 1.5f);
}Test with real 3D models:
- STEP files with assemblies
- glTF models with KHR extensions
- OBJ files with textures
- FBX models with animations
Test on multiple platforms:
# Linux (GCC)
# Windows (MSVC)
# macOS (Clang)Profile changes to ensure no regression:
# Measure shader compilation time
# Profile material editor responsiveness
# Check texture loading performance- Add Doxygen-style comments to public APIs
- Explain complex algorithms
- Include references to papers/specifications
Update README.md if you:
- Add/remove dependencies
- Change build process
- Add major features
- Fix documented bugs
Comment on non-obvious calculations:
// Frisvad orthonormal basis for importance sampling
// Reference: "Building an Orthonormal Basis, Revisited"
vec3 frisvadBasis(vec3 normal);Keep commit messages clear for future reference:
This helps with:
- Git log readability
- Bisect debugging
- Historical understanding
- Profile changes: Ensure no frame rate regression
- Optimize GPU memory: Minimize texture uploads
- Batch rendering: Reduce draw calls
- Shader optimization: Avoid expensive operations in loops
- Test large models: 100+ MB files
- Memory efficiency: Don't load entire files into memory
- Progress feedback: Long operations should report progress
Do not create public issues for security vulnerabilities.
Instead, email sharjith@gmail.com with:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if available)
We'll acknowledge receipt within 48 hours and work with you on a fix.
- GitHub Issues: For bugs and feature requests
- GitHub Discussions: For questions and design discussions
- Email: sharjith@gmail.com for security issues
By contributing to ModelViewer, you agree that your contributions will be licensed under its GPL-3.0 License.
Thank you for contributing to ModelViewer! Your efforts help make professional 3D visualization tools better for everyone.
Happy coding! 🚀✨
Last Updated: March 2026
Version: 1.0