rebuild structure.
This commit is contained in:
parent
5b3c598744
commit
3a24f4e1e9
24 changed files with 25 additions and 380 deletions
31
game/CMakeLists.txt
Normal file
31
game/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
||||
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(epoxy REQUIRED)
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
set(GAME_SRC
|
||||
main.cpp
|
||||
opengl.cpp
|
||||
glclasses.cpp
|
||||
config.cpp
|
||||
simulation.cpp
|
||||
renderer.cpp
|
||||
)
|
||||
|
||||
set(GAME_HEADERS
|
||||
opengl.h
|
||||
glclasses.h
|
||||
vector.h
|
||||
config.h
|
||||
simulation.h
|
||||
renderer.h
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
|
||||
add_executable(game ${GAME_SRC} ${GAME_HEADERS})
|
||||
setup_target(game)
|
||||
target_link_libraries(game X11 epoxy)
|
||||
2
game/config.cpp
Normal file
2
game/config.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#include "config.h"
|
||||
|
||||
33
game/config.h
Normal file
33
game/config.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
struct Config {
|
||||
int maxPlayers;
|
||||
int numPlanets;
|
||||
int maxSegments;
|
||||
int segmentSteps;
|
||||
int numShots;
|
||||
int fastmode;
|
||||
int fullscreen;
|
||||
int timeout;
|
||||
int margintop;
|
||||
int marginleft;
|
||||
int marginright;
|
||||
int marginbottom;
|
||||
double playerSize;
|
||||
int energy;
|
||||
int realtime;
|
||||
int debug;
|
||||
double battlefieldW;
|
||||
double battlefieldH;
|
||||
int throttle;
|
||||
char* ip;
|
||||
char* message;
|
||||
int pot;
|
||||
int area;
|
||||
};
|
||||
|
||||
class ConfigParser{
|
||||
private:
|
||||
protected:
|
||||
public:
|
||||
};
|
||||
39
game/glclasses.cpp
Normal file
39
game/glclasses.cpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include "glclasses.h"
|
||||
|
||||
endofthejedi::VAO::VAO() { glGenVertexArrays(1, &m_name); }
|
||||
|
||||
endofthejedi::VAO::~VAO() { glDeleteVertexArrays(1, &m_name); }
|
||||
|
||||
void endofthejedi::VAO::bind() { glBindVertexArray(m_name); }
|
||||
|
||||
void endofthejedi::VAO::fill(GLuint index, GLint size, GLenum type,
|
||||
GLboolean normalized, GLsizei stride,
|
||||
const GLvoid *pointer) {
|
||||
glEnableVertexAttribArray(index);
|
||||
glVertexAttribPointer(index, size, GL_FLOAT, normalized, stride, pointer);
|
||||
}
|
||||
|
||||
endofthejedi::Shader::Shader() {
|
||||
m_program = glCreateProgram();
|
||||
}
|
||||
|
||||
endofthejedi::Shader::~Shader() {}
|
||||
|
||||
void endofthejedi::Shader::bind() {
|
||||
glUseProgram(m_program);
|
||||
}
|
||||
|
||||
void endofthejedi::Shader::unbind() {
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void endofthejedi::Shader::load(std::string path, GLenum shadertype) {
|
||||
GLuint cheddar = glCreateShader(shadertype);
|
||||
const char* cheddardata = path.c_str();
|
||||
glShaderSource(cheddar, 1, &cheddardata, NULL);
|
||||
glCompileShader(cheddar);
|
||||
glAttachShader(m_program, cheddar);
|
||||
glLinkProgram(m_program);
|
||||
glDeleteShader(cheddar);
|
||||
}
|
||||
|
||||
83
game/glclasses.h
Normal file
83
game/glclasses.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#pragma once
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
#include <epoxy/glx.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace endofthejedi {
|
||||
|
||||
template <GLenum T> class BufferObject {
|
||||
private:
|
||||
GLuint m_name;
|
||||
GLvoid* m_mappointer;
|
||||
protected:
|
||||
public:
|
||||
BufferObject();
|
||||
~BufferObject();
|
||||
void bind();
|
||||
void bind(GLuint index, GLintptr offset = 0, GLsizeiptr size = 0);
|
||||
void fill(GLenum usage, GLsizei size = 0, GLvoid* data = NULL);
|
||||
void subfill(GLintptr offset, GLsizei size, const GLvoid* data);
|
||||
void map(GLenum access);
|
||||
void unmap();
|
||||
};
|
||||
|
||||
typedef BufferObject<GL_ARRAY_BUFFER> VBO;
|
||||
typedef BufferObject<GL_ELEMENT_ARRAY_BUFFER> IBO;
|
||||
|
||||
class VAO {
|
||||
private:
|
||||
GLuint m_name;
|
||||
protected:
|
||||
public:
|
||||
VAO();
|
||||
~VAO();
|
||||
void bind();
|
||||
void fill(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride = 0, const GLvoid* pointer = NULL);
|
||||
};
|
||||
|
||||
class Shader {
|
||||
private:
|
||||
GLuint m_program;
|
||||
protected:
|
||||
public:
|
||||
Shader();
|
||||
~Shader();
|
||||
void bind();
|
||||
void unbind();
|
||||
void load(std::string data, GLenum shadertype);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define TBufferObject_(pre, post) \
|
||||
template <GLenum T> pre endofthejedi::BufferObject<T>::post
|
||||
#define TBufferObject(...) TBufferObject_(__VA_ARGS__)
|
||||
|
||||
TBufferObject(, BufferObject)() { glGenBuffers(1, &m_name); }
|
||||
|
||||
TBufferObject(, ~BufferObject)() { glDeleteBuffers(1, &m_name); }
|
||||
|
||||
TBufferObject(void, bind)() { glBindBuffer(T, m_name); }
|
||||
|
||||
TBufferObject(void, bind)(GLuint index, GLintptr offset, GLsizeiptr size) {
|
||||
// todo
|
||||
}
|
||||
|
||||
TBufferObject(void, fill)(GLenum usage, GLsizei size, GLvoid *data) {
|
||||
glBufferData(T, size, data, usage);
|
||||
}
|
||||
|
||||
TBufferObject(void, subfill)(GLintptr offset, GLsizei size,
|
||||
const GLvoid *data) {
|
||||
glBufferSubData(T, offset, size, data);
|
||||
}
|
||||
|
||||
TBufferObject(void, map)(GLenum access) {
|
||||
// todo
|
||||
}
|
||||
|
||||
TBufferObject(void, unmap)() {
|
||||
// todo
|
||||
}
|
||||
37
game/main.cpp
Normal file
37
game/main.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include "opengl.h"
|
||||
#include <iostream>
|
||||
|
||||
class MainWindow : public endofthejedi::GLWindow {
|
||||
private:
|
||||
protected:
|
||||
void init() override {
|
||||
glClearColor(0.5f, 0.6f, 0.7f, 1.0f);
|
||||
resize();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
void render(double time) override {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor3f(1.0f, 0.0f, 0.0f);
|
||||
glVertex3f(0.0f, -1.0f, 0.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f);
|
||||
glVertex3f(-1.0f, 1.0f, 0.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, 0.0f);
|
||||
glEnd();
|
||||
}
|
||||
void resize() override { glViewport(0, 0, getwidth(), getheight()); }
|
||||
|
||||
public:
|
||||
MainWindow(unsigned int width, unsigned int height)
|
||||
: endofthejedi::GLWindow(width, height) {}
|
||||
};
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
MainWindow window(500, 500);
|
||||
window.set_maxfps(60.0);
|
||||
window.loop();
|
||||
window.stop();
|
||||
}
|
||||
142
game/opengl.cpp
Normal file
142
game/opengl.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#include "opengl.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define UNUSED(foo) (void)foo;
|
||||
|
||||
timespec diff(timespec start, timespec end) {
|
||||
timespec result;
|
||||
if ((end.tv_nsec - start.tv_nsec) < 0) {
|
||||
result.tv_sec = end.tv_sec - start.tv_sec - 1;
|
||||
result.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
|
||||
} else {
|
||||
result.tv_sec = end.tv_sec - start.tv_sec;
|
||||
result.tv_nsec = end.tv_nsec - start.tv_nsec;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
endofthejedi::GLWindow::GLWindow(unsigned int width, unsigned int height)
|
||||
: m_width(width), m_height(height) {
|
||||
m_display = XOpenDisplay(NULL);
|
||||
|
||||
if (m_display == NULL) {
|
||||
throw std::runtime_error("XOpenDisplay NULL");
|
||||
}
|
||||
|
||||
m_rootwnd = DefaultRootWindow(m_display);
|
||||
|
||||
m_visualinfo = glXChooseVisual(m_display, 0, m_attributes);
|
||||
|
||||
if (m_visualinfo == NULL) {
|
||||
throw std::runtime_error("glXChooseVisual NULL");
|
||||
}
|
||||
|
||||
m_colormap =
|
||||
XCreateColormap(m_display, m_rootwnd, m_visualinfo->visual, AllocNone);
|
||||
|
||||
m_swa.colormap = m_colormap;
|
||||
m_swa.event_mask = ExposureMask | KeyPressMask;
|
||||
|
||||
m_window = XCreateWindow(
|
||||
m_display, m_rootwnd, 0, 0, width, height, 0, m_visualinfo->depth,
|
||||
InputOutput, m_visualinfo->visual, CWColormap | CWEventMask, &m_swa);
|
||||
|
||||
m_atomWmDeleteWindow = XInternAtom(m_display, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(m_display, m_window, &m_atomWmDeleteWindow, 1);
|
||||
|
||||
XMapWindow(m_display, m_window);
|
||||
XStoreName(m_display, m_window, "NAME");
|
||||
|
||||
m_glcontext = glXCreateContext(m_display, m_visualinfo, NULL, GL_TRUE);
|
||||
|
||||
XSync(m_display, False);
|
||||
|
||||
glXMakeCurrent(m_display, m_window, m_glcontext);
|
||||
|
||||
std::cout << "GL Renderer: " << glGetString(GL_RENDERER) << "\n";
|
||||
std::cout << "GL Version: " << glGetString(GL_VERSION) << "\n";
|
||||
std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION)
|
||||
<< "\n";
|
||||
|
||||
init();
|
||||
|
||||
XClearWindow(m_display, m_window);
|
||||
XMapRaised(m_display, m_window);
|
||||
}
|
||||
|
||||
endofthejedi::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() {
|
||||
if (XPending(m_display) > 0) {
|
||||
XEvent xev;
|
||||
XNextEvent(m_display, &xev);
|
||||
handle(xev);
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::handle(XEvent event) {
|
||||
if (event.type == Expose) {
|
||||
XWindowAttributes attribs;
|
||||
XGetWindowAttributes(m_display, m_window, &attribs);
|
||||
m_width = attribs.width;
|
||||
m_height = attribs.height;
|
||||
resize();
|
||||
} else if (event.type == ClientMessage) {
|
||||
if (event.xclient.data.l[0] == m_atomWmDeleteWindow) {
|
||||
stop();
|
||||
}
|
||||
} else if (event.type == DestroyNotify) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
||||
|
||||
void endofthejedi::GLWindow::loop() {
|
||||
m_running = true;
|
||||
|
||||
timespec prev;
|
||||
timespec current;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &prev);
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
|
||||
|
||||
double delta = 0.0;
|
||||
double sleeptime = 0.0;
|
||||
|
||||
while (m_running) {
|
||||
handleevents();
|
||||
render(delta);
|
||||
swap();
|
||||
|
||||
if (m_maxfps > 0) {
|
||||
sleeptime = ((1000000000.0/m_maxfps) - delta) + sleeptime;
|
||||
if (sleeptime > 0.0) {
|
||||
usleep((unsigned int)(sleeptime/1000.0));
|
||||
sleeptime = sleeptime - (unsigned int)(sleeptime/1000.0);
|
||||
}
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
|
||||
delta = diff(prev, current).tv_nsec;
|
||||
prev = current;
|
||||
if(delta > 0.0) {
|
||||
m_fps = (1000000000.0/delta);
|
||||
std::cout << m_fps << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::stop() { m_running = false; }
|
||||
|
||||
void endofthejedi::GLWindow::init() {}
|
||||
void endofthejedi::GLWindow::render(double time) { UNUSED(time) }
|
||||
void endofthejedi::GLWindow::resize() {}
|
||||
103
game/opengl.h
Normal file
103
game/opengl.h
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <epoxy/gl.h>
|
||||
#include <epoxy/glx.h>
|
||||
|
||||
namespace endofthejedi {
|
||||
|
||||
class GLWindow {
|
||||
private:
|
||||
//X-related stuff
|
||||
Display* m_display;
|
||||
Window m_rootwnd;
|
||||
GLint m_attributes[23] =
|
||||
{
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
GLX_STENCIL_SIZE, 8,
|
||||
GLX_DOUBLEBUFFER, True,
|
||||
None
|
||||
};
|
||||
|
||||
XVisualInfo* m_visualinfo;
|
||||
Colormap m_colormap;
|
||||
XSetWindowAttributes m_swa;
|
||||
Window m_window;
|
||||
GLXContext m_glcontext;
|
||||
XWindowAttributes m_gwa;
|
||||
Atom m_atomWmDeleteWindow;
|
||||
//End of X related stuff
|
||||
|
||||
unsigned int m_width;
|
||||
unsigned int m_height;
|
||||
|
||||
//mainloop condition
|
||||
bool m_running = false;
|
||||
|
||||
double m_fps;
|
||||
//if maxfps = 0 there's no fps limit
|
||||
double m_maxfps;
|
||||
|
||||
void handleevents();
|
||||
|
||||
protected:
|
||||
//ancestors shall override these methods
|
||||
virtual void init();
|
||||
//called by mainloop periodically
|
||||
//time shall be used for timebased movement
|
||||
virtual void render(double time);
|
||||
//called by handle on window resize
|
||||
virtual void resize();
|
||||
//the ancestor should call the handle function in this class, too,
|
||||
//as it handles the close calls & resizing
|
||||
virtual void handle(XEvent event);
|
||||
|
||||
public:
|
||||
//initializes the X Window & creates an OpenGL context
|
||||
GLWindow(unsigned int width, unsigned int height);
|
||||
~GLWindow();
|
||||
|
||||
//mainloop does event handling & calls render/swap
|
||||
void loop();
|
||||
void swap();
|
||||
//stops the mainloop by setting m_running false
|
||||
void stop();
|
||||
|
||||
//getters
|
||||
unsigned int getheight() const {
|
||||
return m_height;
|
||||
}
|
||||
|
||||
unsigned int getwidth() const {
|
||||
return m_width;
|
||||
}
|
||||
|
||||
double get_maxfps() const {
|
||||
return m_maxfps;
|
||||
}
|
||||
|
||||
double get_fps() const {
|
||||
return m_fps;
|
||||
}
|
||||
|
||||
bool get_running() const {
|
||||
return m_running;
|
||||
}
|
||||
|
||||
//setters
|
||||
void set_maxfps(const double maxfps) {
|
||||
m_maxfps = maxfps;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
18
game/renderer.cpp
Normal file
18
game/renderer.cpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include "renderer.h"
|
||||
|
||||
endofthejedi::Renderer::Renderer() {
|
||||
|
||||
}
|
||||
|
||||
endofthejedi::Renderer::~Renderer() {}
|
||||
|
||||
void endofthejedi::Renderer::drawCircle(float x, float y, float radius, float r,
|
||||
float g, float b) {
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glVertex2f(x, y); // center of circle
|
||||
for (int i = 0; i <= 64; i++) {
|
||||
glColor3f(r,g,b);
|
||||
glVertex2f(x + (radius * cos(i * 2 * M_PI / 64)), y + (radius * sin(i * 2 * M_PI / 64)));
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
25
game/renderer.h
Normal file
25
game/renderer.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
#include <epoxy/glx.h>
|
||||
|
||||
#include "glclasses.h"
|
||||
|
||||
namespace endofthejedi {
|
||||
|
||||
class Renderer {
|
||||
private:
|
||||
VBO m_vbo;
|
||||
VAO m_vao;
|
||||
Shader m_shader;
|
||||
protected:
|
||||
public:
|
||||
Renderer();
|
||||
~Renderer();
|
||||
void drawCircle(float x, float y, float radius, float r,
|
||||
float g, float b);
|
||||
};
|
||||
|
||||
}
|
||||
2
game/simulation.cpp
Normal file
2
game/simulation.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#include "simulation.h"
|
||||
|
||||
50
game/simulation.h
Normal file
50
game/simulation.h
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vec2d position;
|
||||
Vec2d speed;
|
||||
int live;
|
||||
int leftSource;
|
||||
int stale;
|
||||
} SimMissile;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vec2d* dot;
|
||||
SimMissile missile;
|
||||
int length;
|
||||
int player;
|
||||
double angle;
|
||||
double velocity;
|
||||
} SimShot;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SimShot* shot;
|
||||
int currentShot;
|
||||
Vec2d position;
|
||||
double angle;
|
||||
double velocity;
|
||||
double energy;
|
||||
double oldVelocity;
|
||||
int watch;
|
||||
int deaths;
|
||||
int kills;
|
||||
int shots;
|
||||
int active;
|
||||
int valid;
|
||||
int didShoot;
|
||||
int timeout;
|
||||
int timeoutcnt;
|
||||
char name[16];
|
||||
} SimPlayer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Vec2d position;
|
||||
double radius;
|
||||
double mass;
|
||||
} SimPlanet;
|
||||
90
game/vector.h
Normal file
90
game/vector.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
|
||||
struct Vec2d
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
|
||||
double length() {
|
||||
return sqrt(x*x + y*y);
|
||||
}
|
||||
double distance(Vec2d other) {
|
||||
Vec2d tmp = (*this - other);
|
||||
return tmp.length();
|
||||
}
|
||||
|
||||
Vec2d & operator+=(const Vec2d& rhs) {
|
||||
x+=rhs.x;
|
||||
y+=rhs.y;
|
||||
return *this;
|
||||
}
|
||||
Vec2d & operator-=(const Vec2d& rhs) {
|
||||
x-=rhs.x;
|
||||
y-=rhs.y;
|
||||
return *this;
|
||||
}
|
||||
Vec2d & operator*=(const double& rhs) {
|
||||
x*=rhs;
|
||||
y*=rhs;
|
||||
return *this;
|
||||
}
|
||||
Vec2d & operator/=(const double& rhs) {
|
||||
x/=rhs;
|
||||
y/=rhs;
|
||||
return *this;
|
||||
}
|
||||
const Vec2d operator+(const Vec2d& rhs) const {
|
||||
Vec2d result = *this;
|
||||
result += rhs;
|
||||
return result;
|
||||
}
|
||||
const Vec2d operator-(const Vec2d& rhs) const {
|
||||
Vec2d result = *this;
|
||||
result -= rhs;
|
||||
return result;
|
||||
}
|
||||
const double operator*(const Vec2d& rhs) const {
|
||||
return (this->x * rhs.x) + (this->y * rhs.y);
|
||||
}
|
||||
const Vec2d operator*(const double& rhs) const {
|
||||
Vec2d result = *this;
|
||||
result *= rhs;
|
||||
return result;
|
||||
}
|
||||
const Vec2d operator/(const double& rhs) const {
|
||||
Vec2d result = *this;
|
||||
result /= rhs;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
/*
|
||||
struct Mat4d {
|
||||
std::array<double, 16> data;
|
||||
|
||||
const Mat4d operator*(const Mat4d& rhs) const {
|
||||
Mat4d result;
|
||||
result[0] = result[0]*rhs[0] + result[1]*result[5] + result[2]*result[9] + result[3]*result[13];
|
||||
result[1] = result[0]*rhs[1] + result[1]*result[6] + result[2]*result[10] + result[3]*result[14];
|
||||
result[2] = result[0]*rhs[2] + result[1]*result[7] + result[2]*result[11] + result[3]*result[15];
|
||||
result[3] = result[0]*rhs[3] + result[1]*result[8] + result[2]*result[12] + result[3]*result[16];
|
||||
|
||||
result[4] = result[4]*rhs[0] + result[5]*result[5] + result[6]*result[9] + result[7]*result[13];
|
||||
result[5] = result[4]*rhs[1] + result[5]*result[6] + result[6]*result[10] + result[7]*result[14];
|
||||
result[6] = result[4]*rhs[2] + result[5]*result[7] + result[6]*result[11] + result[7]*result[15];
|
||||
result[7] = result[4]*rhs[3] + result[5]*result[8] + result[6]*result[12] + result[7]*result[16];
|
||||
|
||||
result[8] = result[8]*rhs[0] + result[9]*result[5] + result[10]*result[9] + result[11]*result[13];
|
||||
result[9] = result[8]*rhs[1] + result[9]*result[6] + result[10]*result[10] + result[11]*result[14];
|
||||
result[10] = result[8]*rhs[2] + result[9]*result[7] + result[10]*result[11] + result[11]*result[15];
|
||||
result[11] = result[8]*rhs[3] + result[9]*result[8] + result[10]*result[12] + result[11]*result[16];
|
||||
|
||||
result[12] = result[12]*rhs[0] + result[13]*result[5] + result[14]*result[9] + result[15]*result[13];
|
||||
result[13] = result[12]*rhs[1] + result[13]*result[6] + result[14]*result[10] + result[15]*result[14];
|
||||
result[14] = result[12]*rhs[2] + result[13]*result[7] + result[14]*result[11] + result[15]*result[15];
|
||||
result[15] = result[12]*rhs[3] + result[13]*result[8] + result[14]*result[12] + result[15]*result[16];
|
||||
return result;
|
||||
}
|
||||
};
|
||||
*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue