glfw version of sample app
This commit is contained in:
41
Makefile
Normal file
41
Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
CXXFLAGS = -Wall -Wextra -std=c++11 -stdlib=libc++ -fno-exceptions
|
||||
CPPFLAGS = -O3 -DDEBUG
|
||||
INCLUDE = -Iinclude
|
||||
|
||||
|
||||
|
||||
SRCS += src/map/map.cpp
|
||||
SRCS += src/map/tile.cpp
|
||||
SRCS += src/map/transform.cpp
|
||||
SRCS += src/geometry/linevertexbuffer.cpp
|
||||
SRCS += src/renderer/painter.cpp
|
||||
SRCS += src/renderer/shader.cpp
|
||||
SRCS += src/renderer/shader-fill.cpp
|
||||
SRCS += src/renderer/shader-line.cpp
|
||||
SRCS += src/util/mat4.c
|
||||
|
||||
SRCS += macosx/main.mm
|
||||
|
||||
OBJS = $(patsubst %.mm,%.o,$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS))))
|
||||
|
||||
main: macosx
|
||||
|
||||
library: $(OBJS)
|
||||
|
||||
macosx: library
|
||||
$(CXX) $(OBJS) $(INCLUDE) -lglfw3 -framework OpenGL -framework Foundation -o bin/macosx
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE) -c -o $@ $^
|
||||
|
||||
%.o: %.mm
|
||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(INCLUDE) -c -o $@ $^
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CPPFLAGS) $(INCLUDE) -c -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -rf src/*/*.o
|
||||
rm -rf bin/macosx
|
||||
|
||||
.PHONY: macosx
|
||||
2
enable-emscripten
Normal file
2
enable-emscripten
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
export PATH="`emsdk active_path`:$PATH"
|
||||
26
include/llmr/geometry/linevertexbuffer.hpp
Normal file
26
include/llmr/geometry/linevertexbuffer.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef LLMR_GEOMETRY_LINEVERTEXBUFFER
|
||||
#define LLMR_GEOMETRY_LINEVERTEXBUFFER
|
||||
|
||||
#include "../platform/gl.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class linevertexbuffer {
|
||||
public:
|
||||
linevertexbuffer();
|
||||
|
||||
void addDegenerate();
|
||||
void addCoordinate(int16_t x, int16_t y);
|
||||
|
||||
uint32_t length();
|
||||
void bind();
|
||||
private:
|
||||
std::vector<uint16_t> array;
|
||||
GLuint buffer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
6
include/llmr/llmr.hpp
Normal file
6
include/llmr/llmr.hpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef LLMR_MAIN
|
||||
#define LLMR_MAIN
|
||||
|
||||
#include "map/map.hpp"
|
||||
|
||||
#endif
|
||||
34
include/llmr/map/map.hpp
Normal file
34
include/llmr/map/map.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef LLMR_MAP_MAP
|
||||
#define LLMR_MAP_MAP
|
||||
|
||||
#include "../platform/platform.hpp"
|
||||
#include "../renderer/painter.hpp"
|
||||
#include "transform.hpp"
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class tile;
|
||||
|
||||
class map {
|
||||
public:
|
||||
map(class platform *platform, class painter *painter);
|
||||
~map();
|
||||
|
||||
/* callback */
|
||||
bool render();
|
||||
void moveBy(double dx, double dy);
|
||||
void scaleBy(double ds, double cx, double cy);
|
||||
void tileLoaded(tile *tile);
|
||||
void tileFailed(tile *tile);
|
||||
|
||||
private:
|
||||
platform *platform;
|
||||
painter *painter;
|
||||
transform *transform;
|
||||
|
||||
std::vector<tile *> tiles;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
35
include/llmr/map/tile.hpp
Normal file
35
include/llmr/map/tile.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef LLMR_MAP_TILE
|
||||
#define LLMR_MAP_TILE
|
||||
|
||||
#include "../geometry/linevertexbuffer.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class tile {
|
||||
public:
|
||||
tile(int32_t z, int32_t x, int32_t y);
|
||||
|
||||
void setData(uint8_t *data, uint32_t bytes);
|
||||
bool parse();
|
||||
void parseLayer(const uint8_t *data, uint32_t bytes);
|
||||
void parseFeature(const uint8_t *data, uint32_t bytes);
|
||||
void loadGeometry(const uint8_t *data, uint32_t bytes);
|
||||
|
||||
public:
|
||||
const int32_t z, x, y;
|
||||
bool loaded;
|
||||
linevertexbuffer lineVertex;
|
||||
|
||||
private:
|
||||
// Source data
|
||||
uint8_t *data;
|
||||
uint32_t bytes;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
22
include/llmr/map/transform.hpp
Normal file
22
include/llmr/map/transform.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef LLMR_MAP_TRANSFORM
|
||||
#define LLMR_MAP_TRANSFORM
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class tile;
|
||||
|
||||
class transform {
|
||||
public:
|
||||
transform();
|
||||
|
||||
void moveBy(double dx, double dy);
|
||||
void scaleBy(double ds, double cx, double cy);
|
||||
|
||||
public:
|
||||
double x, y;
|
||||
double scale;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
22
include/llmr/platform/gl.hpp
Normal file
22
include/llmr/platform/gl.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef LLMR_RENDERER_GL
|
||||
#define LLMR_RENDERER_GL
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "TargetConditionals.h"
|
||||
#if TARGET_OS_IPHONE
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#elif TARGET_IPHONE_SIMULATOR
|
||||
#include <OpenGLES/ES2/gl.h>
|
||||
#include <OpenGLES/ES2/glext.h>
|
||||
#elif TARGET_OS_MAC
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#else
|
||||
#error Unsupported Apple platform
|
||||
#endif
|
||||
#else
|
||||
#error Unsupported platform
|
||||
#endif
|
||||
|
||||
#endif
|
||||
24
include/llmr/platform/platform.hpp
Normal file
24
include/llmr/platform/platform.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef LLMR_PLATFORM_IOS
|
||||
#define LLMR_PLATFORM_IOS
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class tile;
|
||||
|
||||
class platform {
|
||||
public:
|
||||
platform(void *obj) : obj(obj) {}
|
||||
|
||||
const char *shaderSource(const char *name, const char *extension);
|
||||
void restart();
|
||||
void request(tile *tile);
|
||||
|
||||
private:
|
||||
void *obj;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
55
include/llmr/renderer/painter.hpp
Normal file
55
include/llmr/renderer/painter.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef LLMR_RENDERER_PAINTER
|
||||
#define LLMR_RENDERER_PAINTER
|
||||
|
||||
#include "../platform/gl.hpp"
|
||||
|
||||
#include "shader-fill.hpp"
|
||||
#include "shader-line.hpp"
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class platform;
|
||||
class transform;
|
||||
class tile;
|
||||
|
||||
class painter {
|
||||
public:
|
||||
painter(class platform *platform);
|
||||
|
||||
void setup();
|
||||
void teardown();
|
||||
|
||||
void resize(GLuint new_width, GLuint new_height);
|
||||
void viewport();
|
||||
|
||||
|
||||
void clear();
|
||||
void render(tile *tile);
|
||||
|
||||
void switchShader(Shader *shader, float matrix[16]);
|
||||
void setTransform(transform *transform);
|
||||
|
||||
private:
|
||||
void setupShaders();
|
||||
void changeMatrix();
|
||||
|
||||
public:
|
||||
|
||||
private:
|
||||
platform *platform;
|
||||
transform *transform;
|
||||
GLuint width, height;
|
||||
GLfloat matrix[16];
|
||||
|
||||
Shader *currentShader;
|
||||
FillShader *fillShader;
|
||||
LineShader *lineShader;
|
||||
|
||||
GLuint vertexArray;
|
||||
GLuint triangleVertexBuffer;
|
||||
GLuint fillVertexBuffer;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
19
include/llmr/renderer/shader-fill.hpp
Normal file
19
include/llmr/renderer/shader-fill.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef LLMR_RENDERER_SHADER_FILL
|
||||
#define LLMR_RENDERER_SHADER_FILL
|
||||
|
||||
#include "shader.hpp"
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class FillShader : public Shader {
|
||||
public:
|
||||
FillShader(const GLchar *vertex, const GLchar *fragment);
|
||||
|
||||
GLint a_pos;
|
||||
GLint u_matrix;
|
||||
GLint u_color;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
19
include/llmr/renderer/shader-line.hpp
Normal file
19
include/llmr/renderer/shader-line.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef LLMR_RENDERER_SHADER_LINE
|
||||
#define LLMR_RENDERER_SHADER_LINE
|
||||
|
||||
#include "shader.hpp"
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class LineShader : public Shader {
|
||||
public:
|
||||
LineShader(const GLchar *vertex, const GLchar *fragment);
|
||||
|
||||
GLint a_pos;
|
||||
GLint u_matrix;
|
||||
GLint u_color;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
23
include/llmr/renderer/shader.hpp
Normal file
23
include/llmr/renderer/shader.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef LLMR_RENDERER_SHADER
|
||||
#define LLMR_RENDERER_SHADER
|
||||
|
||||
#include "../platform/gl.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class Shader {
|
||||
public:
|
||||
Shader(const GLchar *vertex, const GLchar *fragment);
|
||||
~Shader();
|
||||
bool valid;
|
||||
GLuint program;
|
||||
std::vector<GLuint> attributes;
|
||||
|
||||
private:
|
||||
bool compileShader(GLuint *shader, GLenum type, const GLchar *source);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
41
include/llmr/util/mat4.h
Normal file
41
include/llmr/util/mat4.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// This is an incomplete port of http://glmatrix.net/
|
||||
//
|
||||
// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the
|
||||
// use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not claim
|
||||
// that you wrote the original software. If you use this software in a
|
||||
// product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#ifndef llmr_util_mat4_
|
||||
#define llmr_util_mat4_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void mat4_identity(float out[16]);
|
||||
void mat4_ortho(float out[16], float left, float right, float bottom, float top, float near, float far);
|
||||
void mat4_copy(float out[16], float a[16]);
|
||||
void mat4_translate(float out[16], float a[16], float x, float y, float z);
|
||||
void mat4_scale(float out[16], float a[16], float x, float y, float z);
|
||||
void mat4_multiply(float out[16], float a[16], float b[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
33
src/geometry/linevertexbuffer.cpp
Normal file
33
src/geometry/linevertexbuffer.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <llmr/geometry/linevertexbuffer.hpp>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
linevertexbuffer::linevertexbuffer()
|
||||
: buffer(0) {
|
||||
}
|
||||
|
||||
void linevertexbuffer::addDegenerate() {
|
||||
array.push_back(32767);
|
||||
array.push_back(0);
|
||||
}
|
||||
|
||||
void linevertexbuffer::addCoordinate(int16_t x, int16_t y) {
|
||||
array.push_back(x);
|
||||
array.push_back(y);
|
||||
}
|
||||
|
||||
uint32_t linevertexbuffer::length() {
|
||||
// We store 2 coordinates per vertex
|
||||
return array.size() / 2;
|
||||
}
|
||||
|
||||
void linevertexbuffer::bind() {
|
||||
if (buffer == 0) {
|
||||
glGenBuffers(1, &buffer);
|
||||
fprintf(stderr, "new buffer id: %d\n", buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, array.size() * sizeof(uint16_t), array.data(), GL_STATIC_DRAW);
|
||||
} else {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
}
|
||||
}
|
||||
64
src/map/map.cpp
Normal file
64
src/map/map.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#include <llmr/map/map.hpp>
|
||||
#include <llmr/map/tile.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
map::map(class platform *platform, class painter *painter)
|
||||
: platform(platform),
|
||||
painter(painter),
|
||||
transform(new class transform()) {
|
||||
|
||||
painter->setTransform(transform);
|
||||
|
||||
|
||||
tile *tile = new class tile(0, 0, 0);
|
||||
tiles.push_back(tile);
|
||||
platform->request(tile);
|
||||
|
||||
}
|
||||
|
||||
map::~map() {
|
||||
delete transform;
|
||||
}
|
||||
|
||||
|
||||
void map::moveBy(double dx, double dy) {
|
||||
transform->moveBy(dx, dy);
|
||||
platform->restart();
|
||||
}
|
||||
|
||||
void map::scaleBy(double ds, double cx, double cy) {
|
||||
transform->scaleBy(ds, cx, cy);
|
||||
platform->restart();
|
||||
}
|
||||
|
||||
|
||||
bool map::render() {
|
||||
painter->clear();
|
||||
|
||||
for (tile *tile : tiles) {
|
||||
// painter->viewport();
|
||||
if (tile->loaded) {
|
||||
painter->render(tile);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void map::tileLoaded(tile *tile) {
|
||||
platform->restart();
|
||||
// fprintf(stderr, "[%8zx] tile loaded %d/%d/%d\n",
|
||||
// std::hash<std::thread::id>()(std::this_thread::get_id()),
|
||||
// tile->z, tile->x, tile->y);
|
||||
// schedule rerender
|
||||
}
|
||||
|
||||
void map::tileFailed(tile *tile) {
|
||||
fprintf(stderr, "[%8zx] tile failed to load %d/%d/%d\n",
|
||||
std::hash<std::thread::id>()(std::this_thread::get_id()),
|
||||
tile->z, tile->x, tile->y);
|
||||
}
|
||||
178
src/map/pbf.hpp
Normal file
178
src/map/pbf.hpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Some parts are from upb - a minimalist implementation of protocol buffers.
|
||||
*
|
||||
* Copyright (c) 2008-2011 Google Inc. See LICENSE for details.
|
||||
* Author: Josh Haberman <jhaberman@gmail.com>
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
// #include <cassert>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
struct pbf {
|
||||
inline pbf(const unsigned char *data, uint32_t length);
|
||||
inline pbf(const char *data, uint32_t length);
|
||||
// inline pbf(const std::string& buffer);
|
||||
|
||||
inline bool next();
|
||||
inline uint64_t varint();
|
||||
inline int64_t svarint();
|
||||
inline std::string string();
|
||||
inline float float32();
|
||||
inline double float64();
|
||||
inline int64_t int64();
|
||||
inline bool boolean();
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline T *message(const Args&... args);
|
||||
|
||||
inline void skip();
|
||||
inline void skipValue(uint32_t val);
|
||||
inline void skipBytes(uint32_t bytes);
|
||||
|
||||
const uint8_t *data;
|
||||
const uint8_t *end;
|
||||
uint32_t value;
|
||||
uint32_t tag;
|
||||
};
|
||||
|
||||
pbf::pbf(const unsigned char *data, uint32_t length)
|
||||
: data(data),
|
||||
end(data + length)
|
||||
{}
|
||||
|
||||
pbf::pbf(const char *data, uint32_t length)
|
||||
: data((const unsigned char *)data),
|
||||
end((const unsigned char *)data + length)
|
||||
{}
|
||||
|
||||
// pbf::pbf(const std::string& buffer)
|
||||
// : data((const unsigned char *)buffer.data()),
|
||||
// end((const unsigned char *)buffer.data() + buffer.size())
|
||||
// {}
|
||||
|
||||
bool pbf::next()
|
||||
{
|
||||
if (data < end) {
|
||||
value = (uint32_t)varint();
|
||||
tag = value >> 3;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint64_t pbf::varint()
|
||||
{
|
||||
uint8_t byte = 0x80;
|
||||
uint64_t result = 0;
|
||||
int bitpos;
|
||||
for (bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
|
||||
if (data >= end) {
|
||||
fprintf(stderr, "unterminated varint, unexpected end of buffer");
|
||||
exit(1);
|
||||
}
|
||||
result |= ((uint64_t)(byte = *data) & 0x7F) << bitpos;
|
||||
|
||||
data++;
|
||||
}
|
||||
if (bitpos == 70 && (byte & 0x80)) {
|
||||
fprintf(stderr, "unterminated varint (too long)");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t pbf::svarint()
|
||||
{
|
||||
uint64_t n = varint();
|
||||
return (n >> 1) ^ -(int64_t)(n & 1);
|
||||
}
|
||||
|
||||
std::string pbf::string()
|
||||
{
|
||||
uint32_t bytes = (uint32_t)varint();
|
||||
const char *string = (const char *)data;
|
||||
skipBytes(bytes);
|
||||
return std::string(string, bytes);
|
||||
}
|
||||
|
||||
float pbf::float32()
|
||||
{
|
||||
skipBytes(4);
|
||||
float result;
|
||||
memcpy(&result, data - 4, 4);
|
||||
return result;
|
||||
}
|
||||
double pbf::float64()
|
||||
{
|
||||
skipBytes(8);
|
||||
double result;
|
||||
memcpy(&result, data - 8, 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
int64_t pbf::int64()
|
||||
{
|
||||
return (int64_t)varint();
|
||||
}
|
||||
|
||||
bool pbf::boolean()
|
||||
{
|
||||
skipBytes(1);
|
||||
return *(bool *)(data - 1);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename... Args> T *pbf::message(const Args&... args)
|
||||
{
|
||||
uint32_t bytes = (uint32_t)varint();
|
||||
T *result = new T(data, bytes, args...);
|
||||
skipBytes(bytes);
|
||||
return result;
|
||||
}
|
||||
|
||||
void pbf::skip()
|
||||
{
|
||||
skipValue(value);
|
||||
}
|
||||
|
||||
void pbf::skipValue(uint32_t val)
|
||||
{
|
||||
switch (val & 0x7) {
|
||||
case 0: // varint
|
||||
varint();
|
||||
break;
|
||||
case 1: // 64 bit
|
||||
skipBytes(8);
|
||||
break;
|
||||
case 2: // string/message
|
||||
skipBytes((uint32_t)varint());
|
||||
break;
|
||||
case 5: // 32 bit
|
||||
skipBytes(4);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "cannot skip unknown type %d", val & 0x7);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void pbf::skipBytes(uint32_t bytes)
|
||||
{
|
||||
data += bytes;
|
||||
if (data > end) {
|
||||
fprintf(stderr, "unexpected end of buffer");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llmr
|
||||
|
||||
138
src/map/tile.cpp
Normal file
138
src/map/tile.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <llmr/map/tile.hpp>
|
||||
|
||||
#include <stdint.h>
|
||||
// #include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "pbf.hpp"
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
tile::tile(int32_t z, int32_t x, int32_t y)
|
||||
: z(z),
|
||||
x(x),
|
||||
y(y),
|
||||
loaded(false),
|
||||
data(0),
|
||||
bytes(0) {
|
||||
}
|
||||
|
||||
void tile::setData(uint8_t *data, uint32_t bytes) {
|
||||
this->data = (uint8_t *)malloc(bytes);
|
||||
this->bytes = bytes;
|
||||
memcpy(this->data, data, bytes);
|
||||
}
|
||||
|
||||
bool tile::parse()
|
||||
{
|
||||
fprintf(stderr, "[%8zx] parsing tile\n",
|
||||
std::hash<std::thread::id>()(std::this_thread::get_id())
|
||||
);
|
||||
|
||||
// try {
|
||||
pbf tile(data, bytes);
|
||||
while (tile.next()) {
|
||||
if (tile.tag == 3) { // layer
|
||||
uint32_t bytes = (uint32_t)tile.varint();
|
||||
parseLayer(tile.data, bytes);
|
||||
tile.skipBytes(bytes);
|
||||
} else {
|
||||
tile.skip();
|
||||
}
|
||||
}
|
||||
// } catch (std::exception& ex) {
|
||||
// std::cerr << ex.what();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
loaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void tile::parseLayer(const uint8_t *data, uint32_t bytes) {
|
||||
pbf layer(data, bytes);
|
||||
std::string name;
|
||||
while (layer.next()) {
|
||||
if (layer.tag == 1) {
|
||||
name = layer.string();
|
||||
} else if (layer.tag == 2) {
|
||||
uint32_t bytes = (uint32_t)layer.varint();
|
||||
parseFeature(layer.data, bytes);
|
||||
layer.skipBytes(bytes);
|
||||
} else {
|
||||
layer.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tile::parseFeature(const uint8_t *data, uint32_t bytes) {
|
||||
pbf feature(data, bytes);
|
||||
while (feature.next()) {
|
||||
if (feature.tag == 1) {
|
||||
uint64_t id = feature.varint();
|
||||
} else if (feature.tag == 2) {
|
||||
const uint8_t *tag_end = feature.data + feature.varint();
|
||||
while (feature.data < tag_end) {
|
||||
uint32_t key = (uint32_t)feature.varint();
|
||||
uint32_t value = (uint32_t)feature.varint();
|
||||
}
|
||||
} else if (feature.tag == 3) {
|
||||
uint32_t type = (uint32_t)feature.varint();
|
||||
} else if (feature.tag == 4) {
|
||||
uint32_t bytes = (uint32_t)feature.varint();
|
||||
loadGeometry(feature.data, bytes);
|
||||
feature.skipBytes(bytes);
|
||||
} else {
|
||||
feature.skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tile::loadGeometry(const uint8_t *data, uint32_t bytes) {
|
||||
pbf geometry(data, bytes);
|
||||
|
||||
uint32_t cmd = 1;
|
||||
uint32_t length = 0;
|
||||
int32_t x = 0, y = 0;
|
||||
|
||||
// var lines = [];
|
||||
// var line = null;
|
||||
int32_t ox = 0, oy = 0;
|
||||
|
||||
while (geometry.data < geometry.end) {
|
||||
if (!length) {
|
||||
uint32_t cmd_length = (uint32_t)geometry.varint();
|
||||
cmd = cmd_length & 0x7;
|
||||
length = cmd_length >> 3;
|
||||
}
|
||||
|
||||
length--;
|
||||
|
||||
if (cmd == 1 || cmd == 2) {
|
||||
x += geometry.svarint();
|
||||
y += geometry.svarint();
|
||||
|
||||
if (cmd == 1) {
|
||||
// moveTo
|
||||
// fprintf(stderr, "[m %d/%d] ", x, y);
|
||||
// degenerate vertex
|
||||
lineVertex.addDegenerate();
|
||||
ox = x;
|
||||
oy = y;
|
||||
} else {
|
||||
// lineTo
|
||||
// fprintf(stderr, "[l %d/%d] ", x, y);
|
||||
}
|
||||
lineVertex.addCoordinate(x, y);
|
||||
} else if (cmd == 7) {
|
||||
// closePolygon
|
||||
// fprintf(stderr, "[c]\n");
|
||||
lineVertex.addCoordinate(ox, oy);
|
||||
} else {
|
||||
// throw new Error('unknown command ' + cmd);
|
||||
// throw std::runtime_error("unknown command");
|
||||
fprintf(stderr, "unknown command");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/map/transform.cpp
Normal file
21
src/map/transform.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <llmr/map/transform.hpp>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
transform::transform()
|
||||
: x(0.0f),
|
||||
y(0.0f),
|
||||
scale(1.0f) {
|
||||
|
||||
}
|
||||
|
||||
void transform::moveBy(double dx, double dy) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
|
||||
void transform::scaleBy(double ds, double cx, double cy) {
|
||||
scale *= ds;
|
||||
x = x * ds + cx * (1 - ds);
|
||||
y = y * ds + cy * (1 - ds);
|
||||
}
|
||||
226
src/renderer/painter.cpp
Normal file
226
src/renderer/painter.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
#include <llmr/renderer/painter.hpp>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include <llmr/util/mat4.h>
|
||||
#include <llmr/platform/platform.hpp>
|
||||
#include <llmr/map/transform.hpp>
|
||||
#include <llmr/map/tile.hpp>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||
|
||||
GLfloat triangle_vertices[] = {
|
||||
100, 100,
|
||||
100, 300,
|
||||
150, 150
|
||||
};
|
||||
|
||||
GLfloat fill_vertices[] = {
|
||||
0, 0,
|
||||
300, 0,
|
||||
0, 300,
|
||||
300, 300
|
||||
};
|
||||
|
||||
|
||||
painter::painter(class platform *platform)
|
||||
: platform(platform),
|
||||
transform(NULL),
|
||||
width(0),
|
||||
height(0),
|
||||
currentShader(NULL),
|
||||
fillShader(NULL) {
|
||||
|
||||
}
|
||||
|
||||
void painter::setTransform(class transform *transform) {
|
||||
this->transform = transform;
|
||||
}
|
||||
|
||||
|
||||
void painter::setup() {
|
||||
setupShaders();
|
||||
|
||||
|
||||
assert(fillShader);
|
||||
|
||||
|
||||
|
||||
glGenBuffers(1, &triangleVertexBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_vertices), triangle_vertices, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &fillVertexBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, fillVertexBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(fill_vertices), fill_vertices, GL_STATIC_DRAW);
|
||||
|
||||
|
||||
// glGenVertexArraysOES(1, &vertexArray);
|
||||
// glBindVertexArrayOES(vertexArray);
|
||||
// glBindVertexArrayOES(0);
|
||||
}
|
||||
|
||||
void painter::setupShaders() {
|
||||
const GLchar *vertexSource, *fragmentSource;
|
||||
|
||||
vertexSource = platform->shaderSource("fill", "vertex.glsl");
|
||||
assert((vertexSource, "Missing fill vertex shader source"));
|
||||
fragmentSource = platform->shaderSource("fill", "fragment.glsl");
|
||||
assert((fragmentSource, "Missing fill fragment shader source"));
|
||||
|
||||
fillShader = new FillShader(vertexSource, fragmentSource);
|
||||
|
||||
vertexSource = platform->shaderSource("line", "vertex.glsl");
|
||||
assert((vertexSource, "Missing line vertex shader source"));
|
||||
fragmentSource = platform->shaderSource("line", "fragment.glsl");
|
||||
assert((fragmentSource, "Missing line fragment shader source"));
|
||||
lineShader = new LineShader(vertexSource, fragmentSource);
|
||||
}
|
||||
|
||||
void painter::teardown() {
|
||||
glDeleteBuffers(1, &triangleVertexBuffer);
|
||||
glDeleteBuffers(1, &fillVertexBuffer);
|
||||
|
||||
// glDeleteVertexArraysOES(1, &vertexArray);
|
||||
|
||||
if (fillShader) {
|
||||
delete fillShader;
|
||||
fillShader = NULL;
|
||||
}
|
||||
|
||||
if (lineShader) {
|
||||
delete lineShader;
|
||||
lineShader = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void painter::resize(GLuint new_width, GLuint new_height) {
|
||||
if (width == new_width && height == new_height) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "changing viewport size to %d/%d\n", new_width, new_height);
|
||||
width = new_width;
|
||||
height = new_height;
|
||||
}
|
||||
|
||||
void painter::changeMatrix() {
|
||||
assert(transform);
|
||||
|
||||
// Initialize projection matrix
|
||||
float projMatrix[16];
|
||||
mat4_ortho(projMatrix, 0, width, height, 0, 1, 10);
|
||||
|
||||
float mvMatrix[16];
|
||||
mat4_identity(mvMatrix);
|
||||
mat4_translate(mvMatrix, mvMatrix, transform->x, transform->y, -1);
|
||||
mat4_scale(mvMatrix, mvMatrix, transform->scale / 8, transform->scale / 8, 1);
|
||||
|
||||
mat4_multiply(matrix, projMatrix, mvMatrix);
|
||||
}
|
||||
|
||||
void painter::clear() {
|
||||
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void painter::render(tile *tile) {
|
||||
changeMatrix();
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// fprintf(stderr, "render tile\n");
|
||||
switchShader(lineShader, matrix);
|
||||
glUniformMatrix4fv(lineShader->u_matrix, 1, GL_FALSE, matrix);
|
||||
|
||||
// glEnable(GL_BLEND);
|
||||
|
||||
// glVertexAttribPointer(fillShader->a_pos, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
// glVertexAttribPointer(fillShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBuffer);
|
||||
tile->lineVertex.bind();
|
||||
glVertexAttribPointer(lineShader->a_pos, 2, GL_SHORT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
glUniform4f(lineShader->u_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glLineWidth(1.0f);
|
||||
glDrawArrays(GL_LINE_STRIP, 0, tile->lineVertex.length());
|
||||
|
||||
// switchShader(fillShader, matrix);
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBuffer);
|
||||
// glVertexAttribPointer(fillShader->a_pos, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
// glUniform4f(fillShader->u_color, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||
// glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
|
||||
|
||||
|
||||
|
||||
|
||||
// glBindVertexArrayOES(vertexArray);
|
||||
// switchShader(fillShader, matrix);
|
||||
// glUniformMatrix4fv(fillShader->u_matrix, 1, GL_FALSE, matrix);
|
||||
|
||||
// glEnable(GL_STENCIL_TEST);
|
||||
|
||||
// Draw stencil mask.
|
||||
// glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
// glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
|
||||
// glStencilFunc(GL_EQUAL, 0xFF, 0xFF);
|
||||
// glStencilMask(0xFF);
|
||||
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBuffer);
|
||||
// glVertexAttribPointer(fillShader->a_pos, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
// glUniform4f(fillShader->u_color, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||
// glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
|
||||
|
||||
|
||||
// // Draw covering fill.
|
||||
// glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
// glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
// glStencilFunc(GL_EQUAL, 0xFF, 0xFF);
|
||||
|
||||
// glBindBuffer(GL_ARRAY_BUFFER, fillVertexBuffer);
|
||||
// glVertexAttribPointer(fillShader->a_pos, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||
// glUniform4f(fillShader->u_color, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
// glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
void painter::viewport() {
|
||||
|
||||
}
|
||||
|
||||
// Switches to a different shader program.
|
||||
void painter::switchShader(Shader *shader, float matrix[16]) {
|
||||
if (currentShader != shader) {
|
||||
glUseProgram(shader->program);
|
||||
|
||||
// Disable all attributes from the existing shader that aren't used in
|
||||
// the new shader. Note: attribute indices are *not* program specific!
|
||||
if (currentShader) {
|
||||
// const std::vector<GLuint> &enabled = currentShader->attributes;
|
||||
// const std::vector<GLuint> &required = shader->attributes;
|
||||
// TODO
|
||||
|
||||
// for (var i = 0; i < enabled.length; i++) {
|
||||
// if (required.indexOf(enabled[i]) < 0) {
|
||||
// gl.disableVertexAttribArray(enabled[i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Enable all attributes for the new shader.
|
||||
// for (var j = 0; j < required.length; j++) {
|
||||
// if (enabled.indexOf(required[j]) < 0) {
|
||||
// gl.enableVertexAttribArray(required[j]);
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
// Enable all attributes for the new shader.
|
||||
for (GLuint index : shader->attributes) {
|
||||
glEnableVertexAttribArray(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentShader = shader;
|
||||
}
|
||||
14
src/renderer/shader-fill.cpp
Normal file
14
src/renderer/shader-fill.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <llmr/renderer/shader-fill.hpp>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
FillShader::FillShader(const GLchar *vertSource, const GLchar *fragSource)
|
||||
: Shader(vertSource, fragSource) {
|
||||
if (!valid) return;
|
||||
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
attributes.push_back(a_pos);
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_color = glGetUniformLocation(program, "u_color");
|
||||
}
|
||||
14
src/renderer/shader-line.cpp
Normal file
14
src/renderer/shader-line.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <llmr/renderer/shader-line.hpp>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
LineShader::LineShader(const GLchar *vertSource, const GLchar *fragSource)
|
||||
: Shader(vertSource, fragSource) {
|
||||
if (!valid) return;
|
||||
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
attributes.push_back(a_pos);
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_color = glGetUniformLocation(program, "u_color");
|
||||
}
|
||||
134
src/renderer/shader.cpp
Normal file
134
src/renderer/shader.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include <llmr/renderer/shader.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
Shader::Shader(const GLchar *vertSource, const GLchar *fragSource)
|
||||
: valid(false),
|
||||
program(0) {
|
||||
|
||||
GLuint vertShader;
|
||||
if (!compileShader(&vertShader, GL_VERTEX_SHADER, vertSource)) {
|
||||
fprintf(stderr, "Vertex shader failed to compile: %s\n", vertSource);
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint fragShader;
|
||||
if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, fragSource)) {
|
||||
fprintf(stderr, "Fragment shader failed to compile: %s\n", fragSource);
|
||||
return;
|
||||
}
|
||||
|
||||
program = glCreateProgram();
|
||||
|
||||
// Attach shaders
|
||||
glAttachShader(program, vertShader);
|
||||
glAttachShader(program, fragShader);
|
||||
|
||||
|
||||
{
|
||||
// Link program
|
||||
GLint status;
|
||||
glLinkProgram(program);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(program, logLength, &logLength, log);
|
||||
fprintf(stderr, "Program link log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
if (status == 0) {
|
||||
fprintf(stderr, "Program failed to link\n");
|
||||
glDeleteShader(vertShader);
|
||||
vertShader = 0;
|
||||
glDeleteShader(fragShader);
|
||||
fragShader = 0;
|
||||
glDeleteProgram(program);
|
||||
program = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Validate program
|
||||
GLint status;
|
||||
glValidateProgram(program);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetProgramInfoLog(program, logLength, &logLength, log);
|
||||
fprintf(stderr, "Program validate log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
|
||||
if (status == 0) {
|
||||
fprintf(stderr, "Program failed to validate\n");
|
||||
glDeleteShader(vertShader);
|
||||
vertShader = 0;
|
||||
glDeleteShader(fragShader);
|
||||
fragShader = 0;
|
||||
glDeleteProgram(program);
|
||||
program = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Remove the compiled shaders; they are now part of the program.
|
||||
glDetachShader(program, vertShader);
|
||||
glDeleteShader(vertShader);
|
||||
glDetachShader(program, fragShader);
|
||||
glDeleteShader(fragShader);
|
||||
|
||||
|
||||
fprintf(stderr, "successfully compiled shader\n");
|
||||
valid = true;
|
||||
}
|
||||
|
||||
|
||||
bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
|
||||
GLint status;
|
||||
|
||||
*shader = glCreateShader(type);
|
||||
glShaderSource(*shader, 1, &source, NULL);
|
||||
glCompileShader(*shader);
|
||||
|
||||
#if defined(DEBUG)
|
||||
GLint logLength;
|
||||
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
|
||||
if (logLength > 0) {
|
||||
GLchar *log = (GLchar *)malloc(logLength);
|
||||
glGetShaderInfoLog(*shader, logLength, &logLength, log);
|
||||
fprintf(stderr, "Shader compile log:\n%s", log);
|
||||
free(log);
|
||||
}
|
||||
#endif
|
||||
|
||||
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
|
||||
if (status == 0) {
|
||||
glDeleteShader(*shader);
|
||||
*shader = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Shader::~Shader() {
|
||||
if (program) {
|
||||
glDeleteProgram(program);
|
||||
program = 0;
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
5
src/shader/fill.fragment.glsl
Normal file
5
src/shader/fill.fragment.glsl
Normal file
@@ -0,0 +1,5 @@
|
||||
uniform vec4 u_color;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = u_color;
|
||||
}
|
||||
7
src/shader/fill.vertex.glsl
Normal file
7
src/shader/fill.vertex.glsl
Normal file
@@ -0,0 +1,7 @@
|
||||
attribute vec2 a_pos;
|
||||
|
||||
uniform mat4 u_matrix;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
}
|
||||
5
src/shader/line.fragment.glsl
Normal file
5
src/shader/line.fragment.glsl
Normal file
@@ -0,0 +1,5 @@
|
||||
uniform vec4 u_color;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = u_color;
|
||||
}
|
||||
8
src/shader/line.vertex.glsl
Normal file
8
src/shader/line.vertex.glsl
Normal file
@@ -0,0 +1,8 @@
|
||||
attribute vec2 a_pos;
|
||||
|
||||
uniform mat4 u_matrix;
|
||||
|
||||
void main() {
|
||||
float z = step(32767.0, a_pos.x) * 2.0;
|
||||
gl_Position = u_matrix * vec4(a_pos, z, 1);
|
||||
}
|
||||
160
src/util/mat4.c
Normal file
160
src/util/mat4.c
Normal file
@@ -0,0 +1,160 @@
|
||||
// This is an incomplete port of http://glmatrix.net/
|
||||
//
|
||||
// Copyright (c) 2013 Brandon Jones, Colin MacKenzie IV
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the
|
||||
// use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not claim
|
||||
// that you wrote the original software. If you use this software in a
|
||||
// product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
#include <llmr/util/mat4.h>
|
||||
|
||||
void mat4_identity(float out[16]) {
|
||||
out[0] = 1.0f;
|
||||
out[1] = 0.0f;
|
||||
out[2] = 0.0f;
|
||||
out[3] = 0.0f;
|
||||
out[4] = 0.0f;
|
||||
out[5] = 1.0f;
|
||||
out[6] = 0.0f;
|
||||
out[7] = 0.0f;
|
||||
out[8] = 0.0f;
|
||||
out[9] = 0.0f;
|
||||
out[10] = 1.0f;
|
||||
out[11] = 0.0f;
|
||||
out[12] = 0.0f;
|
||||
out[13] = 0.0f;
|
||||
out[14] = 0.0f;
|
||||
out[15] = 1.0f;
|
||||
}
|
||||
|
||||
void mat4_ortho(float out[16], float left, float right, float bottom, float top, float near, float far) {
|
||||
float lr = 1.0f / (left - right),
|
||||
bt = 1.0f / (bottom - top),
|
||||
nf = 1.0f / (near - far);
|
||||
out[0] = -2.0f * lr;
|
||||
out[1] = 0.0f;
|
||||
out[2] = 0.0f;
|
||||
out[3] = 0.0f;
|
||||
out[4] = 0.0f;
|
||||
out[5] = -2.0f * bt;
|
||||
out[6] = 0.0f;
|
||||
out[7] = 0.0f;
|
||||
out[8] = 0.0f;
|
||||
out[9] = 0.0f;
|
||||
out[10] = 2.0f * nf;
|
||||
out[11] = 0.0f;
|
||||
out[12] = (left + right) * lr;
|
||||
out[13] = (top + bottom) * bt;
|
||||
out[14] = (far + near) * nf;
|
||||
out[15] = 1.0f;
|
||||
}
|
||||
|
||||
void mat4_copy(float out[16], float a[16]) {
|
||||
out[0] = a[0];
|
||||
out[1] = a[1];
|
||||
out[2] = a[2];
|
||||
out[3] = a[3];
|
||||
out[4] = a[4];
|
||||
out[5] = a[5];
|
||||
out[6] = a[6];
|
||||
out[7] = a[7];
|
||||
out[8] = a[8];
|
||||
out[9] = a[9];
|
||||
out[10] = a[10];
|
||||
out[11] = a[11];
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
}
|
||||
|
||||
void mat4_translate(float out[16], float a[16], float x, float y, float z) {
|
||||
float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
|
||||
|
||||
out[0] = a00 + a03 * x;
|
||||
out[1] = a01 + a03 * y;
|
||||
out[2] = a02 + a03 * z;
|
||||
out[3] = a03;
|
||||
|
||||
out[4] = a10 + a13 * x;
|
||||
out[5] = a11 + a13 * y;
|
||||
out[6] = a12 + a13 * z;
|
||||
out[7] = a13;
|
||||
|
||||
out[8] = a20 + a23 * x;
|
||||
out[9] = a21 + a23 * y;
|
||||
out[10] = a22 + a23 * z;
|
||||
out[11] = a23;
|
||||
out[12] = a30 + a33 * x;
|
||||
out[13] = a31 + a33 * y;
|
||||
out[14] = a32 + a33 * z;
|
||||
out[15] = a33;
|
||||
}
|
||||
|
||||
void mat4_scale(float out[16], float a[16], float x, float y, float z) {
|
||||
out[0] = a[0] * x;
|
||||
out[1] = a[1] * x;
|
||||
out[2] = a[2] * x;
|
||||
out[3] = a[3] * x;
|
||||
out[4] = a[4] * y;
|
||||
out[5] = a[5] * y;
|
||||
out[6] = a[6] * y;
|
||||
out[7] = a[7] * y;
|
||||
out[8] = a[8] * z;
|
||||
out[9] = a[9] * z;
|
||||
out[10] = a[10] * z;
|
||||
out[11] = a[11] * z;
|
||||
out[12] = a[12];
|
||||
out[13] = a[13];
|
||||
out[14] = a[14];
|
||||
out[15] = a[15];
|
||||
}
|
||||
|
||||
void mat4_multiply(float out[16], float a[16], float b[16]) {
|
||||
float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
|
||||
|
||||
// Cache only the current line of the second matrix
|
||||
float b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
|
||||
out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
||||
out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
||||
out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
||||
out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
||||
|
||||
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
|
||||
out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
||||
out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
||||
out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
||||
out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
||||
|
||||
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
|
||||
out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
||||
out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
||||
out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
||||
out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
||||
|
||||
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
|
||||
out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
||||
out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
||||
out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
||||
out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
||||
}
|
||||
Reference in New Issue
Block a user