This commit is contained in:
ninja
2025-12-15 23:22:33 +08:00
parent 019570564b
commit 8782765fbc
809 changed files with 118753 additions and 18289 deletions

View File

@@ -0,0 +1,466 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "application.h"
#include <iostream>
#include <fstream>
#include <glm/gtc/matrix_transform.hpp>
/*static settings initialisation*/
glm::vec2 Application::last_position = glm::vec2(0.f);
bool Application::first_mouse = true;
Camera Application::camera = Camera();
int Application::screen_width = 0;
int Application::screen_height = 0;
bool Application::is_wireframe = false;
/*global variable*/
constexpr unsigned short icon_size = 32;
/**********************************************************************************************************************/
/*compute_camera: wrapper to call initialize_position */
/*in : -bbox, used to calculate the appropriate camera position */
/*out: -void */
/*return: void */
/**********************************************************************************************************************/
void Application::compute_camera(const utils::geometry::BoundingBox& box)
{
Application::camera.initialize_position(box);
}
/**********************************************************************************************************************/
/*~Application: destructor of the Application'class, it calls glfwTerminate which destroys all remaining windows and */
/* cursorsand frees any other glfw allocated resources. */
/*in : -void */
/*out: -window, which is destroyed no further callbacks will be called for that window. */
/*return: void */
/**********************************************************************************************************************/
Application::~Application()
{
if (window != nullptr)
{
glfwDestroyWindow((GLFWwindow*) window);
window = nullptr;
}
glfwTerminate();
}
/**********************************************************************************************************************/
/*initialize_glf: This function initializes the GLFW library with initialize_glf. It also sets hints for the next call*/
/* to glfwCreateWindow */
/*in : -void */
/*out: -void */
/*return: 1 if the initialisation of glf failed, */
/* 0 if success */
/**********************************************************************************************************************/
int Application::initialize_glf()
{
if (glfwInit() != 1)
{
return 1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
return 0;
}
/**********************************************************************************************************************/
/*get_ts3d_logo: This function creates a ts3d logo from a binary file containing the RGB pixels of the ts3d logo */
/*in : -void */
/*out: -pixels a char array which will contain the ts3d logo in the following format: a sequence of 4 unsigned char */
/* for each pixel satisfying R G B A */
/*return: void */
/**********************************************************************************************************************/
void Application::get_ts3d_logo(char* pixels)
{
std::string logo_path = SHADERS_FOLDER;
logo_path.append("/../../../resources/ts3d32.bin");
unsigned short pixel_size = icon_size * icon_size * 4;
std::ifstream pixel_stream(logo_path.c_str(), std::ios::binary);
pixel_stream.read(pixels, pixel_size);
}
/**********************************************************************************************************************/
/*create_window: This function creates a window and its associated OpenGL or OpenGL ES context. */
/*in : -void */
/*out: -screen_width, screen width initialisation */
/* -screen_height, screen height initialisation */
/* -last_position, set the last position of the mouse in the center of the screen */
/* -window, a GLFWwindow created here with its associated OpenGL context. */
/*return: 1 if the window creation fails */
/* 0 if success */
/**********************************************************************************************************************/
int Application::create_window(int width, int height, std::string title)
{
screen_width = width;
screen_height = height;
last_position.x = screen_width / 2.0f;
last_position.y = screen_height / 2.0f;
window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
if (window == nullptr)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return 1;
}
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
GLFWimage images[1];
unsigned short pixel_size = icon_size * icon_size * 4;
char* pixels = new char[pixel_size];
get_ts3d_logo(pixels);
images[0].pixels = (unsigned char*)pixels;
images[0].width = icon_size;
images[0].height = icon_size;
glfwSetWindowIcon(window, 1, images);
delete[] pixels;
//else no logo in the window, but no error
return 0;
}
void Application::set_blending(bool blend)
{
if (blend)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
else
{
glDisable(GL_BLEND);
}
}
/**********************************************************************************************************************/
/*initialize_glad: Load all OpenGL functions using the glfw loader function at runtime. This is required to access */
/* functions from OpenGL. */
/*in : -void */
/*out: -void */
/*return: 1 if the OpenGL functions Loading fails */
/* 0 if success */
/**********************************************************************************************************************/
int Application::initialize_glad()
{
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return 1;
}
//to be consistent with the initialisation of is_wireframe = false;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_DEPTH_TEST);
return 0;
}
/**********************************************************************************************************************/
/*set_callbacks: initialise all the callback events that will interact with the user */
/*in : -void */
/*out: -void */
/*return: void */
/**********************************************************************************************************************/
void Application::set_callbacks()
{
glfwMakeContextCurrent(window);
glfwSetCursorPosCallback(window, mouse_moved_callback);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetScrollCallback(window, scroll_callback);
glfwSetKeyCallback(window, key_pressed_callback);
glfwSetWindowSizeCallback(window, window_size_changed_callback);
glfwSetMouseButtonCallback(window, mouse_pressed_callback);
// tell GLFW to capture our mouse
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
/**********************************************************************************************************************/
/*launch: calls all the initialisation functions */
/*in : -void */
/*out: -void */
/*return: 1 if there is an error in the launch */
/* 0 if sucess */
/**********************************************************************************************************************/
int Application::launch(int width, int height, std::string title)
{
if (initialize_glf() != 0)
return 1;
if (create_window(width, height, title) != 0)
return 1;
set_callbacks();
if (initialize_glad() != 0)
return 1;
return 0;
}
/**********************************************************************************************************************/
/*compute_projection_matrix: Creates a matrix for a symetric perspective-view frustum. */
/*in : -screen width */
/* -screen height */
/* -camera */
/*return: glm::mat4 representing the symetric perspective-view frustrum */
/* glm::mat4 null if the screen height worth 0glm::mat4 */
/**********************************************************************************************************************/
glm::mat4 Application::compute_projection_matrix() const
{
if (screen_height > 0)
{
return glm::perspective(glm::pi<float>() / 4.f, (float) screen_width / (float) screen_height, camera.calculate_near(), camera.calculate_far());
}
return glm::mat4(0.f);
}
/**********************************************************************************************************************/
/*compute_view_matrix: get the "look at" view matrix based on the camera */
/*in : -void */
/*out: -void */
/*return: glm::mat4 containing the "look at" matrix representing the 3D model */
/**********************************************************************************************************************/
glm::mat4 Application::compute_view_matrix() const
{
return camera.get_view_matrix();
}
/**********************************************************************************************************************/
/*clear: specify clear values (light grey) for the color buffers and clear buffers to preset values */
/*in : -void */
/*out: -void */
/*return: void */
/**********************************************************************************************************************/
void Application::clear()
{
glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
/**********************************************************************************************************************/
/*should_close: returns the value of the close flag of the window. */
/*in : -void */
/*out: -void */
/*return: true if the windows is closed else true */
/**********************************************************************************************************************/
bool Application::should_close()
{
return glfwWindowShouldClose(window);
}
/**********************************************************************************************************************/
/*display: This function swaps the front and back buffers of window when rendering with OpenGL and processes only */
/* those events that are already in the event queue and then returns immediately */
/*in : -window */
/*out: -void */
/*return: void */
/**********************************************************************************************************************/
void Application::display()
{
glfwSwapBuffers(window);
glfwPollEvents();
}
/**********************************************************************************************************************/
/*mouse_moved_callback: callback function called for the cursor position event of the specified window */
/*in : -window,a GLFWwindow* where the event comes from */
/* -xposIn, a double representing the abscissa of the mouse */
/* -yposIn, a double representing the ordinate of the mouse */
/*out: -last_position, the new mouse coordinates become the last position of the mouse */
/* -first_mouse, this boolean allows the event to know if it's the first time in the mouse moving we enter in this*/
/* function, then we initialise the first usefull settings of the move */
/* -camera, the Camera object is modified with is new position */
/*return: void */
/**********************************************************************************************************************/
void Application::mouse_moved_callback(GLFWwindow* window, double xposIn, double yposIn)
{
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
{
const float xpos = static_cast<float>( xposIn );
const float ypos = static_cast<float>( yposIn );
if (first_mouse)
{
last_position.x = xpos;
last_position.y = ypos;
first_mouse = false;
}
const float xOffset = xpos - last_position.x;
const float yOffset = last_position.y - ypos; // reversed since y-coordinates go from bottom to top
int width = 0;
int height = 0;
glfwGetWindowSize(window, &width, &height);
if (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS)
{
camera.process_mouse_translation(xOffset, yOffset);
}
else
{
camera.process_mouse_rotation(xOffset, yOffset, width, height);
}
last_position.x = xpos;
last_position.y = ypos;
}
}
/**********************************************************************************************************************/
/*mouse_pressed_callback: callback function called when a press mouse button event appears in window */
/*in : -window, the GLFWwindow* window where appears this event */
/* -button, int that represents mouse button that was pressed or released. */
/* -action, int that represents GLFW_PRESS or GLFW_RELEASE */
/* -int mods, int that represents which modifier keys were held down (not use here) */
/*out: -camera, the Camera object is modified with is new position */
/*return: void */
/**********************************************************************************************************************/
void Application::mouse_pressed_callback(GLFWwindow* /*window*/, int button, int action, int /*mods*/)
{
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_RELEASE)
{
camera.process_switch_view();
}
if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
first_mouse = true;
}
}
/**********************************************************************************************************************/
/*framebuffer_size_callback: callback function called for framebuffer size event, that enbles to adapt the 3D model */
/* with the new window size */
/*in : -window, the GLFWwindow* window where appears this event */
/* -w, int that represents the new width in pixel of windoax */
/* -h, int that represents the new height in pixel of windoax */
/*out: -void */
/*return: void */
/**********************************************************************************************************************/
void Application::framebuffer_size_callback(GLFWwindow* /*window*/, int w, int h)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, w, h);
}
/**********************************************************************************************************************/
/*scroll_callback: A scroll callback function called by scroll events */
/*in : -window, a GLFWwindow that recevied the event */
/* -xoffset, double representing the scroll offset along the x-axis */
/* -yoffset, double representing the scroll offset along the y-axis */
/*out: -camera, the Camera object is modified with is new position */
/*return: void */
/**********************************************************************************************************************/
void Application::scroll_callback(GLFWwindow* /*window*/, double /*xoffset*/, double yoffset)
{
camera.process_mouse_scroll(yoffset > 0.f);
}
/**********************************************************************************************************************/
/*key_pressed_callback: a keyboard key callback function called by key pressed events */
/*in : -window, a GLFWwindow that recevied the event */
/* -key, int representing the keyboard key that was pressed or released. */
/* -scancode, int representing the system-specific scancode of the key. */
/* -action, int representing GLFW_PRESS, GLFW_RELEASE or GLFW_REPEAT. */
/* -mods, int representing bit field describing which modifier keys were held down. */
/*out: -camera, the Camera object is modified with is new position */
/*return: void */
/**********************************************************************************************************************/
void Application::key_pressed_callback(GLFWwindow* window, int key, int /*scancode*/, int action, int mods)
{
if (action == GLFW_RELEASE)
{
if (key == GLFW_KEY_F && mods == GLFW_MOD_SHIFT)
{
// flip the Wireframe mode
if (is_wireframe)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
is_wireframe = !is_wireframe;
}
else if (key == GLFW_KEY_ESCAPE)
{
glfwSetWindowShouldClose(window, true);
}
else if (key == GLFW_KEY_O)
{
camera.set_to_origin();
}
}
else if (action == GLFW_REPEAT || action == GLFW_PRESS)
{
switch (key)
{
case GLFW_KEY_W:
camera.process_keyboard(Camera::EMovement::ZOOM_IN);
break;
case GLFW_KEY_S:
camera.process_keyboard(Camera::EMovement::ZOOM_OUT);
break;
case GLFW_KEY_A:
camera.process_keyboard(Camera::EMovement::FRONT_DIRECT);
break;
case GLFW_KEY_D:
camera.process_keyboard(Camera::EMovement::FRONT_INV);
break;
case GLFW_KEY_R:
camera.process_keyboard(Camera::EMovement::RIGHT_DIRECT);
break;
case GLFW_KEY_V:
camera.process_keyboard(Camera::EMovement::RIGHT_INV);
break;
case GLFW_KEY_Z:
camera.process_keyboard(Camera::EMovement::UP_DIRECT);
break;
case GLFW_KEY_X:
camera.process_keyboard(Camera::EMovement::UP_INV);
break;
case GLFW_KEY_RIGHT:
camera.process_keyboard(Camera::EMovement::MV_RIGHT);
break;
case GLFW_KEY_LEFT:
camera.process_keyboard(Camera::EMovement::MV_LEFT);
break;
case GLFW_KEY_UP:
camera.process_keyboard(Camera::EMovement::MV_UP);
break;
case GLFW_KEY_DOWN:
camera.process_keyboard(Camera::EMovement::MV_DOWN);
break;
default:
break;
}
}
}
/**********************************************************************************************************************/
/*window_size_changed_callback: window size callbacks function called when the screen size as changed */
/*in : -window, a GLFWwindow that recevied the event */
/* -width, int of the new width, in screen coordinates, of the window */
/* -height, int of the new eight, in screen coordinates, of the window */
/*out: -screen_width, the new width screen */
/* -screen_width, the new height screen */
/*return: void */
/**********************************************************************************************************************/
void Application::window_size_changed_callback(GLFWwindow* /*window*/, int width, int height)
{
screen_width = width;
screen_height = height;
}

View File

@@ -0,0 +1,64 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#ifndef APPLICATION_H
#define APPLICATION_H
#include <string>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/vec2.hpp>
#include "camera.h"
class Application
{
public:
GLFWwindow* window = nullptr;
static Camera camera;
Application() = default;
~Application();
void compute_camera(const utils::geometry::BoundingBox& box);
int launch(int width, int height, std::string title);
void clear();
bool should_close();
void display();
glm::mat4 compute_projection_matrix() const;
glm::mat4 compute_view_matrix() const;
void set_blending(bool blend);
private:
// Callbacks management
static void mouse_moved_callback(GLFWwindow* window, double position_x, double position_y);
static void mouse_pressed_callback(GLFWwindow* window, int button, int action, int mods);
static void framebuffer_size_callback(GLFWwindow* window, int w, int h);
static void scroll_callback(GLFWwindow* window, double offset_x, double offset_y);
static void key_pressed_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
static void window_size_changed_callback(GLFWwindow* window, int width, int height);
void get_ts3d_logo(char* pixels);
int initialize_glf();
int create_window(int width, int height, std::string title);
void set_callbacks();
int initialize_glad();
static int screen_width;
static int screen_height;
static bool first_mouse;
static glm::vec2 last_position;
static bool is_wireframe;
};
#endif // APPLICATION_H

View File

@@ -0,0 +1,322 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "camera.h"
#include <glm/gtc/matrix_transform.hpp>
/**********************************************************************************************************************/
/*initialize_position: this function must be call once just after the camera has been created. It calculates the */
/* camera's position with the the model's bounding box. the initial position corresponds to an */
/* isometric view. The various member parameters are also initialized */
/*in : -bbox, used to calculate the appropriate camera position */
/*out: -orbital_center, the point which will be the center of the bounding, it also will be the orbital center of the */
/* camera movement */
/* -max_bbx_length, the diagonal length of the bounding box */
/* -position, the 3D point where the camera is located in the global space */
/* -up, the 3D vector of the camera which shows the up direction of the camera from his position */
/* -right, the 3D vector which shows the right direction of the camera from his position */
/* -front, the 3D vector which shows the front direction of the camera from his position, normal vector from */
/* position to the orbital center */
/* -start_position, 3D point of the initial position, allow the user to come back at the first view */
/* -start_right, 3D vector of the initial right vector, allow the user to come back at the first view */
/* -start_front, 3D vector of the initial front vector, allow the user to come back at the first view */
/* -start_up, 3D vector of the initial front vector, allow the user to come back at the first view */
/* -current_view, this setting is initialized to the isometric view, then we could switch step by step to the */
/* other views */
/*return : void */
/**********************************************************************************************************************/
void Camera::initialize_position(const utils::geometry::BoundingBox& bbox)
{
orbital_center = bbox.center();
max_bbx_length = (float)glm::distance(bbox.min, bbox.max);
position = orbital_center - (max_bbx_length * 1.5f) * glm::vec3(-glm::sqrt(2.f) / 2.f, glm::sqrt(2.f) / 2.f, 0.f);
current_view = EView::ISO;
up = glm::vec3(0.f, 0.f, 1.f);
right = glm::vec3(glm::sqrt(2.f) / 2.f, glm::sqrt(2.f) / 2.f, 0.f);
front = glm::vec3(-glm::sqrt(2.f) / 2.f, glm::sqrt(2.f) / 2.f, 0.f);
start_position = position;
start_right = right;
start_front = front;
start_up = up;
}
/**********************************************************************************************************************/
/*get_view_matrix: a wrapper to the glm lookAt function which builds a "look at" view matrix based on the camera */
/* parameters. */
/*in :-void */
/*out:-void */
/*return: A glm::mat4 matrix corresponding to the "look at" of the camera position */
/**********************************************************************************************************************/
glm::mat4 Camera::get_view_matrix()
{
return glm::lookAt(position, position + front, up);
}
/**********************************************************************************************************************/
/*calculate_far: called by compute_projection_matrix in the main loop of the drawing, it is */
/* particularly useful when zooming, and the far plan will move closer or further away, then the model */
/* won't be cut off. */
/*in :-void */
/*out:-void */
/*return: a float which will be the new far to apply in the rendering model */
/**********************************************************************************************************************/
float Camera::calculate_far()
{
float far = glm::distance(orbital_center, position) + max_bbx_length / 2.f;
far *= 1.1f;
return far;
}
/**********************************************************************************************************************/
/*calculate_far: called by compute_projection_matrix in the main loop of the drawing, it is */
/* particularly useful when the distance is very great, the near performs better whenit is closer to */
/* the model */
/*in :-void */
/*out:-void */
/*return: a float which will be the new near to apply to the rendering model */
/**********************************************************************************************************************/
float Camera::calculate_near()
{
float near = glm::distance(orbital_center, position) - max_bbx_length / 2.f;
near *= 0.9f;
if (near <= 0)
{
near = max_bbx_length/1000.f;
}
return near;
}
/**********************************************************************************************************************/
/* rotate_camera: private method to rotate the model, the camera is actually moved around the axis (axe_rotate), */
/* passing through the centre of the orbitand through an angle alpha(in parameter). */
/*in : -axe_rotate, the vector qualifying the axis passing through the orbital centre around which the camera will */
/* rotate */
/* -alpha, a float defining the angle of rotation */
/*out: -position, the point defining the new camera position after the rotation */
/* -front, the front vector after the rotation */
/* -right, the right vector after the rotation */
/* -up, the right vector after the rotation */
/*return: void */
/**********************************************************************************************************************/
void Camera::rotate_camera(glm::vec3 axe_rotate, float alpha)
{
glm::mat4 rotate = glm::mat4(1.f);
glm::vec4 translate(-orbital_center.x, -orbital_center.y, -orbital_center.z, 1.f);
rotate = glm::rotate(rotate, alpha, axe_rotate);
position = glm::vec4(position, 1.f) + translate;
position = glm::vec4(position, 1.f) * rotate;
position = glm::vec4(position, 1.f) - translate;
front = glm::vec4(front, 1.f) * rotate;
right = glm::vec4(right, 1.f) * rotate;
up = glm::vec4(up, 1.f) * rotate;
}
/**********************************************************************************************************************/
/*set_to_origin: called after pressing the "O" button, to place the camera in the position it was in when the model */
/* was opened. */
/*in : -void */
/*out: -position, the point defining the camera position will be defined as it was at the begining */
/* -right, the right vector of the camera will be defined as it was at the beginning */
/* -front, the front vector of the camera will be defined as it was at the beginning */
/* -up, the up vector of the camera will be defined as it was at the beginning */
/*return: void */
/**********************************************************************************************************************/
void Camera::set_to_origin()
{
position = start_position;
right = start_right;
front = start_front;
up = start_up;
}
/**********************************************************************************************************************/
/*process_keyboard: called after a keyboard event to move the camera by rotation or translation */
/*in : -direction, an EMovement enabling to know how to move the camera */
/*out: -position, the 3D point of the camera will be changed with the appropriate move */
/* -front (indirectly by rotate_camera), the front camera vector after the move */
/* -right (indirectly by rotate_camera), the right camera vector after the move */
/* -up (indirectly by rotate_camera), the up camera vector after the move */
/*return: void */
/**********************************************************************************************************************/
void Camera::process_keyboard(Camera::EMovement direction)
{
switch (direction)
{
case Camera::EMovement::ZOOM_IN:
position += front * (max_bbx_length * 0.05f);
break;
case Camera::EMovement::ZOOM_OUT:
position -= front * (max_bbx_length * 0.05f);
break;
case Camera::EMovement::FRONT_DIRECT:
rotate_camera(front, glm::radians(1.f));
break;
case Camera::EMovement::FRONT_INV:
rotate_camera(front, glm::radians(-1.f));
break;
case Camera::EMovement::RIGHT_DIRECT:
rotate_camera(right, glm::radians(1.f));
break;
case Camera::EMovement::RIGHT_INV:
rotate_camera(right, glm::radians(-1.f));
break;
case Camera::EMovement::UP_DIRECT:
rotate_camera(up, glm::radians(1.f));
break;
case Camera::EMovement::UP_INV:
rotate_camera(up, glm::radians(-1.f));
break;
case Camera::EMovement::MV_RIGHT:
position -= right * (max_bbx_length * 0.05f);
break;
case Camera::EMovement::MV_LEFT:
position += right * (max_bbx_length * 0.05f);
break;
case Camera::EMovement::MV_UP:
//we lower the camera to move the model up
position -= up * (max_bbx_length * 0.05f);
break;
case Camera::EMovement::MV_DOWN:
position += up * (max_bbx_length * 0.05f);
break;
default:
break;
}
}
/**********************************************************************************************************************/
/*process_mouse_rotation: called by a mouse move event with his left button pressed and not release, this functions */
/* allows the user to move the 3D model by rotation around right, front, or up axes depending */
/* */
/*in : -xOffset, the mouse move in X axes since the last capture of the mouse position */
/* -yOffset, the mouse move in Y axes since the last capture of the mouse position */
/* -screenWidth, the current width of the opengl window where the model is displayed */
/* -screenHeight, the current length of the opengl window where the model is displayed */
/*out: -position (indirectly by rotate_camera), the 3D point of the camera will be changed with the appropriate move */
/* -front (indirectly by rotate_camera), the front camera vector after the move */
/* -right (indirectly by rotate_camera), the right camera vector after the move */
/* -up (indirectly by rotate_camera), the up camera vector after the move */
/*return: void */
/**********************************************************************************************************************/
void Camera::process_mouse_rotation(float xOffset, float yOffset, int screenWidth, int screenHeight)
{
if (glm::abs(screenWidth) > glm::epsilon<float>() && glm::abs(screenHeight) > glm::epsilon<float>())
{
const float alphaX = xOffset / screenWidth * glm::pi<float>();
const float alphaY = yOffset / screenHeight * glm::pi<float>();
rotate_camera(up, alphaX);
rotate_camera(right, -alphaY);
}
}
/**********************************************************************************************************************/
/*process_mouse_translation: called by a mouse move event with his left button pressed and not release simultaneously */
/* with the shift key presses, this functions allows the user to move the 3D model by */
/* parallel translation with the screen */
/* */
/*in : -xOffset, the mouse move in X axes since the last capture of the mouse position */
/* -yOffset, the mouse move in Y axes since the last capture of the mouse position */
/*out: -position (indirectly by rotate_camera), the 3D point of the camera will be changed with the appropriate move */
/* -front (indirectly by rotate_camera), the front camera vector after the move */
/* -right (indirectly by rotate_camera), the right camera vector after the move */
/* -up (indirectly by rotate_camera), the up camera vector after the move */
/*return: void */
/**********************************************************************************************************************/
void Camera::process_mouse_translation(float xOffset, float yOffset)
{
position -= right * xOffset * max_bbx_length / 1000.f;
position -= up * yOffset * max_bbx_length / 1000.f;
}
/**********************************************************************************************************************/
/*process_mouse_scroll: called by a mouse scroll event, the purpose of this function is to move the camera closer or */
/* further away */
/*in : -is_zoom_in, a boolean to know if the camera has to move closer or further */
/*out: -position, the 3D point which will be the new position of the camea */
/*return: void */
/**********************************************************************************************************************/
void Camera::process_mouse_scroll(bool is_zoom_in)
{
float sign = is_zoom_in ? 2.f : -2.f;
position += sign * front * ( max_bbx_length * 0.05f );
}
/**********************************************************************************************************************/
/*process_switch_view: called by a mouse right click event, the purpose of this function is to swith the model view */
/* between the usual view know: Isometric, top, bottom, left, right,front and back */
/*in : void */
/*out: -position, the 3D point of the new position of the camera in the switched view */
/* -up, the 3D vector of the up camera in the switched view */
/* -right, the 3D vector of the right camera in the switched view */
/* -front, the 3D vector of the front camera in the switched view */
/*return: void */
/**********************************************************************************************************************/
void Camera::process_switch_view()
{
current_view = (Camera::EView)(((int)current_view + 1) % 7);
switch (current_view)
{
case Camera::EView::ISO:
position = orbital_center - (max_bbx_length * 1.5f) * glm::vec3(-glm::sqrt(2.f)/2.f, glm::sqrt(2.f) / 2.f, 0.f);
up = glm::vec3(0.f, 0.f, 1.f);
right = glm::vec3(glm::sqrt(2.f) / 2.f, glm::sqrt(2.f) / 2.f, 0.f);
front = glm::vec3(-glm::sqrt(2.f) / 2.f, glm::sqrt(2.f) / 2.f, 0.f);
break;
case Camera::EView::TOP:
position = orbital_center + (max_bbx_length * 1.5f) * glm::vec3(0.f, 0.f, 1.f);
up = glm::vec3(0.f, 1.f, 0.f);
right = glm::vec3(-1.f, 0.f, 0.f);
front = glm::vec3(0.f, 0.f, -1.f);
break;
case Camera::EView::BOTTOM:
position = orbital_center - (max_bbx_length * 1.5f) * glm::vec3(0.f, 0.f, 1.f);
up = glm::vec3(0.f, -1.f, 0.f);
right = glm::vec3(1.f, 0.f, 0.f);
front = glm::vec3(0.f, 0.f, 1.f);
break;
case Camera::EView::LEFT:
position = orbital_center - (max_bbx_length * 1.5f) * glm::vec3(1.f, 0.f, 0.f);
up = glm::vec3(0.f, 0.f, 1.f);
right = glm::vec3(0.f, -1.f, 0.f);
front = glm::vec3(1.f, 0.f, 0.f);
break;
case Camera::EView::RIGHT:
position = orbital_center + (max_bbx_length * 1.5f) * glm::vec3(1.f, 0.f, 0.f);
up = glm::vec3(0.f, 0.f, 1.f);
right = glm::vec3(0.f, 1.f, 0.f);
front = glm::vec3(-1.f, 0.f, 0.f);
break;
case Camera::EView::FRONT:
position = orbital_center - (max_bbx_length * 1.5f) * glm::vec3(0.f, 1.f, 0.f);
up = glm::vec3(0.f, 0.f, 1.f);
right = glm::vec3(1.f, 0.f, 0.f);
front = glm::vec3(0.f, 1.f, 0.f);
break;
case Camera::EView::BACK:
position = orbital_center + (max_bbx_length * 1.5f) * glm::vec3(0.f, 1.f, 0.f);
up = glm::vec3(0.f, 0.f, 1.f);
right = glm::vec3(-1.f, 0.f, 0.f);
front = glm::vec3(0.f, -1.f, 0.f);
break;
default:
break;
}
}

View File

@@ -0,0 +1,101 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#ifndef CAMERA_H
#define CAMERA_H
#include <glm/vec3.hpp>
#include "../utils/bounding_box.h"
class Camera
{
public:
enum class EMovement
{
ZOOM_IN = 0,
ZOOM_OUT,
FRONT_DIRECT,
FRONT_INV,
RIGHT_DIRECT,
RIGHT_INV,
UP_DIRECT,
UP_INV,
MV_RIGHT,
MV_LEFT,
MV_UP,
MV_DOWN
};//enum to manage the different kind of camera moving
enum class EView
{
ISO = 0,
TOP,
BOTTOM,
LEFT,
RIGHT,
FRONT,
BACK
};//enum names the computed views
glm::vec3 position;
glm::vec3 front;
glm::vec3 up;
glm::vec3 right;
glm::vec3 orbital_center;
glm::vec3 start_position;
glm::vec3 start_front;
glm::vec3 start_right;
glm::vec3 start_up;
// camera Attributes
float max_bbx_length;
EView current_view;
~Camera()= default;
// processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
void process_keyboard(Camera::EMovement direction);
// processes input received from a mouse input system. Expects the offset value in both the x and y direction.
void process_mouse_rotation(float xOffset, float yOffset, int screenWidth, int screenHeight);
// processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis.
void process_mouse_scroll(bool is_zoom_in);
// processes input received from a mouse move event.
void process_mouse_translation(float xOffset, float yOffset);
// process input received from a right mouse click.
void process_switch_view();
// set the original position of the camera, calculated with the size of the bounding box
void initialize_position( const utils::geometry::BoundingBox& bbox);
// processes input received when the O key on the keyboard is pressed.
void set_to_origin();
// allows to have the most optimised far after a zoom in or out
float calculate_far();
// allows to have the most optimised near after a zoom in or out
float calculate_near();
// returns the view matrix calculated
glm::mat4 get_view_matrix();
private:
// allow to move the camera in cercle from orbital center and the current camera position
void rotate_camera(glm::vec3 axe_rotate, float alpha);
};
#endif // CAMERA_H

View File

@@ -0,0 +1,45 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "ebo.h"
EBO::EBO(const array_of_indices& indices)
{
glGenBuffers(1, &id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
}
EBO::EBO(const std::vector<array_of_indices>& array_of_indices)
{
std::size_t start = 0;
for (const auto& indices : array_of_indices)
{
glGenBuffers(1, &id);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
start += indices.size() * sizeof(GLuint);
}
}
void EBO::Bind()
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id);
}
void EBO::Unbind()
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void EBO::Delete()
{
glDeleteBuffers(1, &id);
}

View File

@@ -0,0 +1,33 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#ifndef EBO_H
#define EBO_H
#include <vector>
#include <glad/glad.h>
using array_of_indices = std::vector<unsigned int>;
class EBO
{
public:
GLuint id;
// Mesh mono color or with vertex color
EBO(const array_of_indices& indices);
// Mesh sort by faces
EBO(const std::vector<array_of_indices>& array_of_indices);
void Bind();
void Unbind();
void Delete();
};
#endif // EBO_H

View File

@@ -0,0 +1,55 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "mesh.h"
#include <algorithm>
#include <glm/mat4x4.hpp>
Mesh::Mesh(const utils::geometry::BufferData& data,
const glm::mat4& plnt,
const utils::properties::style::Graphics& style_)
{
placement = plnt;
style = style_;
indice_count = static_cast<int>(data.indices.size() );
box = data.mesh_box.transform(plnt);
vao.Bind();
VBO vbo(data.vertices);
EBO ebo(data.indices);
vao.LinkAttrib(vbo, 0, 3, GL_FLOAT, sizeof(utils::geometry::Vertex), (GLvoid*) 0);
vao.LinkAttrib(vbo, 1, 3, GL_FLOAT, sizeof(utils::geometry::Vertex), (GLvoid*) ( 3 * sizeof(float) ));
vao.Unbind();
vbo.Unbind();
ebo.Unbind();
}
void Mesh::draw()
{
if (indice_count == 0)
return;
vao.Bind();
// Draw the actual mesh
glDrawElements(GL_TRIANGLES, indice_count, GL_UNSIGNED_INT, 0);
vao.Unbind();
}
void Mesh::sort_by_style(std::vector<Mesh>& models)
{
auto by_style = [] (const Mesh& m1, const Mesh& m2) {
return m1.style.id < m2.style.id;
};
std::sort(models.begin(), models.end(), by_style);
}

View File

@@ -0,0 +1,41 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#ifndef MESH_H
#define MESH_H
#include "../../utils/bounding_box.h"
#include "../../utils/properties.h"
#include "../../utils/geometry.h"
#include "ebo.h"
#include "vao.h"
class Mesh
{
public:
int indice_count = 0;
utils::geometry::BoundingBox box;
glm::mat4 placement;
utils::properties::style::Graphics style;
VAO vao;
Mesh(const utils::geometry::BufferData& data,
const glm::mat4& placement,
const utils::properties::style::Graphics& style);
Mesh() = default;
~Mesh() = default;
// Draws the mesh
void draw();
static void sort_by_style(std::vector<Mesh>& models);
};
#endif // MESH_H

View File

@@ -0,0 +1,226 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "shader.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
std::string parse_file(const char* filename)
{
try
{
std::ifstream file;
file.open(filename);
std::stringstream filestream;
filestream << file.rdbuf();
file.close();
return filestream.str();
}
catch (std::ifstream::failure& e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ: " << e.what() << std::endl;
}
return "";
}
Shader::Shader(const char* vertex_filename, const char* fragment_filename)
{
std::string vertex_filepath = SHADERS_FOLDER;
vertex_filepath.append("/");
vertex_filepath.append(vertex_filename);
std::string vertexCode = parse_file(vertex_filepath.c_str());
const char* vShaderCode = vertexCode.c_str();
std::string fragment_filepath = SHADERS_FOLDER;
fragment_filepath.append("/");
fragment_filepath.append(fragment_filename);
std::string fragmentCode = parse_file(fragment_filepath.c_str());
const char* fShaderCode = fragmentCode.c_str();
unsigned int vertex, fragment;
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, nullptr);
glCompileShader(vertex);
compile_errors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, nullptr);
glCompileShader(fragment);
compile_errors(fragment, "FRAGMENT");
// shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
compile_errors(ID, "PROGRAM");
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::use()
{
glUseProgram(ID);
}
void Shader::detach()
{
glDeleteProgram(ID);
}
void Shader::add_light_properties(const glm::vec3& light_position)
{
use();
set_vec4("lightColor", 1.f, 1.f, 1.f, 0.f);
set_vec3("lightPos", light_position);
}
void Shader::compile_errors(unsigned int shader, const std::string & type)
{
GLint success;
GLchar infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
}
void Shader::set_value(const std::string& name, float value) const
{
glUniform1fv(glGetUniformLocation(ID, name.c_str()), 1, &value);
}
void Shader::set_vec2(const std::string& name, const glm::vec2& value) const
{
glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::set_vec2(const std::string& name, float x, float y) const
{
glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
}
// ------------------------------------------------------------------------
void Shader::set_vec3(const std::string& name, const glm::vec3& value) const
{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::set_vec3(const std::string& name, float x, float y, float z) const
{
glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
}
// ------------------------------------------------------------------------
void Shader::set_vec4(const std::string& name, const glm::vec4& value) const
{
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::set_vec4(const std::string& name, float x, float y, float z, float w) const
{
glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
}
// ------------------------------------------------------------------------
void Shader::set_mat4(const std::string& name, const glm::mat4& mat) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void Shader::update_view_matrix(const glm::mat4& mat) const
{
set_mat4("view", mat);
}
void Shader::update_world_matrix(const glm::mat4& mat) const
{
set_mat4("world", mat);
}
void Shader::update_model_matrix(const glm::mat4& mat) const
{
set_mat4("model", mat);
set_mat4("model_normal", glm::transpose(glm::inverse(mat)));
}
void Shader::update_projection_matrix(const glm::mat4& mat) const
{
set_mat4("projection", mat);
}
void Shader::update_mesh_color(const glm::vec4& rgba) const
{
set_vec4("material.ambiant", rgba);
set_vec4("material.diffuse", rgba);
set_vec4("material.specular", 0.5f, 0.5f, 0.5f, rgba[3]);
set_vec4("material.emissive", 0.f, 0.f, 0.f, rgba[3]);
set_value("material.shininess", 0.5f);
}
void Shader::update_mesh_material(const utils::properties::style::Material& material) const
{
set_vec4("material.ambiant", material.ambient);
set_vec4("material.diffuse", material.diffuse);
set_vec4("material.specular", material.specular);
set_vec4("material.emissive", material.emissive);
set_value("material.shininess", material.shininess);
}
void Shader::update_mesh_style(const utils::properties::style::Graphics& graphics, bool& is_first)
{
if (!is_first && current_graphics_id == graphics.id)
return;
is_first = false;
current_graphics_id = graphics.id;
if (graphics.id == -1)
{
update_mesh_material(utils::properties::style::default_material);
}
else if (graphics.type == utils::properties::style::Graphics::UNDEF)
{
update_mesh_material(utils::properties::style::default_material);
}
else if (graphics.type == utils::properties::style::Graphics::TEXTURE)
{
std::cout << "WARNING::TEXTURE::NOT_IMPLEMENTED_IN_THE_SAMPLE" << std::endl;
update_mesh_material(utils::properties::style::default_material);
}
else if (graphics.type == utils::properties::style::Graphics::RGBA)
{
update_mesh_color(graphics.rgba);
}
else if (graphics.type == utils::properties::style::Graphics::MATERIAL)
{
update_mesh_material(graphics.material);
}
else
{
std::cout << "ERROR::STYLE::UNEXPECTED" << std::endl;
update_mesh_material(utils::properties::style::default_material);
}
}

View File

@@ -0,0 +1,57 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#ifndef SHADER_H
#define SHADER_H
#include <string>
#include <vector>
#include <glad/glad.h>
#include <glm/mat4x4.hpp>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include "../../utils/properties.h"
class Shader
{
public:
GLuint ID;
int current_graphics_id = -1;
Shader(const char* vertexFile, const char* fragmentFile);
void use();
void detach();
void add_light_properties(const glm::vec3& light_position);
void update_view_matrix(const glm::mat4& mat) const;
void update_model_matrix(const glm::mat4& mat) const;
void update_world_matrix(const glm::mat4& mat) const;
void update_projection_matrix(const glm::mat4& mat) const;
void update_mesh_style(const utils::properties::style::Graphics& graphics, bool& is_first);
void set_vec3(const std::string& name, const glm::vec3& value) const;
private:
void update_mesh_color(const glm::vec4& rgba) const;
void update_mesh_material(const utils::properties::style::Material& material) const;
void compile_errors(unsigned int shader, const std::string & type);
void set_value(const std::string& name, float value) const;
void set_vec2(const std::string& name, const glm::vec2& value) const;
void set_vec2(const std::string& name, float x, float y) const;
void set_vec3(const std::string& name, float x, float y, float z) const;
void set_vec4(const std::string& name, const glm::vec4& value) const;
void set_vec4(const std::string& name, float x, float y, float z, float w) const;
void set_mat4(const std::string& name, const glm::mat4& mat) const;
};
#endif // SHADER_H

View File

@@ -0,0 +1,42 @@
#version 420 core
out vec4 FragColor;
in vec3 Normal;
in vec3 FragPos;
in vec3 viewPos;
uniform vec3 lightPos;
uniform vec4 lightColor;
uniform vec4 meshColor;
struct Material {
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 emissive;
float shininess;
};
uniform Material material;
void main()
{
vec3 normal = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 halfwayDir = normalize(lightDir + viewDir);
// diffuse
float diff = max(dot(normal, lightDir), 0.0);
// specular
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec4 ambient = lightColor * material.ambient;
vec4 diffuse = lightColor * (diff * material.diffuse);
vec4 specular = lightColor * (spec *material.specular);
FragColor = ambient + diffuse + specular + material.emissive;
}

View File

@@ -0,0 +1,21 @@
#version 420 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 FragPos;
out vec3 Normal;
out vec3 viewPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 model_normal;
uniform vec3 view_position;
void main()
{
FragPos = vec3(model * vec4(aPos, 1.0f));
Normal = vec3(model_normal * vec4(aNormal, 1.0f));
viewPos = view_position;
gl_Position = projection * view * vec4(FragPos, 1.0f);
}

View File

@@ -0,0 +1,40 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "vao.h"
VAO::VAO()
{
glGenVertexArrays(1, &id);
}
void VAO::LinkAttrib(VBO& vbo, GLuint layout, GLuint numComponents, GLenum type, GLsizei stride, void* offset)
{
vbo.Bind();
glVertexAttribPointer(layout, numComponents, type, GL_FALSE, stride, offset);
glEnableVertexAttribArray(layout);
vbo.Unbind();
}
void VAO::Bind()
{
glBindVertexArray(id);
}
void VAO::Unbind()
{
glBindVertexArray(0);
}
void VAO::Delete()
{
glDeleteVertexArrays(1, &id);
}

View File

@@ -0,0 +1,30 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#ifndef VAO_H
#define VAO_H
#include <glad/glad.h>
#include "vbo.h"
class VAO
{
public:
GLuint id;
VAO();
void LinkAttrib(VBO& vbo, GLuint layout, GLuint numComponents, GLenum type, GLsizei stride, void* offset);
void Bind();
void Unbind();
void Delete();
};
#endif // VAO_H

View File

@@ -0,0 +1,34 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "vbo.h"
VBO::VBO(const std::vector<utils::geometry::Vertex> &vertices)
{
glGenBuffers(1, &id);
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(utils::geometry::Vertex), vertices.data(), GL_STATIC_DRAW);
}
void VBO::Bind()
{
glBindBuffer(GL_ARRAY_BUFFER, id);
}
void VBO::Unbind()
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void VBO::Delete()
{
glDeleteBuffers(1, &id);
}

View File

@@ -0,0 +1,32 @@
/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#ifndef VBO_H
#define VBO_H
#include <vector>
#include <glm/glm.hpp>
#include <glad/glad.h>
#include "../../utils/geometry.h"
class VBO
{
public:
GLuint id;
VBO(const std::vector<utils::geometry::Vertex> &vertices);
void Bind();
void Unbind();
void Delete();
};
#endif // VBO_H