mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-06 21:26:56 +02:00
- FFP renderer
This commit is contained in:
149
src/core.h
Normal file
149
src/core.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#ifndef H_CORE
|
||||
#define H_CORE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <gl/GL.h>
|
||||
#include <gl/glext.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "input.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(_MSC_VER) // Visual Studio
|
||||
#define GetProcOGL(x) *(void**)&x=(void*)wglGetProcAddress(#x);
|
||||
#else // GCC
|
||||
#define GetProcOGL(x) x=(typeof(x))wglGetProcAddress(#x);
|
||||
#endif
|
||||
|
||||
// Texture
|
||||
PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||
PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
|
||||
// Shader
|
||||
PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||
PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
||||
PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||
PFNGLUSEPROGRAMPROC glUseProgram;
|
||||
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
||||
PFNGLCREATESHADERPROC glCreateShader;
|
||||
PFNGLDELETESHADERPROC glDeleteShader;
|
||||
PFNGLSHADERSOURCEPROC glShaderSource;
|
||||
PFNGLATTACHSHADERPROC glAttachShader;
|
||||
PFNGLCOMPILESHADERPROC glCompileShader;
|
||||
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
|
||||
PFNGLUNIFORM1IVPROC glUniform1iv;
|
||||
PFNGLUNIFORM3FVPROC glUniform3fv;
|
||||
PFNGLUNIFORM4FVPROC glUniform4fv;
|
||||
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
|
||||
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
||||
// Mesh
|
||||
PFNGLGENBUFFERSARBPROC glGenBuffers;
|
||||
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
|
||||
PFNGLBINDBUFFERARBPROC glBindBuffer;
|
||||
PFNGLBUFFERDATAARBPROC glBufferData;
|
||||
#endif
|
||||
|
||||
namespace Core {
|
||||
int width, height;
|
||||
float deltaTime;
|
||||
mat4 mView, mProj, mViewProj, mModel;
|
||||
}
|
||||
|
||||
#include "texture.h"
|
||||
#include "shader.h"
|
||||
#include "mesh.h"
|
||||
|
||||
enum CullMode { cfNone, cfBack, cfFront };
|
||||
enum BlendMode { bmNone, bmAlpha, bmAdd, bmMultiply, bmScreen };
|
||||
|
||||
namespace Core {
|
||||
|
||||
void init() {
|
||||
GetProcOGL(glActiveTexture);
|
||||
GetProcOGL(glCompressedTexImage2D);
|
||||
|
||||
GetProcOGL(glCreateProgram);
|
||||
GetProcOGL(glDeleteProgram);
|
||||
GetProcOGL(glLinkProgram);
|
||||
GetProcOGL(glUseProgram);
|
||||
GetProcOGL(glGetProgramInfoLog);
|
||||
GetProcOGL(glCreateShader);
|
||||
GetProcOGL(glDeleteShader);
|
||||
GetProcOGL(glShaderSource);
|
||||
GetProcOGL(glAttachShader);
|
||||
GetProcOGL(glCompileShader);
|
||||
GetProcOGL(glGetShaderInfoLog);
|
||||
GetProcOGL(glGetUniformLocation);
|
||||
GetProcOGL(glUniform1iv);
|
||||
GetProcOGL(glUniform3fv);
|
||||
GetProcOGL(glUniform4fv);
|
||||
GetProcOGL(glUniformMatrix4fv);
|
||||
GetProcOGL(glBindAttribLocation);
|
||||
GetProcOGL(glEnableVertexAttribArray);
|
||||
GetProcOGL(glDisableVertexAttribArray);
|
||||
GetProcOGL(glVertexAttribPointer);
|
||||
|
||||
GetProcOGL(glGenBuffers);
|
||||
GetProcOGL(glDeleteBuffers);
|
||||
GetProcOGL(glBindBuffer);
|
||||
GetProcOGL(glBufferData);
|
||||
}
|
||||
|
||||
void free() {
|
||||
//
|
||||
}
|
||||
|
||||
void clear(const vec4 &color) {
|
||||
glClearColor(color.x, color.y, color.z, color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void setViewport(int x, int y, int width, int height) {
|
||||
glViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
void setCulling(CullMode mode) {
|
||||
switch (mode) {
|
||||
case cfNone :
|
||||
glDisable(GL_CULL_FACE);
|
||||
case cfBack :
|
||||
glCullFace(GL_BACK);
|
||||
break;
|
||||
case cfFront :
|
||||
glCullFace(GL_FRONT);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode != bmNone)
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
void setBlending(BlendMode mode) {
|
||||
switch (mode) {
|
||||
case bmNone :
|
||||
glDisable(GL_BLEND);
|
||||
break;
|
||||
case bmAlpha :
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
break;
|
||||
case bmAdd :
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
break;
|
||||
case bmMultiply :
|
||||
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
break;
|
||||
case bmScreen :
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode != bmNone)
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
1639
src/game.h
Normal file
1639
src/game.h
Normal file
File diff suppressed because it is too large
Load Diff
83
src/input.h
Normal file
83
src/input.h
Normal file
@@ -0,0 +1,83 @@
|
||||
#ifndef H_INPUT
|
||||
#define H_INPUT
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
enum InputKey { ikNone,
|
||||
// keyboard
|
||||
ikLeft, ikRight, ikUp, ikDown, ikSpace, ikEnter, ikEscape, ikShift, ikCtrl, ikAlt,
|
||||
ik0, ik1, ik2, ik3, ik4, ik5, ik6, ik7, ik8, ik9,
|
||||
ikA, ikB, ikC, ikD, ikE, ikF, ikG, ikH, ikI, ikJ, ikK, ikL, ikM,
|
||||
ikN, ikO, ikP, ikQ, ikR, ikS, ikT, ikU, ikV, ikW, ikX, ikY, ikZ,
|
||||
// mouse
|
||||
ikMouseL, ikMouseR, ikMouseM,
|
||||
// touch
|
||||
ikTouchA, ikTouchB,
|
||||
// gamepad
|
||||
ikJoyA, ikJoyB, ikJoyX, ikJoyY, ikJoyLB, ikJoyRB, ikJoyL, ikJoyR, ikJoySelect, ikJoyStart, ikJoyLT, ikJoyRT, ikJoyDP,
|
||||
ikMAX };
|
||||
|
||||
namespace Input {
|
||||
|
||||
bool down[ikMAX];
|
||||
|
||||
struct {
|
||||
vec2 pos;
|
||||
struct {
|
||||
vec2 L, R, M;
|
||||
} start;
|
||||
} mouse;
|
||||
|
||||
struct {
|
||||
vec2 L, R;
|
||||
float LT, RT, DP;
|
||||
} joy;
|
||||
|
||||
struct {
|
||||
vec2 A, B;
|
||||
|
||||
struct {
|
||||
vec2 A, B;
|
||||
} start;
|
||||
} touch;
|
||||
|
||||
void reset() {
|
||||
memset(down, 0, sizeof(down));
|
||||
memset(&mouse, 0, sizeof(mouse));
|
||||
memset(&joy, 0, sizeof(joy));
|
||||
memset(&touch, 0, sizeof(touch));
|
||||
}
|
||||
|
||||
void setDown(InputKey key, bool value) {
|
||||
if (down[key] == value)
|
||||
return;
|
||||
|
||||
if (value)
|
||||
switch (key) {
|
||||
case ikMouseL : mouse.start.L = mouse.pos; break;
|
||||
case ikMouseR : mouse.start.R = mouse.pos; break;
|
||||
case ikMouseM : mouse.start.M = mouse.pos; break;
|
||||
case ikTouchA : touch.start.A = touch.A; break;
|
||||
case ikTouchB : touch.start.B = touch.B; break;
|
||||
}
|
||||
|
||||
down[key] = value;
|
||||
}
|
||||
|
||||
void setPos(InputKey key, const vec2 &pos) {
|
||||
switch (key) {
|
||||
case ikMouseL :
|
||||
case ikMouseR :
|
||||
case ikMouseM : mouse.pos = pos; break;
|
||||
case ikJoyL : joy.L = pos; break;
|
||||
case ikJoyR : joy.R = pos; break;
|
||||
case ikJoyLT : joy.LT = pos.x; break;
|
||||
case ikJoyRT : joy.RT = pos.x; break;
|
||||
case ikJoyDP : joy.DP = pos.x; break;
|
||||
case ikTouchA : touch.A = pos; break;
|
||||
case ikTouchB : touch.B = pos; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
62
src/mesh.h
Normal file
62
src/mesh.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef H_MESH
|
||||
#define H_MESH
|
||||
|
||||
#include "core.h"
|
||||
|
||||
typedef unsigned short Index;
|
||||
|
||||
struct Vertex {
|
||||
vec3 coord;
|
||||
vec3 normal;
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
struct Mesh {
|
||||
GLuint ID[2];
|
||||
int iCount;
|
||||
int vCount;
|
||||
|
||||
Mesh(const char *name) {
|
||||
Stream stream(name);
|
||||
Index *indices = stream.readArray<Index> (stream.read(iCount));
|
||||
Vertex *vertices = stream.readArray<Vertex>(stream.read(vCount));
|
||||
|
||||
glGenBuffers(2, ID);
|
||||
bind();
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iCount * sizeof(Index), indices, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, vCount * sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||
|
||||
delete[] indices;
|
||||
delete[] vertices;
|
||||
}
|
||||
|
||||
virtual ~Mesh() {
|
||||
glDeleteBuffers(2, ID);
|
||||
}
|
||||
|
||||
void bind() {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ID[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ID[1]);
|
||||
}
|
||||
|
||||
void render() {
|
||||
bind();
|
||||
|
||||
glEnableVertexAttribArray(aCoord);
|
||||
glEnableVertexAttribArray(aNormal);
|
||||
glEnableVertexAttribArray(aTexCoord);
|
||||
|
||||
|
||||
Vertex *v = NULL;
|
||||
glVertexAttribPointer(aCoord, 3, GL_FLOAT, false, sizeof(Vertex), &v->coord);
|
||||
glVertexAttribPointer(aNormal, 3, GL_FLOAT, false, sizeof(Vertex), &v->normal);
|
||||
glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, false, sizeof(Vertex), &v->texCoord);
|
||||
glDrawElements(GL_TRIANGLES, iCount, GL_UNSIGNED_SHORT, NULL);
|
||||
|
||||
glDisableVertexAttribArray(aCoord);
|
||||
glDisableVertexAttribArray(aNormal);
|
||||
glDisableVertexAttribArray(aTexCoord);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
91
src/shader.h
Normal file
91
src/shader.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef H_SHADER
|
||||
#define H_SHADER
|
||||
|
||||
#include "core.h"
|
||||
|
||||
enum AttribType { aCoord, aTexCoord, aNormal, aMAX };
|
||||
enum SamplerType { sTex0, sMAX };
|
||||
enum UniformType { uViewProj, uModel, uLightVec, uMAX };
|
||||
|
||||
const char *AttribName[aMAX] = { "aCoord", "aTexCoord", "aNormal" };
|
||||
const char *SamplerName[sMAX] = { "sTex0" };
|
||||
const char *UniformName[uMAX] = { "uViewProj", "uModel", "uLightVec" };
|
||||
|
||||
struct Shader {
|
||||
GLuint ID;
|
||||
GLint uID[uMAX];
|
||||
|
||||
Shader(const char *name, int param) {
|
||||
Stream stream(name);
|
||||
|
||||
char *text = new char[stream.size + 1];
|
||||
stream.read(text, stream.size);
|
||||
text[stream.size] = '\0';
|
||||
|
||||
#define GLSL_DEFINE "#version 110\n"
|
||||
|
||||
const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
|
||||
const char *code[2][2] = {
|
||||
{ GLSL_DEFINE "#define VERTEX\n", text },
|
||||
{ GLSL_DEFINE "#define FRAGMENT\n", text }
|
||||
};
|
||||
|
||||
GLchar info[256];
|
||||
|
||||
ID = glCreateProgram();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
GLuint obj = glCreateShader(type[i]);
|
||||
glShaderSource(obj, 2, code[i], NULL);
|
||||
glCompileShader(obj);
|
||||
|
||||
glGetShaderInfoLog(obj, sizeof(info), NULL, info);
|
||||
if (info[0]) LOG("! shader: %s\n", info);
|
||||
|
||||
glAttachShader(ID, obj);
|
||||
glDeleteShader(obj);
|
||||
}
|
||||
delete[] text;
|
||||
|
||||
for (int at = 0; at < aMAX; at++)
|
||||
glBindAttribLocation(ID, at, AttribName[at]);
|
||||
|
||||
glLinkProgram(ID);
|
||||
|
||||
glGetProgramInfoLog(ID, sizeof(info), NULL, info);
|
||||
if (info[0]) LOG("! program: %s\n", info);
|
||||
|
||||
bind();
|
||||
for (int st = 0; st < sMAX; st++)
|
||||
glUniform1iv(glGetUniformLocation(ID, (GLchar*)SamplerName[st]), 1, &st);
|
||||
|
||||
for (int ut = 0; ut < uMAX; ut++)
|
||||
uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]);
|
||||
}
|
||||
|
||||
virtual ~Shader() {
|
||||
glDeleteProgram(ID);
|
||||
}
|
||||
|
||||
void bind() {
|
||||
glUseProgram(ID);
|
||||
setParam(uViewProj, Core::mViewProj);
|
||||
setParam(uModel, Core::mModel);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec3 &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
glUniform3fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
glUniform4fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const mat4 &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
103
src/texture.h
Normal file
103
src/texture.h
Normal file
@@ -0,0 +1,103 @@
|
||||
#ifndef H_TEXTURE
|
||||
#define H_TEXTURE
|
||||
|
||||
#include "core.h"
|
||||
|
||||
#define PVR_RGBA8 0x61626772
|
||||
#define PVR_ALPHA 0x00000061
|
||||
#define PVR_PVRTC4 0x00000002 // iOS
|
||||
#define PVR_ETC1 0x00000006 // Android
|
||||
#define PVR_BC1 0x00000007 // Desktop
|
||||
|
||||
#define GL_COMPRESSED_RGB_S3TC_DXT1 0x83F0
|
||||
#define GL_ETC1_RGB8_OES 0x8D64
|
||||
#define GL_COMPRESSED_RGB_PVRTC_4BPPV1 0x8C00
|
||||
|
||||
struct Texture {
|
||||
GLuint ID;
|
||||
int width, height;
|
||||
|
||||
Texture(const char *name) {
|
||||
Stream stream(name);
|
||||
|
||||
struct {
|
||||
int version;
|
||||
int flags;
|
||||
long format;
|
||||
long ext;
|
||||
int color;
|
||||
int channel;
|
||||
int height;
|
||||
int width;
|
||||
int depth;
|
||||
int surfaces;
|
||||
int faces;
|
||||
int mipCount;
|
||||
int metaSize;
|
||||
} header;
|
||||
|
||||
stream.read(header);
|
||||
stream.seek(header.metaSize);
|
||||
|
||||
GLenum fmt;
|
||||
int minSize;
|
||||
switch (header.format) {
|
||||
case PVR_ALPHA : minSize = 1; fmt = GL_ALPHA; break;
|
||||
case PVR_RGBA8 : minSize = 1; fmt = GL_RGBA; break;
|
||||
case PVR_BC1 : minSize = 4; fmt = GL_COMPRESSED_RGB_S3TC_DXT1; break;
|
||||
case PVR_ETC1 : minSize = 4; fmt = GL_ETC1_RGB8_OES; break;
|
||||
case PVR_PVRTC4 : minSize = 8; fmt = GL_COMPRESSED_RGB_PVRTC_4BPPV1; break;
|
||||
default :
|
||||
LOG("! unsupported texture format\n");
|
||||
ID = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
glGenTextures(1, &ID);
|
||||
bind(0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, header.mipCount == 1 ? GL_LINEAR : GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
int sizeX = width = header.width;
|
||||
int sizeY = height = header.height;
|
||||
|
||||
char *data = new char[width * height * 4];
|
||||
for (int i = 0; i < header.mipCount; i++) {
|
||||
if (minSize == 1) {
|
||||
int size = sizeX * sizeY * (header.format == PVR_RGBA8 ? 4 : 1);
|
||||
stream.read(data, size);
|
||||
glTexImage2D(GL_TEXTURE_2D, i, fmt, sizeX, sizeY, 0, fmt, GL_UNSIGNED_BYTE, data);
|
||||
} else {
|
||||
int size = (max(sizeX, minSize) * max(sizeY, minSize) * 4 + 7) / 8;
|
||||
stream.read(data, size);
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, i, fmt, sizeX, sizeY, 0, size, data);
|
||||
}
|
||||
sizeX /= 2;
|
||||
sizeY /= 2;
|
||||
}
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
Texture(int width, int height, int format, void *data) : width(width), height(height) {
|
||||
glGenTextures(1, &ID);
|
||||
bind(0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
virtual ~Texture() {
|
||||
glDeleteTextures(1, &ID);
|
||||
}
|
||||
|
||||
void bind(int sampler) {
|
||||
glActiveTexture(GL_TEXTURE0 + sampler);
|
||||
glBindTexture(GL_TEXTURE_2D, ID);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
540
src/utils.h
Normal file
540
src/utils.h
Normal file
@@ -0,0 +1,540 @@
|
||||
#ifndef H_UTILS
|
||||
#define H_UTILS
|
||||
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define debugBreak() _asm { int 3 }
|
||||
#define ASSERT(expr) if (expr) {} else { LOG("ASSERT %s in %s:%d\n", #expr, __FILE__, __LINE__); debugBreak(); }
|
||||
#else
|
||||
#define ASSERT(expr)
|
||||
#endif
|
||||
|
||||
#ifndef ANDROID
|
||||
#define LOG(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#include <android/log.h>
|
||||
#define LOG(...) __android_log_print(ANDROID_LOG_INFO,"X5",__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define PI 3.14159265358979323846f
|
||||
#define DEG2RAD (PI / 180.0f)
|
||||
#define RAD2DEG (180.0f / PI)
|
||||
#define EPS FLT_EPSILON
|
||||
|
||||
template <typename T>
|
||||
inline const T& min(const T &a, const T &b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline const T& max(const T &a, const T &b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
struct vec2 {
|
||||
float x, y;
|
||||
vec2() {}
|
||||
vec2(float s) : x(s), y(s) {}
|
||||
vec2(float x, float y) : x(x), y(y) {}
|
||||
|
||||
vec2 operator + (const vec2 &v) const { return vec2(x+v.x, y+v.y); }
|
||||
vec2 operator - (const vec2 &v) const { return vec2(x-v.x, y-v.y); }
|
||||
vec2 operator * (float s) const { return vec2(x*s, y*s); }
|
||||
float dot(const vec2 &v) const { return x*v.x + y*v.y; }
|
||||
float cross(const vec2 &v) const { return x*v.y - y*v.x; }
|
||||
float length() const { return sqrtf(dot(*this)); }
|
||||
vec2 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
|
||||
};
|
||||
|
||||
struct vec3 {
|
||||
float x, y, z;
|
||||
vec3() {}
|
||||
vec3(float s) : x(s), y(s), z(s) {}
|
||||
vec3(float x, float y, float z) : x(x), y(y), z(z) {}
|
||||
vec3(const vec2 &xy, float z = 0.0f) : x(xy.x), y(xy.y), z(z) {}
|
||||
|
||||
vec3 operator + (const vec3 &v) const { return vec3(x+v.x, y+v.y, z+v.z); }
|
||||
vec3 operator - (const vec3 &v) const { return vec3(x-v.x, y-v.y, z-v.z); }
|
||||
vec3 operator * (const vec3 &v) const { return vec3(x*v.x, y*v.y, z*v.z); }
|
||||
vec3 operator * (float s) const { return vec3(x*s, y*s, z*s); }
|
||||
|
||||
|
||||
float dot(const vec3 &v) const { return x*v.x + y*v.y + z*v.z; }
|
||||
vec3 cross(const vec3 &v) const { return vec3(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x); }
|
||||
float length() const { return sqrtf(x*x + y*y + z*z); }
|
||||
vec3 normal() const { float s = length(); return s == 0.0 ? (*this) : (*this)*(1.0f/s); }
|
||||
|
||||
vec3 lerp(const vec3 &v, const float t) const {
|
||||
return *this + (v - *this) * t;
|
||||
}
|
||||
};
|
||||
|
||||
struct vec4 {
|
||||
union {
|
||||
struct { vec3 xyz; };
|
||||
struct { float x, y, z, w; };
|
||||
};
|
||||
|
||||
vec4() {}
|
||||
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
|
||||
};
|
||||
|
||||
struct quat {
|
||||
float x, y, z, w;
|
||||
|
||||
quat() {}
|
||||
quat(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
|
||||
|
||||
quat(const vec3 &axis, float angle) {
|
||||
angle *= 0.5f;
|
||||
float s = sinf(angle);
|
||||
x = axis.x * s;
|
||||
y = axis.y * s;
|
||||
z = axis.z * s;
|
||||
w = cosf(angle);
|
||||
}
|
||||
|
||||
quat quat::operator - () const {
|
||||
return quat(-x, -y, -z, -w);
|
||||
}
|
||||
|
||||
quat quat::operator + (const quat &q) const {
|
||||
return quat(x + q.x, y + q.y, z + q.z, w + q.w);
|
||||
}
|
||||
|
||||
quat quat::operator - (const quat &q) const {
|
||||
return quat(x - q.x, y - q.y, z - q.z, w - q.w);
|
||||
}
|
||||
|
||||
quat quat::operator * (const float s) const {
|
||||
return quat(x * s, y * s, z * s, w * s);
|
||||
}
|
||||
|
||||
quat quat::operator * (const quat &q) const {
|
||||
return quat(w * q.x + x * q.w + y * q.z - z * q.y,
|
||||
w * q.y + y * q.w + z * q.x - x * q.z,
|
||||
w * q.z + z * q.w + x * q.y - y * q.x,
|
||||
w * q.w - x * q.x - y * q.y - z * q.z);
|
||||
}
|
||||
|
||||
float dot(const quat &q) const {
|
||||
return x * q.x + y * q.y + z * q.z + w * q.w;
|
||||
}
|
||||
|
||||
float length2() const {
|
||||
return dot(*this);
|
||||
}
|
||||
|
||||
float length() const {
|
||||
return sqrtf(length2());
|
||||
}
|
||||
|
||||
void quat::normalize() {
|
||||
*this = normal();
|
||||
}
|
||||
|
||||
quat quat::normal() const {
|
||||
return *this * (1.0f / length());
|
||||
}
|
||||
|
||||
quat quat::conjugate() const {
|
||||
return quat(-x, -y, -z, w);
|
||||
}
|
||||
|
||||
quat quat::inverse() const {
|
||||
return conjugate() * (1.0f / length2());
|
||||
}
|
||||
|
||||
quat lerp(const quat &q, float t) const {
|
||||
if (t <= 0.0f) return *this;
|
||||
if (t >= 1.0f) return q;
|
||||
|
||||
return dot(q) < 0 ? (*this - (q + *this) * t) :
|
||||
(*this + (q - *this) * t);
|
||||
}
|
||||
|
||||
quat slerp(const quat &q, float t) const {
|
||||
if (t <= 0.0f) return *this;
|
||||
if (t >= 1.0f) return q;
|
||||
|
||||
quat temp;
|
||||
float omega, cosom, sinom, scale0, scale1;
|
||||
|
||||
cosom = dot(q);
|
||||
if (cosom < 0.0f) {
|
||||
temp = -q;
|
||||
cosom = -cosom;
|
||||
} else
|
||||
temp = q;
|
||||
|
||||
if (1.0f - cosom > EPS) {
|
||||
omega = acos(cosom);
|
||||
sinom = 1.0f / sin(omega);
|
||||
scale0 = sin((1.0f - t) * omega) * sinom;
|
||||
scale1 = sin(t * omega) * sinom;
|
||||
} else {
|
||||
scale0 = 1.0f - t;
|
||||
scale1 = t;
|
||||
}
|
||||
|
||||
return *this * scale0 + temp * scale1;
|
||||
}
|
||||
};
|
||||
|
||||
struct mat4 {
|
||||
|
||||
union {
|
||||
struct {
|
||||
float e00, e10, e20, e30,
|
||||
e01, e11, e21, e31,
|
||||
e02, e12, e22, e32,
|
||||
e03, e13, e23, e33;
|
||||
};
|
||||
struct { vec4 right, up, dir, offset; };
|
||||
};
|
||||
|
||||
mat4() {}
|
||||
|
||||
mat4(const quat &rot, const vec3 &pos) {
|
||||
setRot(rot);
|
||||
setPos(pos);
|
||||
e30 = e31 = e32 = 0.0f;
|
||||
e33 = 1.0f;
|
||||
}
|
||||
|
||||
mat4(float l, float r, float b, float t, float znear, float zfar) {
|
||||
identity();
|
||||
e00 = 2.0f / (r - l);
|
||||
e11 = 2.0f / (t - b);
|
||||
e22 = 2.0f / (znear - zfar);
|
||||
e03 = (l + r) / (l - r);
|
||||
e13 = (b + t) / (b - t);
|
||||
e23 = (zfar + znear) / (znear - zfar);
|
||||
}
|
||||
|
||||
mat4(float fov, float aspect, float znear, float zfar) {
|
||||
float k = 1.0f / tanf(fov * 0.5f * DEG2RAD);
|
||||
identity();
|
||||
e00 = k / aspect;
|
||||
e11 = k;
|
||||
e22 = (znear + zfar) / (znear - zfar);
|
||||
e33 = 0.0f;
|
||||
e32 = -1.0f;
|
||||
e23 = 2.0f * zfar * znear / (znear - zfar);
|
||||
}
|
||||
|
||||
void identity() {
|
||||
e10 = e20 = e30 = e01 = e21 = e31 = e02 = e12 = e32 = e03 = e13 = e23 = 0.0f;
|
||||
e00 = e11 = e22 = e33 = 1.0f;
|
||||
}
|
||||
|
||||
mat4 operator * (const mat4 &m) const {
|
||||
mat4 r;
|
||||
r.e00 = e00 * m.e00 + e01 * m.e10 + e02 * m.e20 + e03 * m.e30;
|
||||
r.e10 = e10 * m.e00 + e11 * m.e10 + e12 * m.e20 + e13 * m.e30;
|
||||
r.e20 = e20 * m.e00 + e21 * m.e10 + e22 * m.e20 + e23 * m.e30;
|
||||
r.e30 = e30 * m.e00 + e31 * m.e10 + e32 * m.e20 + e33 * m.e30;
|
||||
r.e01 = e00 * m.e01 + e01 * m.e11 + e02 * m.e21 + e03 * m.e31;
|
||||
r.e11 = e10 * m.e01 + e11 * m.e11 + e12 * m.e21 + e13 * m.e31;
|
||||
r.e21 = e20 * m.e01 + e21 * m.e11 + e22 * m.e21 + e23 * m.e31;
|
||||
r.e31 = e30 * m.e01 + e31 * m.e11 + e32 * m.e21 + e33 * m.e31;
|
||||
r.e02 = e00 * m.e02 + e01 * m.e12 + e02 * m.e22 + e03 * m.e32;
|
||||
r.e12 = e10 * m.e02 + e11 * m.e12 + e12 * m.e22 + e13 * m.e32;
|
||||
r.e22 = e20 * m.e02 + e21 * m.e12 + e22 * m.e22 + e23 * m.e32;
|
||||
r.e32 = e30 * m.e02 + e31 * m.e12 + e32 * m.e22 + e33 * m.e32;
|
||||
r.e03 = e00 * m.e03 + e01 * m.e13 + e02 * m.e23 + e03 * m.e33;
|
||||
r.e13 = e10 * m.e03 + e11 * m.e13 + e12 * m.e23 + e13 * m.e33;
|
||||
r.e23 = e20 * m.e03 + e21 * m.e13 + e22 * m.e23 + e23 * m.e33;
|
||||
r.e33 = e30 * m.e03 + e31 * m.e13 + e32 * m.e23 + e33 * m.e33;
|
||||
return r;
|
||||
}
|
||||
|
||||
vec3 operator * (const vec3 &v) const {
|
||||
return vec3(
|
||||
e00 * v.x + e01 * v.y + e02 * v.z + e03,
|
||||
e10 * v.x + e11 * v.y + e12 * v.z + e13,
|
||||
e20 * v.x + e21 * v.y + e22 * v.z + e23);
|
||||
}
|
||||
|
||||
vec4 operator * (const vec4 &v) const {
|
||||
return vec4(
|
||||
e00 * v.x + e01 * v.y + e02 * v.z + e03 * v.w,
|
||||
e10 * v.x + e11 * v.y + e12 * v.z + e13 * v.w,
|
||||
e20 * v.x + e21 * v.y + e22 * v.z + e23 * v.w,
|
||||
e30 * v.x + e31 * v.y + e32 * v.z + e33 * v.w);
|
||||
}
|
||||
|
||||
void translate(const vec3 &offset) {
|
||||
mat4 m;
|
||||
m.identity();
|
||||
m.setPos(offset);
|
||||
*this = *this * m;
|
||||
};
|
||||
|
||||
void scale(const vec3 &factor) {
|
||||
mat4 m;
|
||||
m.identity();
|
||||
m.e00 = factor.x;
|
||||
m.e11 = factor.y;
|
||||
m.e22 = factor.z;
|
||||
*this = *this * m;
|
||||
}
|
||||
|
||||
void rotateX(float angle) {
|
||||
mat4 m;
|
||||
m.identity();
|
||||
float s = sinf(angle), c = cosf(angle);
|
||||
m.e11 = c; m.e21 = s;
|
||||
m.e12 = -s; m.e22 = c;
|
||||
*this = *this * m;
|
||||
}
|
||||
|
||||
void rotateY(float angle) {
|
||||
mat4 m;
|
||||
m.identity();
|
||||
float s = sinf(angle), c = cosf(angle);
|
||||
m.e00 = c; m.e20 = -s;
|
||||
m.e02 = s; m.e22 = c;
|
||||
*this = *this * m;
|
||||
}
|
||||
|
||||
void rotateZ(float angle) {
|
||||
mat4 m;
|
||||
m.identity();
|
||||
float s = sinf(angle), c = cosf(angle);
|
||||
m.e00 = c; m.e01 = -s;
|
||||
m.e10 = s; m.e11 = c;
|
||||
*this = *this * m;
|
||||
}
|
||||
|
||||
float det() const {
|
||||
return e00 * (e11 * (e22 * e33 - e32 * e23) - e21 * (e12 * e33 - e32 * e13) + e31 * (e12 * e23 - e22 * e13)) -
|
||||
e10 * (e01 * (e22 * e33 - e32 * e23) - e21 * (e02 * e33 - e32 * e03) + e31 * (e02 * e23 - e22 * e03)) +
|
||||
e20 * (e01 * (e12 * e33 - e32 * e13) - e11 * (e02 * e33 - e32 * e03) + e31 * (e02 * e13 - e12 * e03)) -
|
||||
e30 * (e01 * (e12 * e23 - e22 * e13) - e11 * (e02 * e23 - e22 * e03) + e21 * (e02 * e13 - e12 * e03));
|
||||
}
|
||||
|
||||
mat4 inverse() const {
|
||||
float idet = 1.0f / det();
|
||||
mat4 r;
|
||||
r.e00 = (e11 * (e22 * e33 - e32 * e23) - e21 * (e12 * e33 - e32 * e13) + e31 * (e12 * e23 - e22 * e13)) * idet;
|
||||
r.e01 = -(e01 * (e22 * e33 - e32 * e23) - e21 * (e02 * e33 - e32 * e03) + e31 * (e02 * e23 - e22 * e03)) * idet;
|
||||
r.e02 = (e01 * (e12 * e33 - e32 * e13) - e11 * (e02 * e33 - e32 * e03) + e31 * (e02 * e13 - e12 * e03)) * idet;
|
||||
r.e03 = -(e01 * (e12 * e23 - e22 * e13) - e11 * (e02 * e23 - e22 * e03) + e21 * (e02 * e13 - e12 * e03)) * idet;
|
||||
r.e10 = -(e10 * (e22 * e33 - e32 * e23) - e20 * (e12 * e33 - e32 * e13) + e30 * (e12 * e23 - e22 * e13)) * idet;
|
||||
r.e11 = (e00 * (e22 * e33 - e32 * e23) - e20 * (e02 * e33 - e32 * e03) + e30 * (e02 * e23 - e22 * e03)) * idet;
|
||||
r.e12 = -(e00 * (e12 * e33 - e32 * e13) - e10 * (e02 * e33 - e32 * e03) + e30 * (e02 * e13 - e12 * e03)) * idet;
|
||||
r.e13 = (e00 * (e12 * e23 - e22 * e13) - e10 * (e02 * e23 - e22 * e03) + e20 * (e02 * e13 - e12 * e03)) * idet;
|
||||
r.e20 = (e10 * (e21 * e33 - e31 * e23) - e20 * (e11 * e33 - e31 * e13) + e30 * (e11 * e23 - e21 * e13)) * idet;
|
||||
r.e21 = -(e00 * (e21 * e33 - e31 * e23) - e20 * (e01 * e33 - e31 * e03) + e30 * (e01 * e23 - e21 * e03)) * idet;
|
||||
r.e22 = (e00 * (e11 * e33 - e31 * e13) - e10 * (e01 * e33 - e31 * e03) + e30 * (e01 * e13 - e11 * e03)) * idet;
|
||||
r.e23 = -(e00 * (e11 * e23 - e21 * e13) - e10 * (e01 * e23 - e21 * e03) + e20 * (e01 * e13 - e11 * e03)) * idet;
|
||||
r.e30 = -(e10 * (e21 * e32 - e31 * e22) - e20 * (e11 * e32 - e31 * e12) + e30 * (e11 * e22 - e21 * e12)) * idet;
|
||||
r.e31 = (e00 * (e21 * e32 - e31 * e22) - e20 * (e01 * e32 - e31 * e02) + e30 * (e01 * e22 - e21 * e02)) * idet;
|
||||
r.e32 = -(e00 * (e11 * e32 - e31 * e12) - e10 * (e01 * e32 - e31 * e02) + e30 * (e01 * e12 - e11 * e02)) * idet;
|
||||
r.e33 = (e00 * (e11 * e22 - e21 * e12) - e10 * (e01 * e22 - e21 * e02) + e20 * (e01 * e12 - e11 * e02)) * idet;
|
||||
return r;
|
||||
}
|
||||
|
||||
mat4 transpose() const {
|
||||
mat4 r;
|
||||
r.e00 = e00; r.e10 = e01; r.e20 = e02; r.e30 = e03;
|
||||
r.e01 = e10; r.e11 = e11; r.e21 = e12; r.e31 = e13;
|
||||
r.e02 = e20; r.e12 = e21; r.e22 = e22; r.e32 = e23;
|
||||
r.e03 = e30; r.e13 = e31; r.e23 = e32; r.e33 = e33;
|
||||
return r;
|
||||
}
|
||||
|
||||
quat mat4::getRot() const {
|
||||
float t, s;
|
||||
t = 1.0f + e00 + e11 + e22;
|
||||
if (t > EPS) {
|
||||
s = 0.5f / sqrtf(t);
|
||||
return quat((e21 - e12) * s, (e02 - e20) * s, (e10 - e01) * s, 0.25f / s);
|
||||
} else
|
||||
if (e00 > e11 && e00 > e22) {
|
||||
s = 0.5f / sqrtf(1.0f + e00 - e11 - e22);
|
||||
return quat(0.25f / s, (e01 + e10) * s, (e02 + e20) * s, (e21 - e12) * s);
|
||||
} else
|
||||
if (e11 > e22) {
|
||||
s = 0.5f / sqrtf(1.0f - e00 + e11 - e22);
|
||||
return quat((e01 + e10) * s, 0.25f / s, (e12 + e21) * s, (e02 - e20) * s);
|
||||
} else {
|
||||
s = 0.5f / sqrtf(1.0f - e00 - e11 + e22);
|
||||
return quat((e02 + e20) * s, (e12 + e21) * s, 0.25f / s, (e10 - e01) * s);
|
||||
}
|
||||
}
|
||||
|
||||
void mat4::setRot(const quat &rot) {
|
||||
float sx = rot.x * rot.x,
|
||||
sy = rot.y * rot.y,
|
||||
sz = rot.z * rot.z,
|
||||
sw = rot.w * rot.w,
|
||||
inv = 1.0f / (sx + sy + sz + sw);
|
||||
|
||||
e00 = ( sx - sy - sz + sw) * inv;
|
||||
e11 = (-sx + sy - sz + sw) * inv;
|
||||
e22 = (-sx - sy + sz + sw) * inv;
|
||||
inv *= 2.0f;
|
||||
|
||||
float t1 = rot.x * rot.y;
|
||||
float t2 = rot.z * rot.w;
|
||||
e10 = (t1 + t2) * inv;
|
||||
e01 = (t1 - t2) * inv;
|
||||
|
||||
t1 = rot.x * rot.z;
|
||||
t2 = rot.y * rot.w;
|
||||
e20 = (t1 - t2) * inv;
|
||||
e02 = (t1 + t2) * inv;
|
||||
|
||||
t1 = rot.y * rot.z;
|
||||
t2 = rot.x * rot.w;
|
||||
e21 = (t1 + t2) * inv;
|
||||
e12 = (t1 - t2) * inv;
|
||||
}
|
||||
|
||||
vec3 mat4::getPos() const {
|
||||
return offset.xyz;
|
||||
}
|
||||
|
||||
void mat4::setPos(const vec3 &pos) {
|
||||
offset.xyz = pos;
|
||||
}
|
||||
};
|
||||
|
||||
struct Stream {
|
||||
FILE *f;
|
||||
int size, pos;
|
||||
|
||||
Stream(const char *name) : pos(0) {
|
||||
f = fopen(name, "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
~Stream() {
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void setPos(int pos) {
|
||||
this->pos = pos;
|
||||
fseek(f, pos, SEEK_SET);
|
||||
}
|
||||
|
||||
void seek(int offset) {
|
||||
fseek(f, offset, SEEK_CUR);
|
||||
pos += offset;
|
||||
}
|
||||
|
||||
int read(void *data, int size) {
|
||||
pos += size;
|
||||
return fread(data, 1, size, f);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T& read(T &x) {
|
||||
read(&x, sizeof(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* readArray(int count) {
|
||||
if (!count)
|
||||
return NULL;
|
||||
T *a = new T[count];
|
||||
read(a, count * sizeof(T));
|
||||
return a;
|
||||
}
|
||||
|
||||
char *readStr(char *buffer) {
|
||||
unsigned char len;
|
||||
read(&len, sizeof(len));
|
||||
if (!len)
|
||||
return NULL;
|
||||
read(buffer, len);
|
||||
buffer[len] = 0;
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename C = int>
|
||||
struct Array {
|
||||
T **items;
|
||||
C count;
|
||||
|
||||
Array() : items(NULL), count(0) {}
|
||||
|
||||
Array(int count) : count(count) {
|
||||
if (count == 0) {
|
||||
items = NULL;
|
||||
return;
|
||||
}
|
||||
items = new T*[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
items[i] = new T();
|
||||
}
|
||||
|
||||
Array(Stream *stream) {
|
||||
stream->read(count);
|
||||
if (count == 0) {
|
||||
items = NULL;
|
||||
return;
|
||||
}
|
||||
items = new T*[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
items[i] = new T(stream);
|
||||
}
|
||||
|
||||
~Array() {
|
||||
for (int i = 0; i < count; i++)
|
||||
delete items[i];
|
||||
delete[] items;
|
||||
}
|
||||
|
||||
T* operator[] (int index) const {
|
||||
return items[index];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename C = int>
|
||||
struct Vector {
|
||||
T *items;
|
||||
C count;
|
||||
|
||||
Vector(Stream *stream) {
|
||||
stream->read(count);
|
||||
if (count <= 0) {
|
||||
items = NULL;
|
||||
return;
|
||||
}
|
||||
items = (T*)malloc((int)count * sizeof(T));
|
||||
stream->read(items, (int)count * sizeof(T));
|
||||
}
|
||||
|
||||
Vector(Stream *stream, int count) : count(count) {
|
||||
if (count <= 0) {
|
||||
items = NULL;
|
||||
return;
|
||||
}
|
||||
items = (T*)malloc((int)count * sizeof(T));
|
||||
stream->read(items, (int)count * sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
~Vector() {
|
||||
if (items) free(items);
|
||||
}
|
||||
|
||||
T& operator[] (int index) const {
|
||||
ASSERT(index >= 0);
|
||||
ASSERT(index < count);
|
||||
return items[index];
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
22
src/win/OpenLara.sln
Normal file
22
src/win/OpenLara.sln
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2013 for Windows Desktop
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenLara", "OpenLara.vcxproj", "{6935E070-59B8-418A-9241-70BACB4217B5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6935E070-59B8-418A-9241-70BACB4217B5}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6935E070-59B8-418A-9241-70BACB4217B5}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6935E070-59B8-418A-9241-70BACB4217B5}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6935E070-59B8-418A-9241-70BACB4217B5}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
108
src/win/OpenLara.vcxproj
Normal file
108
src/win/OpenLara.vcxproj
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6935E070-59B8-418A-9241-70BACB4217B5}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>OpenLara</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120_xp</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>..\..\bin\</OutDir>
|
||||
<IncludePath>..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>..\..\bin\</OutDir>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
<IncludePath>..\;$(VC_IncludePath);$(WindowsSdk_71A_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FloatingPointModel>Strict</FloatingPointModel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NOMINMAX;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FloatingPointModel>Strict</FloatingPointModel>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>opengl32.lib;winmm.lib;wcrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\core.h" />
|
||||
<ClInclude Include="..\game.h" />
|
||||
<ClInclude Include="..\input.h" />
|
||||
<ClInclude Include="..\mesh.h" />
|
||||
<ClInclude Include="..\shader.h" />
|
||||
<ClInclude Include="..\texture.h" />
|
||||
<ClInclude Include="..\utils.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
219
src/win/main.cpp
Normal file
219
src/win/main.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "game.h"
|
||||
|
||||
DWORD getTime() {
|
||||
#ifdef DEBUG
|
||||
LARGE_INTEGER Freq, Count;
|
||||
QueryPerformanceFrequency(&Freq);
|
||||
QueryPerformanceCounter(&Count);
|
||||
return (DWORD)(Count.QuadPart * 1000L / Freq.QuadPart);
|
||||
#else
|
||||
timeBeginPeriod(0);
|
||||
return timeGetTime();
|
||||
#endif
|
||||
}
|
||||
|
||||
InputKey keyToInputKey(int code) {
|
||||
int codes[] = {
|
||||
VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_SPACE, VK_RETURN, VK_ESCAPE, VK_SHIFT, VK_CONTROL, VK_MENU,
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(codes) / sizeof(codes[0]); i++)
|
||||
if (codes[i] == code)
|
||||
return (InputKey)(ikLeft + i);
|
||||
return ikNone;
|
||||
}
|
||||
|
||||
InputKey mouseToInputKey(int msg) {
|
||||
return (msg >= WM_LBUTTONDOWN || msg <= WM_LBUTTONDBLCLK) ? ikMouseL :
|
||||
(msg >= WM_RBUTTONDOWN || msg <= WM_RBUTTONDBLCLK) ? ikMouseR : ikMouseM;
|
||||
}
|
||||
|
||||
#define JOY_DEAD_ZONE_STICK 0.3f
|
||||
#define JOY_DEAD_ZONE_TRIGGER 0.01f
|
||||
|
||||
bool joyReady;
|
||||
|
||||
void joyInit() {
|
||||
JOYINFOEX info;
|
||||
info.dwSize = sizeof(info);
|
||||
info.dwFlags = JOY_RETURNALL;
|
||||
joyReady = joyGetPosEx(0, &info) == JOYERR_NOERROR;
|
||||
}
|
||||
|
||||
void joyFree() {
|
||||
joyReady = false;
|
||||
memset(&Input::joy, 0, sizeof(Input::joy));
|
||||
for (int ik = ikJoyA; ik <= ikJoyDP; ik++)
|
||||
Input::down[ik] = false;
|
||||
}
|
||||
|
||||
float joyAxis(int x, int xMin, int xMax) {
|
||||
return ((x - xMin) / (float)(xMax - xMin)) * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
vec2 joyDir(float ax, float ay) {
|
||||
vec2 dir = vec2(ax, ay);
|
||||
float dist = min(1.0f, dir.length());
|
||||
if (dist < JOY_DEAD_ZONE_STICK) dist = 0;
|
||||
|
||||
return dir.normal() * dist;
|
||||
}
|
||||
|
||||
void joyUpdate() {
|
||||
if (!joyReady) return;
|
||||
|
||||
JOYINFOEX info;
|
||||
info.dwSize = sizeof(info);
|
||||
info.dwFlags = JOY_RETURNALL;
|
||||
|
||||
if (joyGetPosEx(0, &info) == JOYERR_NOERROR) {
|
||||
JOYCAPS caps;
|
||||
joyGetDevCaps(0, &caps, sizeof(caps));
|
||||
|
||||
Input::setPos(ikJoyL, joyDir(joyAxis(info.dwXpos, caps.wXmin, caps.wXmax),
|
||||
joyAxis(info.dwYpos, caps.wYmin, caps.wYmax)));
|
||||
|
||||
if ((caps.wCaps & JOYCAPS_HASR) && (caps.wCaps & JOYCAPS_HASU))
|
||||
Input::setPos(ikJoyR, joyDir(joyAxis(info.dwUpos, caps.wUmin, caps.wUmax),
|
||||
joyAxis(info.dwRpos, caps.wRmin, caps.wRmax)));
|
||||
|
||||
if (caps.wCaps & JOYCAPS_HASZ) {
|
||||
float z = joyAxis(info.dwZpos, caps.wZmin, caps.wZmax);
|
||||
if (fabsf(z) > JOY_DEAD_ZONE_TRIGGER)
|
||||
Input::setPos(z > 0.0f ? ikJoyLT : ikJoyRT, vec2(fabsf(z), 0.0f));
|
||||
}
|
||||
|
||||
if (caps.wCaps & JOYCAPS_HASPOV && info.dwPOV != JOY_POVCENTERED)
|
||||
Input::setPos(ikJoyDP, vec2((float)(1 + info.dwPOV / 4500), 0));
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
Input::setDown((InputKey)(ikJoyA + i), (info.dwButtons & (1 << i)) > 0);
|
||||
} else
|
||||
joyFree();
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (msg) {
|
||||
case WM_ACTIVATE :
|
||||
Input::reset();
|
||||
break;
|
||||
// keyboard
|
||||
case WM_KEYDOWN :
|
||||
case WM_KEYUP :
|
||||
case WM_SYSKEYDOWN :
|
||||
case WM_SYSKEYUP :
|
||||
Input::setDown(keyToInputKey(wParam), msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN);
|
||||
break;
|
||||
// mouse
|
||||
case WM_LBUTTONDOWN :
|
||||
case WM_LBUTTONUP :
|
||||
case WM_LBUTTONDBLCLK :
|
||||
case WM_RBUTTONDOWN :
|
||||
case WM_RBUTTONUP :
|
||||
case WM_RBUTTONDBLCLK :
|
||||
case WM_MBUTTONDOWN :
|
||||
case WM_MBUTTONUP :
|
||||
case WM_MBUTTONDBLCLK : {
|
||||
InputKey key = mouseToInputKey(msg);
|
||||
Input::setPos(key, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam)));
|
||||
bool down = msg != WM_LBUTTONUP && msg != WM_RBUTTONUP && msg != WM_MBUTTONUP;
|
||||
Input::setDown(key, down);
|
||||
if (down)
|
||||
SetCapture(hWnd);
|
||||
else
|
||||
ReleaseCapture();
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEMOVE :
|
||||
Input::setPos(ikMouseL, vec2((float)(short)LOWORD(lParam), (float)(short)HIWORD(lParam)));
|
||||
break;
|
||||
// gamepad
|
||||
case WM_DEVICECHANGE :
|
||||
joyInit();
|
||||
return 1;
|
||||
// touch
|
||||
// ...
|
||||
case WM_SIZE :
|
||||
Core::width = LOWORD(lParam);
|
||||
Core::height = HIWORD(lParam);
|
||||
break;
|
||||
case WM_DESTROY :
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
default :
|
||||
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
HGLRC initGL(HDC hDC) {
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cDepthBits = 24;
|
||||
|
||||
int format = ChoosePixelFormat(hDC, &pfd);
|
||||
SetPixelFormat(hDC, format, &pfd);
|
||||
HGLRC hRC = wglCreateContext(hDC);
|
||||
wglMakeCurrent(hDC, hRC);
|
||||
return hRC;
|
||||
}
|
||||
|
||||
void freeGL(HGLRC hRC) {
|
||||
wglMakeCurrent(0, 0);
|
||||
wglDeleteContext(hRC);
|
||||
}
|
||||
|
||||
int main() {
|
||||
RECT r = { 0, 0, 1280, 720 };
|
||||
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
HWND hWnd = CreateWindow("static", "OpenLara", WS_OVERLAPPEDWINDOW, 0, 0, r.right - r.left, r.bottom - r.top, 0, 0, 0, 0);
|
||||
|
||||
joyInit();
|
||||
|
||||
HDC hDC = GetDC(hWnd);
|
||||
HGLRC hRC = initGL(hDC);
|
||||
Game::init();
|
||||
|
||||
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)&WndProc);
|
||||
ShowWindow(hWnd, SW_SHOWDEFAULT);
|
||||
|
||||
DWORD time, lastTime = getTime();
|
||||
|
||||
MSG msg;
|
||||
msg.message = WM_PAINT;
|
||||
|
||||
while (msg.message != WM_QUIT)
|
||||
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
} else {
|
||||
time = getTime();
|
||||
if (time <= lastTime)
|
||||
continue;
|
||||
|
||||
Core::deltaTime = (time - lastTime) * 0.001f;
|
||||
lastTime = time;
|
||||
|
||||
joyUpdate();
|
||||
Game::update();
|
||||
Game::render();
|
||||
|
||||
SwapBuffers(hDC);
|
||||
}
|
||||
|
||||
Game::free();
|
||||
freeGL(hRC);
|
||||
ReleaseDC(hWnd, hDC);
|
||||
|
||||
DestroyWindow(hWnd);
|
||||
|
||||
return 0;
|
||||
}
|
BIN
src/win/wcrt.lib
Normal file
BIN
src/win/wcrt.lib
Normal file
Binary file not shown.
Reference in New Issue
Block a user