fixed much stuff with bad usage of constructor mixed with virtual functions in gl stuff. added model loading with assimp.
This commit is contained in:
parent
aedda9d48e
commit
0105bfe430
17 changed files with 402 additions and 175 deletions
45
data/mesh/small_atomic_bomb.scad
Normal file
45
data/mesh/small_atomic_bomb.scad
Normal file
|
@ -0,0 +1,45 @@
|
|||
$fn = 12;
|
||||
|
||||
offset = 1.0;
|
||||
|
||||
r_inner = 0.2;
|
||||
r_outer = 0.5;
|
||||
|
||||
rotate([0,0,180]) {
|
||||
|
||||
hull() {
|
||||
// hull around the small base
|
||||
translate([offset, 0, 0]) sphere(r_inner);
|
||||
|
||||
// and the thick head
|
||||
sphere(r_outer);
|
||||
}
|
||||
|
||||
pipe_len=0.3;
|
||||
translate([offset, 0, 0]) {
|
||||
rotate([0,90,0]) cylinder(r=r_inner, pipe_len);
|
||||
}
|
||||
|
||||
// fins
|
||||
w = 0.5;
|
||||
h = 0.8 * r_outer;
|
||||
|
||||
difference() {
|
||||
// fin
|
||||
for (i=[0:4]) {
|
||||
rotate([i*90,0,0]) {
|
||||
translate([offset-w/2+pipe_len,0,-h/2]) {
|
||||
hull() {
|
||||
cube([w,0.05,0.01], center=true);
|
||||
rotate([0,-5,0]) {
|
||||
cube([w-0.2,0.05,h+0.15], center=true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cutout part near end of pipe
|
||||
//translate([pipe_len+offset,0,0]) sphere(0.25);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
|||
find_package(OpenGL REQUIRED)
|
||||
find_package(epoxy REQUIRED)
|
||||
find_package(X11 REQUIRED)
|
||||
find_package(assimp REQUIRED)
|
||||
|
||||
set(GAME_SRC
|
||||
main.cpp
|
||||
|
@ -34,7 +35,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
|||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/libs/glm/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/libs/asio/asio/include/)
|
||||
include_directories(${assimp_INCLUDE_DIRS})
|
||||
|
||||
add_executable(game ${GAME_SRC})
|
||||
setup_target(game)
|
||||
target_link_libraries(game X11 epoxy pthread)
|
||||
|
||||
target_link_libraries(game X11 epoxy pthread ${assimp_LIBRARIES} assimp)
|
||||
|
|
|
@ -20,16 +20,20 @@
|
|||
class GameWindow : public endofthejedi::GLWindow {
|
||||
private:
|
||||
Game* m_game;
|
||||
//endofthejedi::RendererPolygon2d m_renderer;
|
||||
endofthejedi::RendererPolygon2d m_renderer;
|
||||
//endofthejedi::RendererPolygon3d m_renderer;
|
||||
endofthejedi::RendererRayTracer m_renderer;
|
||||
//endofthejedi::RendererRayTracer m_renderer;
|
||||
|
||||
protected:
|
||||
void init() override {
|
||||
std::cout<<"init" << std::endl;
|
||||
|
||||
glClearColor(0.5f, 0.6f, 0.7f, 1.0f);
|
||||
resize();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
m_renderer.setup();
|
||||
}
|
||||
|
||||
void render(double time) override {
|
||||
|
|
|
@ -3,24 +3,30 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
endofthejedi::VAO::VAO() { glGenVertexArrays(1, &m_name); }
|
||||
namespace endofthejedi {
|
||||
VAO::VAO() { glGenVertexArrays(1, &m_name); }
|
||||
|
||||
endofthejedi::VAO::~VAO() { glDeleteVertexArrays(1, &m_name); }
|
||||
VAO::~VAO() { glDeleteVertexArrays(1, &m_name); }
|
||||
|
||||
void endofthejedi::VAO::bind() { glBindVertexArray(m_name); }
|
||||
void VAO::bind() { glBindVertexArray(m_name); }
|
||||
|
||||
void endofthejedi::VAO::fill(GLuint index, GLint size, GLenum type,
|
||||
void VAO::fill(GLuint index, GLint size, GLenum type,
|
||||
GLboolean normalized, GLsizei stride,
|
||||
const GLvoid *pointer) {
|
||||
const GLvoid *pointer)
|
||||
{
|
||||
(void) type;
|
||||
|
||||
glEnableVertexAttribArray(index);
|
||||
glVertexAttribPointer(index, size, GL_FLOAT, normalized, stride, pointer);
|
||||
}
|
||||
}
|
||||
|
||||
endofthejedi::Shader::Shader() { m_program = glCreateProgram(); }
|
||||
Shader::Shader() : m_program(0) { }
|
||||
|
||||
endofthejedi::Shader::~Shader() {}
|
||||
Shader::~Shader() {}
|
||||
|
||||
bool endofthejedi::Shader::check() {
|
||||
void Shader::init() { m_program = glCreateProgram(); }
|
||||
|
||||
bool Shader::check() {
|
||||
GLint len = 0;
|
||||
GLint result = 0;
|
||||
|
||||
|
@ -30,15 +36,14 @@ bool endofthejedi::Shader::check() {
|
|||
char *error = (char *)malloc(len);
|
||||
glGetProgramInfoLog(m_program, len, NULL, error);
|
||||
std::string str(error);
|
||||
std::cout << str << "\n";
|
||||
std::cout << str << std::endl;
|
||||
}
|
||||
std::cout << "checked program"
|
||||
<< "\n";
|
||||
std::cout << "checked program" << std::endl;
|
||||
|
||||
return (bool)result;
|
||||
}
|
||||
}
|
||||
|
||||
bool endofthejedi::Shader::checkShader(GLuint shader) {
|
||||
bool Shader::checkShader(GLuint shader) {
|
||||
GLint len = 0;
|
||||
GLint result = 0;
|
||||
|
||||
|
@ -48,19 +53,25 @@ bool endofthejedi::Shader::checkShader(GLuint shader) {
|
|||
char *error = (char *)malloc(len+1);
|
||||
glGetShaderInfoLog(shader, 0, &len, error);
|
||||
std::string str(error, error + len);
|
||||
std::cout << str << "\n";
|
||||
std::cout << str << std::endl;
|
||||
}
|
||||
std::cout << "checked shader"
|
||||
<< "\n";
|
||||
|
||||
std::cout << "checked shader" << std::endl;
|
||||
|
||||
return (bool)result;
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::Shader::bind() { glUseProgram(m_program); }
|
||||
void Shader::bind() { glUseProgram(m_program); }
|
||||
|
||||
void endofthejedi::Shader::unbind() { glUseProgram(0); }
|
||||
void Shader::unbind() { glUseProgram(0); }
|
||||
|
||||
void Shader::load(const std::string &path, GLenum shadertype) {
|
||||
if (m_program == 0) {
|
||||
std::cout<<"[shader] error: shader program is invalid (0)!" << std::endl;
|
||||
exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
void endofthejedi::Shader::load(std::string path, GLenum shadertype) {
|
||||
GLuint cheddar = glCreateShader(shadertype);
|
||||
const char *cheddardata = path.c_str();
|
||||
glShaderSource(cheddar, 1, &cheddardata, NULL);
|
||||
|
@ -70,8 +81,9 @@ void endofthejedi::Shader::load(std::string path, GLenum shadertype) {
|
|||
glLinkProgram(m_program);
|
||||
check();
|
||||
glDeleteShader(cheddar);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint endofthejedi::Shader::location(std::string name) {
|
||||
GLuint Shader::location(const std::string &name) {
|
||||
return glGetUniformLocation(m_program, name.c_str());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ class VAO {
|
|||
class Shader {
|
||||
private:
|
||||
GLuint m_program;
|
||||
|
||||
bool check();
|
||||
bool checkShader(GLuint shader);
|
||||
|
||||
|
@ -50,10 +51,12 @@ class Shader {
|
|||
public:
|
||||
Shader();
|
||||
~Shader();
|
||||
void init(); // call to init when opengl context exists
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
void load(std::string data, GLenum shadertype);
|
||||
GLuint location(std::string name);
|
||||
void load(const std::string &data, GLenum shadertype);
|
||||
GLuint location(const std::string &name);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
GameWindow window(500, 500, &game);
|
||||
window.set_maxfps(60.0);
|
||||
window.open();
|
||||
|
||||
while(window.running()){
|
||||
window.poll();
|
||||
|
|
|
@ -19,8 +19,14 @@ timespec diff(timespec start, timespec end) {
|
|||
return result;
|
||||
}
|
||||
|
||||
endofthejedi::GLWindow::GLWindow(unsigned int width, unsigned int height)
|
||||
: m_width(width), m_height(height) {
|
||||
namespace endofthejedi {
|
||||
|
||||
GLWindow::GLWindow(unsigned int width, unsigned int height) : m_width(width), m_height(height)
|
||||
{
|
||||
}
|
||||
|
||||
void GLWindow::open()
|
||||
{
|
||||
m_display = XOpenDisplay(NULL);
|
||||
|
||||
if (m_display == NULL) {
|
||||
|
@ -42,7 +48,7 @@ endofthejedi::GLWindow::GLWindow(unsigned int width, unsigned int height)
|
|||
m_swa.event_mask = ExposureMask | KeyPressMask;
|
||||
|
||||
m_window = XCreateWindow(
|
||||
m_display, m_rootwnd, 0, 0, width, height, 0, m_visualinfo->depth,
|
||||
m_display, m_rootwnd, 0, 0, m_width, m_height, 0, m_visualinfo->depth,
|
||||
InputOutput, m_visualinfo->visual, CWColormap | CWEventMask, &m_swa);
|
||||
|
||||
m_atomWmDeleteWindow = XInternAtom(m_display, "WM_DELETE_WINDOW", False);
|
||||
|
@ -62,29 +68,31 @@ endofthejedi::GLWindow::GLWindow(unsigned int width, unsigned int height)
|
|||
std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION)
|
||||
<< "\n";
|
||||
|
||||
m_running = true;
|
||||
|
||||
init();
|
||||
|
||||
XClearWindow(m_display, m_window);
|
||||
XMapRaised(m_display, m_window);
|
||||
}
|
||||
}
|
||||
|
||||
endofthejedi::GLWindow::~GLWindow() {
|
||||
GLWindow::~GLWindow() {
|
||||
glXMakeCurrent(m_display, None, NULL);
|
||||
glXDestroyContext(m_display, m_glcontext);
|
||||
XFree(m_visualinfo);
|
||||
XDestroyWindow(m_display, m_window);
|
||||
XCloseDisplay(m_display);
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::handleevents() {
|
||||
void GLWindow::handleevents() {
|
||||
if (XPending(m_display) > 0) {
|
||||
XEvent xev;
|
||||
XNextEvent(m_display, &xev);
|
||||
handle(xev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::handle(XEvent event) {
|
||||
void GLWindow::handle(XEvent event) {
|
||||
if (event.type == Expose) {
|
||||
XWindowAttributes attribs;
|
||||
XGetWindowAttributes(m_display, m_window, &attribs);
|
||||
|
@ -98,11 +106,11 @@ void endofthejedi::GLWindow::handle(XEvent event) {
|
|||
} else if (event.type == DestroyNotify) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
||||
void GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
||||
|
||||
void endofthejedi::GLWindow::poll() {
|
||||
void GLWindow::poll() {
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &prev);
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
|
||||
|
@ -126,10 +134,11 @@ void endofthejedi::GLWindow::poll() {
|
|||
m_fps = (1000000000.0/delta);
|
||||
//std::cout << m_fps << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::stop() { m_running = false; }
|
||||
bool endofthejedi::GLWindow::running() { return m_running; }
|
||||
void endofthejedi::GLWindow::init() { m_running = true; }
|
||||
void endofthejedi::GLWindow::render(double time) { UNUSED(time) }
|
||||
void endofthejedi::GLWindow::resize() {}
|
||||
void GLWindow::stop() { m_running = false; }
|
||||
bool GLWindow::running() { return m_running; }
|
||||
void GLWindow::init() { }
|
||||
void GLWindow::render(double time) { UNUSED(time) }
|
||||
void GLWindow::resize() {}
|
||||
}
|
||||
|
|
|
@ -67,10 +67,14 @@ namespace endofthejedi {
|
|||
virtual void handleevents();
|
||||
|
||||
public:
|
||||
//initializes the X Window & creates an OpenGL context
|
||||
// create the class. call open() afterwards
|
||||
GLWindow(unsigned int width, unsigned int height);
|
||||
|
||||
~GLWindow();
|
||||
|
||||
//initializes the X Window & creates an OpenGL context
|
||||
void open();
|
||||
|
||||
//mainloop does event handling & calls render/swap
|
||||
void poll();
|
||||
void swap();
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
#include "renderer_polygon_2d.hpp"
|
||||
|
||||
namespace endofthejedi {
|
||||
void RendererPolygon2d::setup()
|
||||
{
|
||||
// (dark grey) bg
|
||||
float r = 0.1;
|
||||
float g = 0.1;
|
||||
float b = 0.1;
|
||||
glClearColor(r, g, b, 1.0);
|
||||
}
|
||||
|
||||
void RendererPolygon2d::drawCircle(float x, float y, float radius,
|
||||
float r, float g, float b,
|
||||
int numSides) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
namespace endofthejedi {
|
||||
|
||||
class RendererPolygon2d : Renderer {
|
||||
class RendererPolygon2d : public Renderer {
|
||||
private:
|
||||
void drawCircle(float x, float y, float radius, float r, float g,
|
||||
float b, int numSides = 12);
|
||||
|
@ -27,7 +27,9 @@ namespace endofthejedi {
|
|||
void drawExplosion(const game::Explosion *explosion);
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
void setup() override;
|
||||
void render(const game::State *state) override;
|
||||
};
|
||||
|
||||
|
|
0
game/renderer_polygon_3d/polygon_model.cpp
Normal file
0
game/renderer_polygon_3d/polygon_model.cpp
Normal file
116
game/renderer_polygon_3d/polygon_model.hpp
Normal file
116
game/renderer_polygon_3d/polygon_model.hpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <assimp/Importer.hpp> // C++ importer interface
|
||||
#include <assimp/scene.h> // Output data structure
|
||||
#include <assimp/postprocess.h> // Post processing flags
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
#include <epoxy/glx.h>
|
||||
|
||||
class PolygonModel {
|
||||
public:
|
||||
PolygonModel(const std::string &filename) : m_filename(filename)
|
||||
{
|
||||
if (!import()) {
|
||||
m_loaded = false;
|
||||
|
||||
} else {
|
||||
m_loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool import()
|
||||
{
|
||||
// Create an instance of the Importer class
|
||||
Assimp::Importer importer;
|
||||
// And have it read the given file with some example postprocessing
|
||||
// Usually - if speed is not the most important aspect for you - you'll
|
||||
// propably to request more postprocessing than we do in this example.
|
||||
const aiScene* scene = importer.ReadFile(m_filename,
|
||||
aiProcess_CalcTangentSpace |
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_JoinIdenticalVertices |
|
||||
aiProcess_SortByPType);
|
||||
|
||||
// If the import failed, report it
|
||||
if (!scene) {
|
||||
std::cout<<"[polygonmodel] loading file "
|
||||
<< m_filename << " failed with: "
|
||||
<< importer.GetErrorString() << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now we can access the file's contents.
|
||||
copyVertices(scene);
|
||||
|
||||
// We're done. Everything will be cleaned up by the importer destructor
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool copyVertices(const aiScene *scene)
|
||||
{
|
||||
if (scene->mMeshes == 0) {
|
||||
std::cout << "[polygonmodel : no meshes loaded for " << m_filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
aiNode *node = scene->mRootNode;
|
||||
const aiMesh* mesh = scene->mMeshes[node->mMeshes[0]];
|
||||
|
||||
// 3 vertices per face, 3 floats per vertex
|
||||
m_numVertices = mesh->mNumFaces*3;
|
||||
|
||||
m_data_position.reserve(m_numVertices);
|
||||
m_data_normal.reserve(m_numVertices);
|
||||
|
||||
size_t t, i;
|
||||
for (t=0; t<mesh->mNumFaces; ++t) {
|
||||
const aiFace* face = &mesh->mFaces[t];
|
||||
if (face->mNumIndices != 3) {
|
||||
std::cout << "[polygonmodel] need triangles, got something different with: "
|
||||
<< face->mNumIndices << " vertices" << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i=0; i<face->mNumIndices; i++) {
|
||||
const size_t index = face->mIndices[i];
|
||||
m_data_position.push_back(mesh->mVertices[index].x);
|
||||
m_data_position.push_back(mesh->mVertices[index].y);
|
||||
m_data_position.push_back(mesh->mVertices[index].z);
|
||||
|
||||
m_data_normal.push_back(mesh->mNormals[index].x);
|
||||
m_data_normal.push_back(mesh->mNormals[index].y);
|
||||
m_data_normal.push_back(mesh->mNormals[index].z);
|
||||
}
|
||||
}
|
||||
|
||||
size_t totalBytes = 3*m_numVertices*sizeof(float);
|
||||
std::cout<<"[polygonmodel] loaded " << m_numVertices << " vertices ("
|
||||
<< totalBytes << " bytes)" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &filename() const { return m_filename; }
|
||||
bool ready() const { return m_loaded; }
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
bool m_loaded;
|
||||
|
||||
size_t m_numVertices;
|
||||
|
||||
// both will hold 3 * numVertices floats
|
||||
std::vector<float> m_data_position;
|
||||
std::vector<float> m_data_normal;
|
||||
|
||||
GLuint m_vbo_id_position;
|
||||
GLuint m_vbo_id_normal;
|
||||
};
|
||||
|
|
@ -2,16 +2,21 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include "polygon_model.hpp"
|
||||
|
||||
namespace endofthejedi {
|
||||
void RendererPolygon3d::setup()
|
||||
{
|
||||
std::cout<<"setup 3d" << std::endl;
|
||||
|
||||
PolygonModel atomicBomb("../data/mesh/small_atomic_bomb.stl");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void RendererPolygon3d::render(const game::State *state)
|
||||
{
|
||||
(void) state;
|
||||
|
||||
//std::cout<<"render 3d" << std::endl;
|
||||
std::cout<<"render 3d" << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,18 @@
|
|||
#include "state/ship.hpp"
|
||||
#include "state/explosion.hpp"
|
||||
|
||||
class PolygonModel;
|
||||
|
||||
namespace endofthejedi {
|
||||
|
||||
class RendererPolygon3d : Renderer {
|
||||
class RendererPolygon3d : public Renderer {
|
||||
private:
|
||||
protected:
|
||||
public:
|
||||
void setup();
|
||||
void render(const game::State *state) override;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<PolygonModel*> m_models;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,7 +16,13 @@ static const char *fss =
|
|||
|
||||
|
||||
namespace endofthejedi {
|
||||
RendererRayTracer::RendererRayTracer() {
|
||||
RendererRayTracer::RendererRayTracer()
|
||||
{
|
||||
}
|
||||
|
||||
void RendererRayTracer::setup()
|
||||
{
|
||||
m_shader.init();
|
||||
m_shader.load(vss, GL_VERTEX_SHADER);
|
||||
m_shader.load(fss, GL_FRAGMENT_SHADER);
|
||||
}
|
||||
|
|
|
@ -11,12 +11,14 @@
|
|||
|
||||
namespace endofthejedi {
|
||||
|
||||
class RendererRayTracer: Renderer {
|
||||
class RendererRayTracer : public Renderer {
|
||||
private:
|
||||
Shader m_shader;
|
||||
protected:
|
||||
public:
|
||||
RendererRayTracer();
|
||||
|
||||
void setup() override;
|
||||
void render(const game::State *state) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,9 @@ namespace game {
|
|||
// TODO: idea
|
||||
// shoot multiple rockets at once or from different positions after
|
||||
// level up / upgrade ...
|
||||
Missile *missile = new Missile(player, player->ship->position, util::deg2rad(m_angle), player->speed);
|
||||
|
||||
// angles are supplied in degrees and are CCW
|
||||
Missile *missile = new Missile(player, player->ship->position, -util::deg2rad(m_angle), player->speed);
|
||||
|
||||
Trace *trace = new Trace(missile);
|
||||
missile->trace = trace;
|
||||
|
|
Loading…
Reference in a new issue