added files
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace planetarium {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Camera
|
||||
//
|
||||
// A custom orbital ("arcball") camera. It orbits a focus point at a
|
||||
// controllable yaw/pitch/distance, with all parameters critically-damped
|
||||
// toward their target values every frame so camera moves - including
|
||||
// "focus on selected planet" - feel like smooth, cinematic transitions
|
||||
// rather than instant snaps.
|
||||
// -----------------------------------------------------------------------
|
||||
class Camera {
|
||||
public:
|
||||
Camera();
|
||||
|
||||
// Input handlers - called directly from Engine's GLFW callbacks.
|
||||
void onMouseDrag(float deltaX, float deltaY);
|
||||
void onMousePan(float deltaX, float deltaY);
|
||||
void onScroll(float deltaY);
|
||||
void reset();
|
||||
|
||||
// Smoothly re-targets the orbit focus to a world-space point (e.g. a
|
||||
// selected planet's position) and optionally suggests a nice viewing
|
||||
// distance for that object's scale.
|
||||
void focusOn(const glm::vec3& worldPoint, float suggestedDistance);
|
||||
|
||||
// Advances the smoothing/interpolation. Must be called once per frame
|
||||
// with the frame's delta time in seconds.
|
||||
void update(float deltaTime);
|
||||
|
||||
glm::mat4 viewMatrix() const;
|
||||
glm::vec3 position() const { return currentPosition_; }
|
||||
glm::vec3 focusPoint() const { return currentFocus_; }
|
||||
|
||||
float distance() const { return currentDistance_; }
|
||||
|
||||
private:
|
||||
// Target (goal) state, set instantly by input; current state chases
|
||||
// it every update() call using exponential smoothing.
|
||||
float targetYaw_ = -0.6f;
|
||||
float targetPitch_ = 0.45f;
|
||||
float targetDistance_ = 18.0f;
|
||||
glm::vec3 targetFocus_{0.0f};
|
||||
|
||||
float currentYaw_ = -0.6f;
|
||||
float currentPitch_ = 0.45f;
|
||||
float currentDistance_ = 18.0f;
|
||||
glm::vec3 currentFocus_{0.0f};
|
||||
glm::vec3 currentPosition_{0.0f};
|
||||
|
||||
static constexpr float kMinPitch = -1.45f;
|
||||
static constexpr float kMaxPitch = 1.45f;
|
||||
static constexpr float kMinDistance = 2.0f;
|
||||
static constexpr float kMaxDistance = 400.0f;
|
||||
static constexpr float kSmoothingSpeed = 6.0f;
|
||||
};
|
||||
|
||||
} // namespace planetarium
|
||||
@@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "Camera.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
namespace planetarium {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Engine
|
||||
//
|
||||
// Top-level owner of the GLFW window/context, the frame loop, and input
|
||||
// routing between raw GLFW callbacks and the Camera. This is the only
|
||||
// class that knows about GLFW directly.
|
||||
//
|
||||
// This is the reusable "engine" half of the original Planetarium project
|
||||
// with every game-specific piece (SolarSystem, Planet, UI, picking)
|
||||
// removed. Hook your own logic in via setUpdateCallback/setRenderCallback:
|
||||
//
|
||||
// Engine engine;
|
||||
// engine.initialize(1600, 900, "My App");
|
||||
// engine.setUpdateCallback([](float dt) { ... });
|
||||
// engine.setRenderCallback([&](int fbWidth, int fbHeight) { ... });
|
||||
// engine.run();
|
||||
//
|
||||
// Left-drag orbits the camera, middle-drag pans it, scroll zooms, and R
|
||||
// resets it - wire up more input in your own update/render callbacks via
|
||||
// window() if you need it.
|
||||
// -----------------------------------------------------------------------
|
||||
class Engine {
|
||||
public:
|
||||
using UpdateCallback = std::function<void(float deltaTime)>;
|
||||
using RenderCallback = std::function<void(int framebufferWidth, int framebufferHeight)>;
|
||||
|
||||
~Engine();
|
||||
|
||||
bool initialize(int width, int height, const char* title);
|
||||
void run();
|
||||
|
||||
void setUpdateCallback(UpdateCallback cb) { updateCallback_ = std::move(cb); }
|
||||
void setRenderCallback(RenderCallback cb) { renderCallback_ = std::move(cb); }
|
||||
|
||||
Camera& camera() { return camera_; }
|
||||
const Camera& camera() const { return camera_; }
|
||||
GLFWwindow* window() const { return window_; }
|
||||
|
||||
private:
|
||||
void update(float deltaTime);
|
||||
void render();
|
||||
|
||||
// GLFW callback trampolines (static -> instance via glfwGetWindowUserPointer).
|
||||
static void cursorPosCallback(GLFWwindow* window, double x, double y);
|
||||
static void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
|
||||
static void scrollCallback(GLFWwindow* window, double xOffset, double yOffset);
|
||||
static void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||
static void framebufferSizeCallback(GLFWwindow* window, int width, int height);
|
||||
|
||||
GLFWwindow* window_ = nullptr;
|
||||
Camera camera_;
|
||||
|
||||
UpdateCallback updateCallback_;
|
||||
RenderCallback renderCallback_;
|
||||
|
||||
int framebufferWidth_ = 1600;
|
||||
int framebufferHeight_ = 900;
|
||||
|
||||
double lastMouseX_ = 0.0;
|
||||
double lastMouseY_ = 0.0;
|
||||
bool rotating_ = false;
|
||||
bool panning_ = false;
|
||||
|
||||
double lastFrameTime_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace planetarium
|
||||
@@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// GLFunctions
|
||||
//
|
||||
// Linux distributions only ship GL/gl.h with legacy (<=1.1/1.2) function
|
||||
// declarations; everything from OpenGL 1.5 onward (VAOs/VBOs, GLSL
|
||||
// shaders, etc.) must be resolved at runtime as function pointers. This
|
||||
// is a small, self-contained loader for exactly the subset of OpenGL 3.3
|
||||
// core functions this project's renderer uses. It is intentionally
|
||||
// separate from Dear ImGui's own bundled loader (imgui_impl_opengl3_loader.h)
|
||||
// to avoid the multiple-definition problems that occur when two GL
|
||||
// loaders are mixed in the same program - see the comment at the top of
|
||||
// that file for details.
|
||||
//
|
||||
// Usage: call planetarium::gl::loadGLFunctions() exactly once, right
|
||||
// after the GLFW OpenGL context has been made current and before any
|
||||
// other GL call in the project's own rendering code.
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <cstddef>
|
||||
|
||||
#ifndef GL_ARRAY_BUFFER
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#endif
|
||||
#ifndef GL_ELEMENT_ARRAY_BUFFER
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#endif
|
||||
#ifndef GL_STATIC_DRAW
|
||||
#define GL_STATIC_DRAW 0x88E4
|
||||
#endif
|
||||
#ifndef GL_DYNAMIC_DRAW
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
#endif
|
||||
#ifndef GL_FRAGMENT_SHADER
|
||||
#define GL_FRAGMENT_SHADER 0x8B30
|
||||
#endif
|
||||
#ifndef GL_VERTEX_SHADER
|
||||
#define GL_VERTEX_SHADER 0x8B31
|
||||
#endif
|
||||
#ifndef GL_COMPILE_STATUS
|
||||
#define GL_COMPILE_STATUS 0x8B81
|
||||
#endif
|
||||
#ifndef GL_LINK_STATUS
|
||||
#define GL_LINK_STATUS 0x8B82
|
||||
#endif
|
||||
#ifndef GL_TEXTURE0
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
#endif
|
||||
#ifndef GL_PROGRAM_POINT_SIZE
|
||||
#define GL_PROGRAM_POINT_SIZE 0x8642
|
||||
#endif
|
||||
#ifndef GL_CLAMP_TO_EDGE
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
#endif
|
||||
#ifndef GL_MULTISAMPLE
|
||||
#define GL_MULTISAMPLE 0x809D
|
||||
#endif
|
||||
#ifndef GL_MAJOR_VERSION
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#endif
|
||||
#ifndef GL_MINOR_VERSION
|
||||
#define GL_MINOR_VERSION 0x821C
|
||||
#endif
|
||||
|
||||
typedef char GLchar;
|
||||
typedef ptrdiff_t GLsizeiptr;
|
||||
typedef ptrdiff_t GLintptr;
|
||||
|
||||
namespace planetarium::gl {
|
||||
|
||||
using PFNGLGENVERTEXARRAYS = void (*)(GLsizei, GLuint*);
|
||||
using PFNGLBINDVERTEXARRAY = void (*)(GLuint);
|
||||
using PFNGLDELETEVERTEXARRAYS = void (*)(GLsizei, const GLuint*);
|
||||
using PFNGLGENBUFFERS = void (*)(GLsizei, GLuint*);
|
||||
using PFNGLBINDBUFFER = void (*)(GLenum, GLuint);
|
||||
using PFNGLBUFFERDATA = void (*)(GLenum, GLsizeiptr, const void*, GLenum);
|
||||
using PFNGLDELETEBUFFERS = void (*)(GLsizei, const GLuint*);
|
||||
using PFNGLVERTEXATTRIBPOINTER = void (*)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void*);
|
||||
using PFNGLENABLEVERTEXATTRIBARRAY = void (*)(GLuint);
|
||||
using PFNGLDISABLEVERTEXATTRIBARRAY = void (*)(GLuint);
|
||||
|
||||
using PFNGLCREATESHADER = GLuint (*)(GLenum);
|
||||
using PFNGLSHADERSOURCE = void (*)(GLuint, GLsizei, const GLchar* const*, const GLint*);
|
||||
using PFNGLCOMPILESHADER = void (*)(GLuint);
|
||||
using PFNGLGETSHADERIV = void (*)(GLuint, GLenum, GLint*);
|
||||
using PFNGLGETSHADERINFOLOG = void (*)(GLuint, GLsizei, GLsizei*, GLchar*);
|
||||
using PFNGLDELETESHADER = void (*)(GLuint);
|
||||
using PFNGLCREATEPROGRAM = GLuint (*)();
|
||||
using PFNGLATTACHSHADER = void (*)(GLuint, GLuint);
|
||||
using PFNGLLINKPROGRAM = void (*)(GLuint);
|
||||
using PFNGLGETPROGRAMIV = void (*)(GLuint, GLenum, GLint*);
|
||||
using PFNGLGETPROGRAMINFOLOG = void (*)(GLuint, GLsizei, GLsizei*, GLchar*);
|
||||
using PFNGLUSEPROGRAM = void (*)(GLuint);
|
||||
using PFNGLDELETEPROGRAM = void (*)(GLuint);
|
||||
|
||||
using PFNGLGETUNIFORMLOCATION = GLint (*)(GLuint, const GLchar*);
|
||||
using PFNGLUNIFORMMATRIX4FV = void (*)(GLint, GLsizei, GLboolean, const GLfloat*);
|
||||
using PFNGLUNIFORM3FV = void (*)(GLint, GLsizei, const GLfloat*);
|
||||
using PFNGLUNIFORM4FV = void (*)(GLint, GLsizei, const GLfloat*);
|
||||
using PFNGLUNIFORM1F = void (*)(GLint, GLfloat);
|
||||
using PFNGLUNIFORM1I = void (*)(GLint, GLint);
|
||||
using PFNGLACTIVETEXTURE = void (*)(GLenum);
|
||||
using PFNGLGENERATEMIPMAP = void (*)(GLenum);
|
||||
|
||||
extern PFNGLGENVERTEXARRAYS glGenVertexArrays;
|
||||
extern PFNGLBINDVERTEXARRAY glBindVertexArray;
|
||||
extern PFNGLDELETEVERTEXARRAYS glDeleteVertexArrays;
|
||||
extern PFNGLGENBUFFERS glGenBuffers;
|
||||
extern PFNGLBINDBUFFER glBindBuffer;
|
||||
extern PFNGLBUFFERDATA glBufferData;
|
||||
extern PFNGLDELETEBUFFERS glDeleteBuffers;
|
||||
extern PFNGLVERTEXATTRIBPOINTER glVertexAttribPointer;
|
||||
extern PFNGLENABLEVERTEXATTRIBARRAY glEnableVertexAttribArray;
|
||||
extern PFNGLDISABLEVERTEXATTRIBARRAY glDisableVertexAttribArray;
|
||||
|
||||
extern PFNGLCREATESHADER glCreateShader;
|
||||
extern PFNGLSHADERSOURCE glShaderSource;
|
||||
extern PFNGLCOMPILESHADER glCompileShader;
|
||||
extern PFNGLGETSHADERIV glGetShaderiv;
|
||||
extern PFNGLGETSHADERINFOLOG glGetShaderInfoLog;
|
||||
extern PFNGLDELETESHADER glDeleteShader;
|
||||
extern PFNGLCREATEPROGRAM glCreateProgram;
|
||||
extern PFNGLATTACHSHADER glAttachShader;
|
||||
extern PFNGLLINKPROGRAM glLinkProgram;
|
||||
extern PFNGLGETPROGRAMIV glGetProgramiv;
|
||||
extern PFNGLGETPROGRAMINFOLOG glGetProgramInfoLog;
|
||||
extern PFNGLUSEPROGRAM glUseProgram;
|
||||
extern PFNGLDELETEPROGRAM glDeleteProgram;
|
||||
|
||||
extern PFNGLGETUNIFORMLOCATION glGetUniformLocation;
|
||||
extern PFNGLUNIFORMMATRIX4FV glUniformMatrix4fv;
|
||||
extern PFNGLUNIFORM3FV glUniform3fv;
|
||||
extern PFNGLUNIFORM4FV glUniform4fv;
|
||||
extern PFNGLUNIFORM1F glUniform1f;
|
||||
extern PFNGLUNIFORM1I glUniform1i;
|
||||
extern PFNGLACTIVETEXTURE glActiveTexture;
|
||||
extern PFNGLGENERATEMIPMAP glGenerateMipmap;
|
||||
|
||||
// Resolves every function pointer above via glfwGetProcAddress. Must be
|
||||
// called once, after glfwMakeContextCurrent(). Returns false if any
|
||||
// required entry point could not be resolved.
|
||||
bool loadGLFunctions();
|
||||
|
||||
} // namespace planetarium::gl
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "GLFunctions.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace planetarium {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Mesh
|
||||
//
|
||||
// Owns a VAO/VBO/(optional)EBO describing an interleaved
|
||||
// position+normal+uv vertex stream, plus static factory methods that
|
||||
// procedurally build a few common primitive shapes (spheres, rings,
|
||||
// circles) so a project has no dependency on external model files.
|
||||
// -----------------------------------------------------------------------
|
||||
struct Vertex {
|
||||
glm::vec3 position;
|
||||
glm::vec3 normal;
|
||||
glm::vec2 uv;
|
||||
};
|
||||
|
||||
class Mesh {
|
||||
public:
|
||||
Mesh() = default;
|
||||
~Mesh();
|
||||
|
||||
Mesh(const Mesh&) = delete;
|
||||
Mesh& operator=(const Mesh&) = delete;
|
||||
Mesh(Mesh&& other) noexcept;
|
||||
Mesh& operator=(Mesh&& other) noexcept;
|
||||
|
||||
void upload(const std::vector<Vertex>& vertices, const std::vector<unsigned int>& indices);
|
||||
void uploadLineStrip(const std::vector<glm::vec3>& points);
|
||||
void draw() const;
|
||||
void drawLineStrip() const;
|
||||
|
||||
static Mesh createUVSphere(int stacks, int slices);
|
||||
static Mesh createRing(float innerRadius, float outerRadius, int segments);
|
||||
static Mesh createOrbitCircle(int segments); // unit circle in XZ
|
||||
|
||||
private:
|
||||
void release();
|
||||
|
||||
GLuint vao_ = 0;
|
||||
GLuint vbo_ = 0;
|
||||
GLuint ebo_ = 0;
|
||||
GLsizei indexCount_ = 0;
|
||||
GLsizei vertexCount_ = 0;
|
||||
bool isLineStrip_ = false;
|
||||
};
|
||||
|
||||
} // namespace planetarium
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "GLFunctions.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace planetarium {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Shader
|
||||
//
|
||||
// Thin RAII wrapper around a linked OpenGL program object, compiled from
|
||||
// a vertex + fragment shader pair loaded from disk.
|
||||
// -----------------------------------------------------------------------
|
||||
class Shader {
|
||||
public:
|
||||
Shader() = default;
|
||||
~Shader();
|
||||
|
||||
Shader(const Shader&) = delete;
|
||||
Shader& operator=(const Shader&) = delete;
|
||||
Shader(Shader&& other) noexcept;
|
||||
Shader& operator=(Shader&& other) noexcept;
|
||||
|
||||
// Compiles and links the program. Returns false (and logs to stderr)
|
||||
// on failure; the shader remains unusable but the caller can continue
|
||||
// running with a null program.
|
||||
bool loadFromFiles(const std::string& vertexPath, const std::string& fragmentPath);
|
||||
|
||||
void use() const;
|
||||
GLuint id() const { return program_; }
|
||||
|
||||
void setMat4(const std::string& name, const glm::mat4& m) const;
|
||||
void setVec3(const std::string& name, const glm::vec3& v) const;
|
||||
void setVec4(const std::string& name, const glm::vec4& v) const;
|
||||
void setFloat(const std::string& name, float f) const;
|
||||
void setInt(const std::string& name, int i) const;
|
||||
|
||||
private:
|
||||
GLuint program_ = 0;
|
||||
GLint locationOf(const std::string& name) const;
|
||||
};
|
||||
|
||||
} // namespace planetarium
|
||||
Reference in New Issue
Block a user