initial
This commit is contained in:
commit
d8443b3c8c
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.~*
|
||||||
|
.\#*
|
||||||
|
\#*
|
||||||
|
*~
|
||||||
|
*.o
|
||||||
|
main
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
50
Makefile
Normal file
50
Makefile
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#PREFIX = x86_64-w64-mingw32-
|
||||||
|
CC=$(PREFIX)gcc
|
||||||
|
CXX=$(PREFIX)g++
|
||||||
|
|
||||||
|
OPT = -Og -march=x86-64-v3
|
||||||
|
|
||||||
|
CSTD = -std=gnu23
|
||||||
|
CXXSTD = -std=gnu++23
|
||||||
|
CFLAGS += -g
|
||||||
|
CFLAGS += -fpic
|
||||||
|
CFLAGS += -I./include
|
||||||
|
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -Wno-error=unused-but-set-variable
|
||||||
|
CFLAGS += -Wno-error=unknown-pragmas -Wno-unknown-pragmas
|
||||||
|
CFLAGS += $(shell pkg-config --cflags glfw3)
|
||||||
|
|
||||||
|
LDFLAGS += -lm
|
||||||
|
LDFLAGS += $(shell pkg-config --libs glfw3)
|
||||||
|
|
||||||
|
OBJS = \
|
||||||
|
src/gl.o \
|
||||||
|
src/opengl.o \
|
||||||
|
src/test.o
|
||||||
|
|
||||||
|
all: test.so
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(ARCH) $(CSTD) $(CFLAGS) $(OPT) -c $< -o $@
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CXX) $(ARCH) $(CXXSTD) $(CFLAGS) $(OPT) -c $< -o $@
|
||||||
|
|
||||||
|
test.so: $(OBJS)
|
||||||
|
$(CC) $(ARCH) $(OPT) -shared -g $^ -o $@ -lSDL3
|
||||||
|
|
||||||
|
main: $(OBJS) src/main.o
|
||||||
|
$(CC) $(ARCH) $(LDFLAGS) $(OPT) -g $^ -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
find . -type f ! -name "*.*" -delete
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.INTERMEDIATE:
|
||||||
|
.SECONDARY:
|
||||||
|
.PHONY: all clean phony
|
||||||
|
|
||||||
|
%: RCS/%,v
|
||||||
|
%: RCS/%
|
||||||
|
%: %,v
|
||||||
|
%: s.%
|
||||||
|
%: SCCS/s.%
|
||||||
7
conf.lua
Normal file
7
conf.lua
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
function love.conf(t)
|
||||||
|
t.window.width = 1024
|
||||||
|
t.window.height = 1024
|
||||||
|
t.window.depth = true
|
||||||
|
t.window.resizable = true
|
||||||
|
t.graphics.excluderenderers = {"vulkan", "metal"}
|
||||||
|
end
|
||||||
311
include/KHR/khrplatform.h
Normal file
311
include/KHR/khrplatform.h
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
#ifndef __khrplatform_h_
|
||||||
|
#define __khrplatform_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
** copy of this software and/or associated documentation files (the
|
||||||
|
** "Materials"), to deal in the Materials without restriction, including
|
||||||
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
** the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included
|
||||||
|
** in all copies or substantial portions of the Materials.
|
||||||
|
**
|
||||||
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Khronos platform-specific types and definitions.
|
||||||
|
*
|
||||||
|
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||||
|
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||||
|
* The last semantic modification to khrplatform.h was at commit ID:
|
||||||
|
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||||
|
*
|
||||||
|
* Adopters may modify this file to suit their platform. Adopters are
|
||||||
|
* encouraged to submit platform specific modifications to the Khronos
|
||||||
|
* group so that they can be included in future versions of this file.
|
||||||
|
* Please submit changes by filing pull requests or issues on
|
||||||
|
* the EGL Registry repository linked above.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* See the Implementer's Guidelines for information about where this file
|
||||||
|
* should be located on your system and for more details of its use:
|
||||||
|
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||||
|
*
|
||||||
|
* This file should be included as
|
||||||
|
* #include <KHR/khrplatform.h>
|
||||||
|
* by Khronos client API header files that use its types and defines.
|
||||||
|
*
|
||||||
|
* The types in khrplatform.h should only be used to define API-specific types.
|
||||||
|
*
|
||||||
|
* Types defined in khrplatform.h:
|
||||||
|
* khronos_int8_t signed 8 bit
|
||||||
|
* khronos_uint8_t unsigned 8 bit
|
||||||
|
* khronos_int16_t signed 16 bit
|
||||||
|
* khronos_uint16_t unsigned 16 bit
|
||||||
|
* khronos_int32_t signed 32 bit
|
||||||
|
* khronos_uint32_t unsigned 32 bit
|
||||||
|
* khronos_int64_t signed 64 bit
|
||||||
|
* khronos_uint64_t unsigned 64 bit
|
||||||
|
* khronos_intptr_t signed same number of bits as a pointer
|
||||||
|
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||||
|
* khronos_ssize_t signed size
|
||||||
|
* khronos_usize_t unsigned size
|
||||||
|
* khronos_float_t signed 32 bit floating point
|
||||||
|
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||||
|
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||||
|
* nanoseconds
|
||||||
|
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||||
|
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||||
|
* only be used as a base type when a client API's boolean type is
|
||||||
|
* an enum. Client APIs which use an integer or other type for
|
||||||
|
* booleans cannot use this as the base type for their boolean.
|
||||||
|
*
|
||||||
|
* Tokens defined in khrplatform.h:
|
||||||
|
*
|
||||||
|
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||||
|
*
|
||||||
|
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||||
|
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||||
|
*
|
||||||
|
* Calling convention macros defined in this file:
|
||||||
|
* KHRONOS_APICALL
|
||||||
|
* KHRONOS_APIENTRY
|
||||||
|
* KHRONOS_APIATTRIBUTES
|
||||||
|
*
|
||||||
|
* These may be used in function prototypes as:
|
||||||
|
*
|
||||||
|
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||||
|
* int arg1,
|
||||||
|
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||||
|
# define KHRONOS_STATIC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APICALL
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This precedes the return type of the function in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(KHRONOS_STATIC)
|
||||||
|
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||||
|
* header compatible with static linking. */
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
# define KHRONOS_APICALL __declspec(dllimport)
|
||||||
|
#elif defined (__SYMBIAN32__)
|
||||||
|
# define KHRONOS_APICALL IMPORT_C
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIENTRY
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the return type of the function and precedes the function
|
||||||
|
* name in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||||
|
/* Win32 but not WinCE */
|
||||||
|
# define KHRONOS_APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIATTRIBUTES
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the closing parenthesis of the function prototype arguments.
|
||||||
|
*/
|
||||||
|
#if defined (__ARMCC_2__)
|
||||||
|
#define KHRONOS_APIATTRIBUTES __softfp
|
||||||
|
#else
|
||||||
|
#define KHRONOS_APIATTRIBUTES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* basic type definitions
|
||||||
|
*-----------------------------------------------------------------------*/
|
||||||
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <stdint.h>
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
/*
|
||||||
|
* To support platform where unsigned long cannot be used interchangeably with
|
||||||
|
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
||||||
|
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
||||||
|
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
||||||
|
* unsigned long long or similar (this results in different C++ name mangling).
|
||||||
|
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
||||||
|
* platforms where the size of a pointer is larger than the size of long.
|
||||||
|
*/
|
||||||
|
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
||||||
|
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
||||||
|
#define KHRONOS_USE_INTPTR_T
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__VMS ) || defined(__sgi)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <inttypes.h>
|
||||||
|
*/
|
||||||
|
#include <inttypes.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32
|
||||||
|
*/
|
||||||
|
typedef __int32 khronos_int32_t;
|
||||||
|
typedef unsigned __int32 khronos_uint32_t;
|
||||||
|
typedef __int64 khronos_int64_t;
|
||||||
|
typedef unsigned __int64 khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__sun__) || defined(__digital__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sun or Digital
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#if defined(__arch64__) || defined(_LP64)
|
||||||
|
typedef long int khronos_int64_t;
|
||||||
|
typedef unsigned long int khronos_uint64_t;
|
||||||
|
#else
|
||||||
|
typedef long long int khronos_int64_t;
|
||||||
|
typedef unsigned long long int khronos_uint64_t;
|
||||||
|
#endif /* __arch64__ */
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypothetical platform with no float or int64 support
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 0
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic fallback
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that are (so far) the same on all platforms
|
||||||
|
*/
|
||||||
|
typedef signed char khronos_int8_t;
|
||||||
|
typedef unsigned char khronos_uint8_t;
|
||||||
|
typedef signed short int khronos_int16_t;
|
||||||
|
typedef unsigned short int khronos_uint16_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||||
|
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||||
|
* to be the only LLP64 architecture in current use.
|
||||||
|
*/
|
||||||
|
#ifdef KHRONOS_USE_INTPTR_T
|
||||||
|
typedef intptr_t khronos_intptr_t;
|
||||||
|
typedef uintptr_t khronos_uintptr_t;
|
||||||
|
#elif defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_intptr_t;
|
||||||
|
typedef unsigned long long int khronos_uintptr_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_intptr_t;
|
||||||
|
typedef unsigned long int khronos_uintptr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_ssize_t;
|
||||||
|
typedef unsigned long long int khronos_usize_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_ssize_t;
|
||||||
|
typedef unsigned long int khronos_usize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_FLOAT
|
||||||
|
/*
|
||||||
|
* Float type
|
||||||
|
*/
|
||||||
|
typedef float khronos_float_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_INT64
|
||||||
|
/* Time types
|
||||||
|
*
|
||||||
|
* These types can be used to represent a time interval in nanoseconds or
|
||||||
|
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||||
|
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||||
|
* time the system booted). The Unadjusted System Time is an unsigned
|
||||||
|
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||||
|
* may be either signed or unsigned.
|
||||||
|
*/
|
||||||
|
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||||
|
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy value used to pad enum types to 32 bits.
|
||||||
|
*/
|
||||||
|
#ifndef KHRONOS_MAX_ENUM
|
||||||
|
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerated boolean type
|
||||||
|
*
|
||||||
|
* Values other than zero should be considered to be true. Therefore
|
||||||
|
* comparisons should not be made against KHRONOS_TRUE.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
KHRONOS_FALSE = 0,
|
||||||
|
KHRONOS_TRUE = 1,
|
||||||
|
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||||
|
} khronos_boolean_enum_t;
|
||||||
|
|
||||||
|
#endif /* __khrplatform_h_ */
|
||||||
2221
include/directxmath/directxmath.h
Normal file
2221
include/directxmath/directxmath.h
Normal file
File diff suppressed because it is too large
Load Diff
2187
include/directxmath/directxmathconvert.inl
Normal file
2187
include/directxmath/directxmathconvert.inl
Normal file
File diff suppressed because it is too large
Load Diff
3413
include/directxmath/directxmathmatrix.inl
Normal file
3413
include/directxmath/directxmathmatrix.inl
Normal file
File diff suppressed because it is too large
Load Diff
2425
include/directxmath/directxmathmisc.inl
Normal file
2425
include/directxmath/directxmathmisc.inl
Normal file
File diff suppressed because it is too large
Load Diff
14689
include/directxmath/directxmathvector.inl
Normal file
14689
include/directxmath/directxmathvector.inl
Normal file
File diff suppressed because it is too large
Load Diff
3199
include/glad/gl.h
Normal file
3199
include/glad/gl.h
Normal file
File diff suppressed because it is too large
Load Diff
14
include/opengl.h
Normal file
14
include/opengl.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void * read_file(const char * filename, int * out_size);
|
||||||
|
|
||||||
|
unsigned int compile_from_files(const char * vertex_path,
|
||||||
|
const char * fragment_path);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
2941
include/sal.h
Normal file
2941
include/sal.h
Normal file
File diff suppressed because it is too large
Load Diff
13
include/test.h
Normal file
13
include/test.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void load();
|
||||||
|
void draw();
|
||||||
|
void update(float lx, float ly, float ry);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
56
main.lua
Normal file
56
main.lua
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
local ffi = require 'ffi'
|
||||||
|
local joysticks
|
||||||
|
|
||||||
|
function init()
|
||||||
|
joysticks = love.joystick.getJoysticks()
|
||||||
|
|
||||||
|
ffi.cdef[[
|
||||||
|
void load();
|
||||||
|
void draw();
|
||||||
|
void update(float lx, float ly, float ry);
|
||||||
|
]]
|
||||||
|
test = ffi.load("./test.so")
|
||||||
|
test.load()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local update = function(dt)
|
||||||
|
for _, joystick in ipairs(joysticks) do
|
||||||
|
local lx = joystick:getGamepadAxis("leftx")
|
||||||
|
local ly = joystick:getGamepadAxis("lefty")
|
||||||
|
local ry = joystick:getGamepadAxis("righty")
|
||||||
|
test.update(lx, ly, ry)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local draw = function()
|
||||||
|
test.draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
function love.run()
|
||||||
|
init()
|
||||||
|
|
||||||
|
love.timer.step()
|
||||||
|
|
||||||
|
return function()
|
||||||
|
love.event.pump()
|
||||||
|
for name, a,b,c,d,e,f,g,h in love.event.poll() do
|
||||||
|
if name == "quit" then
|
||||||
|
if c or not love.quit or not love.quit() then
|
||||||
|
return a or 0, b
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if name == "keypressed" then
|
||||||
|
keypressed(a, b, c)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local dt = love.timer.step()
|
||||||
|
update(dt)
|
||||||
|
|
||||||
|
draw()
|
||||||
|
|
||||||
|
love.graphics.present()
|
||||||
|
love.timer.sleep(0.001)
|
||||||
|
end
|
||||||
|
end
|
||||||
BIN
minecraft/block_id_to_texture_id.data
Normal file
BIN
minecraft/block_id_to_texture_id.data
Normal file
Binary file not shown.
104
minecraft/gen/blocks.py
Normal file
104
minecraft/gen/blocks.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import struct
|
||||||
|
|
||||||
|
def id_to_px(i):
|
||||||
|
x = i % 16
|
||||||
|
y = i // 16
|
||||||
|
return x * 16, y * 16
|
||||||
|
|
||||||
|
def px_to_id(px, py):
|
||||||
|
x = px // 16
|
||||||
|
y = py // 16
|
||||||
|
i = y * 16 + x
|
||||||
|
return i
|
||||||
|
|
||||||
|
unk = 185
|
||||||
|
|
||||||
|
mapping = [
|
||||||
|
(1, 1, "stone"),
|
||||||
|
(2, 0, "grass"),
|
||||||
|
(31, 0, "grass"), # fixme actually tallgrass
|
||||||
|
(3, 2, "dirt"),
|
||||||
|
(4, 16, "stonebrick"),
|
||||||
|
(5, 4, "wood"),
|
||||||
|
(6, 15, "sapling"),
|
||||||
|
(7, 17, "bedrock"),
|
||||||
|
(8, 205, "water"), # flowing
|
||||||
|
(9, 205, "water"), # still
|
||||||
|
(10, 237, "lava"), # flowing
|
||||||
|
(11, 237, "lava"), # still
|
||||||
|
(12, 18, "sand"),
|
||||||
|
(13, 19, "gravel"),
|
||||||
|
(14, 32, "oreGold"),
|
||||||
|
(15, 33, "oreIron"),
|
||||||
|
(16, 34, "oreCoal"),
|
||||||
|
(17, 20, "log"),
|
||||||
|
(18, 52, "leaves"),
|
||||||
|
(19, 48, "sponge"),
|
||||||
|
(20, 49, "glass"),
|
||||||
|
(35, 64, "cloth"),
|
||||||
|
(37, 13, "flower"),
|
||||||
|
(38, 12, "rose"),
|
||||||
|
(39, 29, "mushroom"),
|
||||||
|
(40, 28, "mushroom"),
|
||||||
|
(41, 39, "blockGold"),
|
||||||
|
(42, 38, "blockIron"),
|
||||||
|
(43, 5, "stoneSlab"), # double
|
||||||
|
(44, 5, "stoneSlab"), # single
|
||||||
|
(45, 7, "brick"),
|
||||||
|
(46, 8, "tnt"),
|
||||||
|
(47, 35, "bookshelf"),
|
||||||
|
(48, 36, "stoneMoss"),
|
||||||
|
(49, 37, "obsidian"),
|
||||||
|
(50, 80, "torch"),
|
||||||
|
(51, 31, "fire"),
|
||||||
|
(52, 65, "mobSpawner"),
|
||||||
|
(53, 4, "stairsWood"),
|
||||||
|
(54, 27, "chest"),
|
||||||
|
(55, 84, "redstoneDust"),
|
||||||
|
(56, 50, "oreDiamond"),
|
||||||
|
(57, 40, "blockDiamond"),
|
||||||
|
(58, 43, "workbench"),
|
||||||
|
(59, 88, "crops"),
|
||||||
|
(60, 87, "farmland"),
|
||||||
|
(61, 44, "furnace"), # off
|
||||||
|
(62, 61, "furnace"), # burning
|
||||||
|
(63, unk, "sign"),
|
||||||
|
(64, 81, "doorWood"),
|
||||||
|
(65, 83, "ladder"),
|
||||||
|
(66, 128, "rail"),
|
||||||
|
(67, 16, "stairsStone"),
|
||||||
|
(68, unk, "sign"),
|
||||||
|
(69, 96, "lever"),
|
||||||
|
(70, 6, "pressurePlate"),
|
||||||
|
(71, 82, "doorIron"),
|
||||||
|
(72, 6, "pressurePlate"),
|
||||||
|
(73, 51, "oreRedstone"),
|
||||||
|
(74, 51, "oreRedstone"),
|
||||||
|
(75, 115, "notGate"),
|
||||||
|
(76, 99, "notGate"),
|
||||||
|
(77, unk, "button"),
|
||||||
|
(78, 66, "snow"),
|
||||||
|
(79, 67, "ice"),
|
||||||
|
(80, 66, "snow"),
|
||||||
|
(81, 70, "cactus"),
|
||||||
|
(82, 72, "clay"),
|
||||||
|
(83, 73, "reeds"),
|
||||||
|
(84, 74, "jukebox"),
|
||||||
|
(85, 4, "fence"),
|
||||||
|
(86, 102, "pumpkin"),
|
||||||
|
(87, 103, "hellrock"),
|
||||||
|
(88, 104, "hellsand"),
|
||||||
|
(89, 105, "lightgem"),
|
||||||
|
(90, 14, "portal"),
|
||||||
|
(91, 102, "pumpkin"),
|
||||||
|
]
|
||||||
|
|
||||||
|
lookup = {
|
||||||
|
k: v for k, v, _ in mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
with open("block_id_to_texture_id.data", "wb") as f:
|
||||||
|
for i in range(256):
|
||||||
|
value = lookup.get(i, unk)
|
||||||
|
f.write(struct.pack("<i", value))
|
||||||
|
print(str(value)+',')
|
||||||
134
minecraft/gen/cube.py
Normal file
134
minecraft/gen/cube.py
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
positions = [
|
||||||
|
(1.0, 1.0, -1.0),
|
||||||
|
(1.0, -1.0, -1.0),
|
||||||
|
(1.0, 1.0, 1.0),
|
||||||
|
(1.0, -1.0, 1.0),
|
||||||
|
(-1.0, 1.0, -1.0),
|
||||||
|
(-1.0, -1.0, -1.0),
|
||||||
|
(-1.0, 1.0, 1.0),
|
||||||
|
(-1.0, -1.0, 1.0)
|
||||||
|
]
|
||||||
|
|
||||||
|
normals = [
|
||||||
|
(0.0, 1.0, 0.0),
|
||||||
|
(0.0, 0.0, 1.0),
|
||||||
|
(-1.0, 0.0, 0.0),
|
||||||
|
(0.0, -1.0, 0.0),
|
||||||
|
(1.0, 0.0, 0.0),
|
||||||
|
(0.0, 0.0, -1.0),
|
||||||
|
]
|
||||||
|
|
||||||
|
textures = [
|
||||||
|
(1.0, 0.0),
|
||||||
|
(0.0, 1.0),
|
||||||
|
(0.0, 0.0),
|
||||||
|
(1.0, 1.0),
|
||||||
|
(0.0, 0.0),
|
||||||
|
(1.0, 0.0),
|
||||||
|
]
|
||||||
|
|
||||||
|
indices = [
|
||||||
|
[
|
||||||
|
[4, 0, 0],
|
||||||
|
[2, 1, 0],
|
||||||
|
[0, 2, 0],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2, 3, 1],
|
||||||
|
[7, 4, 1],
|
||||||
|
[3, 5, 1],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[6, 3, 2],
|
||||||
|
[5, 4, 2],
|
||||||
|
[7, 5, 2],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[1, 0, 3],
|
||||||
|
[7, 1, 3],
|
||||||
|
[5, 2, 3],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[0, 3, 4],
|
||||||
|
[3, 4, 4],
|
||||||
|
[1, 5, 4],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[4, 3, 5],
|
||||||
|
[1, 4, 5],
|
||||||
|
[5, 5, 5],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[4, 0, 0],
|
||||||
|
[6, 3, 0],
|
||||||
|
[2, 1, 0],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[2, 3, 1],
|
||||||
|
[6, 1, 1],
|
||||||
|
[7, 4, 1],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[6, 3, 2],
|
||||||
|
[4, 1, 2],
|
||||||
|
[5, 4, 2],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[1, 0, 3],
|
||||||
|
[3, 3, 3],
|
||||||
|
[7, 1, 3],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[0, 3, 4],
|
||||||
|
[2, 1, 4],
|
||||||
|
[3, 4, 4],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[4, 3, 5],
|
||||||
|
[0, 1, 5],
|
||||||
|
[1, 4, 5],
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
vertex_buffer = []
|
||||||
|
index_buffer = []
|
||||||
|
index_lookup = {}
|
||||||
|
|
||||||
|
for triangle in indices:
|
||||||
|
for p_ix, t_ix, n_ix in triangle:
|
||||||
|
key = (p_ix, n_ix, t_ix)
|
||||||
|
if key not in index_lookup:
|
||||||
|
position = positions[p_ix]
|
||||||
|
normal = normals[n_ix]
|
||||||
|
texture = textures[t_ix]
|
||||||
|
index = len(vertex_buffer)
|
||||||
|
index_lookup[key] = index
|
||||||
|
vertex_buffer.append((tuple(position),
|
||||||
|
tuple(normal),
|
||||||
|
tuple(texture)))
|
||||||
|
|
||||||
|
index_buffer.append(index_lookup[key])
|
||||||
|
|
||||||
|
def gen():
|
||||||
|
for position, normal, texture in vertex_buffer:
|
||||||
|
p = ", ".join(map(str, map(float, position)))
|
||||||
|
n = ", ".join(map(str, map(float, normal)))
|
||||||
|
t = ", ".join(map(str, map(float, texture)))
|
||||||
|
print(f"vertex_t(vec3({p}), vec3({n}), vec2({t})),")
|
||||||
|
|
||||||
|
for i in range(len(index_buffer) // 3):
|
||||||
|
tri = ", ".join(str(index_buffer[i * 3 + n]) for n in range(3))
|
||||||
|
print(f"{tri},")
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
by_normal = defaultdict(list)
|
||||||
|
for i in range(len(index_buffer) // 3):
|
||||||
|
tri = [index_buffer[i * 3 + n] for n in range(3)]
|
||||||
|
s = set(vertex_buffer[j][1] for j in tri)
|
||||||
|
assert len(s) == 1
|
||||||
|
normal, = iter(s)
|
||||||
|
by_normal[normal].append(tri)
|
||||||
|
|
||||||
|
from pprint import pprint
|
||||||
|
pprint(dict(by_normal))
|
||||||
|
pprint(vertex_buffer)
|
||||||
401
minecraft/gen/mc.py
Normal file
401
minecraft/gen/mc.py
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
# https://minecraft.fandom.com/wiki/Region_file_format
|
||||||
|
# https://minecraft.wiki/w/NBT_format#Binary_format
|
||||||
|
# https://minecraft.wiki/w/Chunk_format/McRegion
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
from pprint import pprint
|
||||||
|
import zlib
|
||||||
|
import enum
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
def _parse_locations(mem, offset):
|
||||||
|
for i in range(1024):
|
||||||
|
ix = offset + i * 4
|
||||||
|
chunk_location, = struct.unpack(">I", mem[ix:ix+4])
|
||||||
|
chunk_offset = (chunk_location >> 8) & 0xffffff
|
||||||
|
chunk_sector_count = chunk_location & 0xff
|
||||||
|
yield chunk_offset, chunk_sector_count
|
||||||
|
|
||||||
|
def parse_locations(mem, offset):
|
||||||
|
locations = list(_parse_locations(mem, offset))
|
||||||
|
return offset + 1024 * 4, locations
|
||||||
|
|
||||||
|
def _parse_timestamps(mem, offset):
|
||||||
|
for i in range(1024):
|
||||||
|
ix = offset + i * 4
|
||||||
|
timestamp, = struct.unpack(">I", mem[ix:ix+4])
|
||||||
|
yield timestamp
|
||||||
|
|
||||||
|
def parse_timestamps(mem, offset):
|
||||||
|
timestamps = list(_parse_timestamps(mem, offset))
|
||||||
|
return offset + 1024 * 4, timestamps
|
||||||
|
|
||||||
|
def print_locations(locations):
|
||||||
|
for y in range(32):
|
||||||
|
for x in range(32):
|
||||||
|
offset, count = locations[y * 32 + x]
|
||||||
|
print(str(offset).rjust(4), end=' ')
|
||||||
|
print()
|
||||||
|
|
||||||
|
class CountZeroException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def parse_payload(mem, location):
|
||||||
|
offset, count = location
|
||||||
|
if count == 0:
|
||||||
|
raise CountZeroException()
|
||||||
|
ix = offset * 4096
|
||||||
|
payload = mem[ix:ix + count * 4096]
|
||||||
|
length, = struct.unpack(">I", payload[0:4])
|
||||||
|
assert length <= count * 4096, (length, count)
|
||||||
|
compression_type = payload[4]
|
||||||
|
data = payload[5:5 + (length - 1)]
|
||||||
|
assert compression_type == 2, compression_type
|
||||||
|
uncompressed = zlib.decompress(data)
|
||||||
|
return memoryview(uncompressed)
|
||||||
|
|
||||||
|
class TAG:
|
||||||
|
Byte = 0x01
|
||||||
|
Short = 0x02
|
||||||
|
Int = 0x03
|
||||||
|
Long = 0x04
|
||||||
|
Float = 0x05
|
||||||
|
Double = 0x06
|
||||||
|
ByteArray = 0x07
|
||||||
|
String = 0x08
|
||||||
|
List = 0x09
|
||||||
|
Compound = 0x0a
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Byte:
|
||||||
|
name: str
|
||||||
|
value: int
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Short:
|
||||||
|
name: str
|
||||||
|
value: int
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Int:
|
||||||
|
name: str
|
||||||
|
value: int
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Long:
|
||||||
|
name: str
|
||||||
|
value: int
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Float:
|
||||||
|
name: str
|
||||||
|
value: float
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Double:
|
||||||
|
name: str
|
||||||
|
value: float
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ByteArray:
|
||||||
|
name: str
|
||||||
|
value: bytes
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class String:
|
||||||
|
name: str
|
||||||
|
value: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class List:
|
||||||
|
name: str
|
||||||
|
items: list
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Compound:
|
||||||
|
name: str
|
||||||
|
tags: list
|
||||||
|
|
||||||
|
def indent(level):
|
||||||
|
return " " * level
|
||||||
|
|
||||||
|
def parse_tag_inner(mem, offset, level, tag_type, name):
|
||||||
|
payload = mem[offset:]
|
||||||
|
if tag_type == TAG.Byte:
|
||||||
|
value, = struct.unpack(">b", payload[0:1])
|
||||||
|
return offset + 1, Byte(name, value)
|
||||||
|
if tag_type == TAG.Short:
|
||||||
|
value, = struct.unpack(">h", payload[0:2])
|
||||||
|
return offset + 2, Short(name, value)
|
||||||
|
elif tag_type == TAG.Int:
|
||||||
|
value, = struct.unpack(">i", payload[0:4])
|
||||||
|
return offset + 4, Int(name, value)
|
||||||
|
elif tag_type == TAG.Long:
|
||||||
|
value, = struct.unpack(">q", payload[0:8])
|
||||||
|
return offset + 8, Long(name, value)
|
||||||
|
elif tag_type == TAG.Float:
|
||||||
|
value, = struct.unpack(">f", payload[0:4])
|
||||||
|
return offset + 4, Float(name, value)
|
||||||
|
elif tag_type == TAG.Double:
|
||||||
|
value, = struct.unpack(">d", payload[0:8])
|
||||||
|
return offset + 8, Double(name, value)
|
||||||
|
elif tag_type == TAG.ByteArray:
|
||||||
|
size, = struct.unpack(">i", payload[0:4])
|
||||||
|
value = bytes(payload[4:4+size])
|
||||||
|
return offset + 4 + size, ByteArray(name, value)
|
||||||
|
elif tag_type == TAG.String:
|
||||||
|
size, = struct.unpack(">H", payload[0:2])
|
||||||
|
value = bytes(payload[2:2+size]).decode('utf-8')
|
||||||
|
return offset + 2 + size, String(name, value)
|
||||||
|
elif tag_type == TAG.List:
|
||||||
|
list_content_tag_id, size = struct.unpack(">BI", payload[0:5])
|
||||||
|
items = []
|
||||||
|
offset = offset + 5
|
||||||
|
for i in range(size):
|
||||||
|
payload = mem[offset:]
|
||||||
|
offset, item = parse_tag_inner(mem, offset, level, list_content_tag_id, None)
|
||||||
|
items.append(item)
|
||||||
|
return offset, List(name, items)
|
||||||
|
elif tag_type == TAG.Compound:
|
||||||
|
tags = []
|
||||||
|
while payload[0] != 0:
|
||||||
|
offset, tag = parse_tag(mem, offset, level+1)
|
||||||
|
payload = mem[offset:]
|
||||||
|
tags.append(tag)
|
||||||
|
return offset + 1, Compound(name, tags)
|
||||||
|
else:
|
||||||
|
assert False, tag_type
|
||||||
|
|
||||||
|
def parse_tag(mem, offset, level):
|
||||||
|
data = mem[offset:]
|
||||||
|
tag_type = data[0]
|
||||||
|
name_length, = struct.unpack(">H", data[1:3])
|
||||||
|
name = bytes(data[3:3+name_length])
|
||||||
|
#print(indent(level), tag_type, name_length, name)
|
||||||
|
offset = offset + 3 + name_length
|
||||||
|
return parse_tag_inner(mem, offset, level, tag_type, name)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Level:
|
||||||
|
blocks: bytes
|
||||||
|
data: bytes
|
||||||
|
sky_light: bytes
|
||||||
|
block_light: bytes
|
||||||
|
height_map: bytes
|
||||||
|
x_pos: int
|
||||||
|
z_pos: int
|
||||||
|
|
||||||
|
def level_from_tag(tag):
|
||||||
|
assert type(tag) == Compound
|
||||||
|
assert tag.name == b''
|
||||||
|
assert len(tag.tags) == 1
|
||||||
|
level, = tag.tags
|
||||||
|
assert type(level) == Compound
|
||||||
|
assert level.name == b'Level'
|
||||||
|
|
||||||
|
name_mapping = {
|
||||||
|
b'Blocks': 'blocks',
|
||||||
|
b'Data': 'data',
|
||||||
|
b'SkyLight': 'sky_light',
|
||||||
|
b'BlockLight': 'block_light',
|
||||||
|
b'HeightMap': 'height_map',
|
||||||
|
b'xPos': 'x_pos',
|
||||||
|
b'zPos': 'z_pos',
|
||||||
|
}
|
||||||
|
|
||||||
|
args = {}
|
||||||
|
|
||||||
|
for tag in level.tags:
|
||||||
|
if tag.name in name_mapping:
|
||||||
|
arg_name = name_mapping[tag.name]
|
||||||
|
args[arg_name] = tag.value
|
||||||
|
|
||||||
|
return Level(**args)
|
||||||
|
|
||||||
|
def parse_location(mem, location):
|
||||||
|
uncompressed = parse_payload(mem, location)
|
||||||
|
offset, tag = parse_tag(uncompressed, 0, 0)
|
||||||
|
assert offset == len(uncompressed), (offset, len(uncompressed))
|
||||||
|
level = level_from_tag(tag)
|
||||||
|
return level
|
||||||
|
|
||||||
|
def xyz_from_block_index(block_index):
|
||||||
|
assert block_index >= 0 and block_index < (128 * 16 * 16)
|
||||||
|
x = int(block_index / (128 * 16))
|
||||||
|
y = int(block_index % 128)
|
||||||
|
z = int(int(block_index / 128) % 16)
|
||||||
|
return x, y, z
|
||||||
|
|
||||||
|
def block_index_from_xyz(x, y, z):
|
||||||
|
assert x >= 0 and x < 16
|
||||||
|
assert y >= 0 and y < 128
|
||||||
|
assert z >= 0 and z < 16
|
||||||
|
return int(y + z * 128 + x * 128 * 16)
|
||||||
|
|
||||||
|
def wrap_n(nc, chunk_c):
|
||||||
|
if nc < 0:
|
||||||
|
nc = 15
|
||||||
|
chunk_c = chunk_c - 1
|
||||||
|
if nc > 15:
|
||||||
|
nc = 0
|
||||||
|
chunk_c = chunk_c + 1
|
||||||
|
return nc, chunk_c
|
||||||
|
|
||||||
|
def vec3_add(v1, v2):
|
||||||
|
return (
|
||||||
|
v1[0] + v2[0],
|
||||||
|
v1[1] + v2[1],
|
||||||
|
v1[2] + v2[2],
|
||||||
|
)
|
||||||
|
|
||||||
|
def vec3_mul(v, s):
|
||||||
|
return (
|
||||||
|
v[0] * s,
|
||||||
|
v[1] * s,
|
||||||
|
v[2] * s,
|
||||||
|
)
|
||||||
|
|
||||||
|
vertex_table = [
|
||||||
|
((-1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (1.0, 0.0)),
|
||||||
|
((1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (0.0, 1.0)),
|
||||||
|
((1.0, 1.0, -1.0), (0.0, 1.0, 0.0), (0.0, 0.0)),
|
||||||
|
((1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 1.0)),
|
||||||
|
|
||||||
|
((-1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 0.0)),
|
||||||
|
((1.0, -1.0, 1.0), (0.0, 0.0, 1.0), (1.0, 0.0)),
|
||||||
|
((-1.0, 1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 1.0)),
|
||||||
|
((-1.0, -1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 0.0)),
|
||||||
|
|
||||||
|
((-1.0, -1.0, 1.0), (-1.0, 0.0, 0.0), (1.0, 0.0)),
|
||||||
|
((1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (1.0, 0.0)),
|
||||||
|
((-1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (0.0, 1.0)),
|
||||||
|
((-1.0, -1.0, -1.0), (0.0, -1.0, 0.0), (0.0, 0.0)),
|
||||||
|
|
||||||
|
((1.0, 1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 1.0)),
|
||||||
|
((1.0, -1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 0.0)),
|
||||||
|
((1.0, -1.0, -1.0), (1.0, 0.0, 0.0), (1.0, 0.0)),
|
||||||
|
((-1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 1.0)),
|
||||||
|
((1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 0.0)),
|
||||||
|
((-1.0, -1.0, -1.0), (0.0, 0.0, -1.0), (1.0, 0.0)),
|
||||||
|
((-1.0, 1.0, 1.0), (0.0, 1.0, 0.0), (1.0, 1.0)),
|
||||||
|
((-1.0, 1.0, 1.0), (0.0, 0.0, 1.0), (0.0, 1.0)),
|
||||||
|
((-1.0, 1.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 1.0)),
|
||||||
|
((1.0, -1.0, 1.0), (0.0, -1.0, 0.0), (1.0, 1.0)),
|
||||||
|
((1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0)),
|
||||||
|
((1.0, 1.0, -1.0), (0.0, 0.0, -1.0), (0.0, 1.0))
|
||||||
|
]
|
||||||
|
|
||||||
|
faces_by_normal = {
|
||||||
|
(-1.0, 0.0, 0.0): [6, 7, 8, 6, 20, 7],
|
||||||
|
(0.0, -1.0, 0.0): [9, 10, 11, 9, 21, 10],
|
||||||
|
(0.0, 0.0, -1.0): [15, 16, 17, 15, 23, 16],
|
||||||
|
(0.0, 0.0, 1.0): [3, 4, 5, 3, 19, 4],
|
||||||
|
(0.0, 1.0, 0.0): [0, 1, 2, 0, 18, 1],
|
||||||
|
(1.0, 0.0, 0.0): [12, 13, 14, 12, 22, 13]
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_buffer = {}
|
||||||
|
|
||||||
|
def add_vertex(vertex):
|
||||||
|
if vertex in vertex_buffer:
|
||||||
|
return vertex_buffer[vertex]
|
||||||
|
else:
|
||||||
|
index = len(vertex_buffer)
|
||||||
|
vertex_buffer[vertex] = index
|
||||||
|
return index
|
||||||
|
|
||||||
|
def emit_face(center_position, block_id, triangles):
|
||||||
|
for index in triangles:
|
||||||
|
position, normal, texture = vertex_table[index]
|
||||||
|
position = vec3_add(vec3_mul(position, 0.5), center_position)
|
||||||
|
vertex = (position, normal, texture, block_id)
|
||||||
|
new_index = add_vertex(vertex)
|
||||||
|
yield new_index
|
||||||
|
|
||||||
|
def block_neighbors(level_table, chunk_x, chunk_z, block_index):
|
||||||
|
block_id = level_table[(chunk_x, chunk_z)].blocks[block_index]
|
||||||
|
if block_id == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
def neighbor_exists(nx, ny, nz):
|
||||||
|
if ny > 127 or ny < 0:
|
||||||
|
return False
|
||||||
|
nx, n_chunk_x = wrap_n(nx, chunk_x)
|
||||||
|
nz, n_chunk_z = wrap_n(nz, chunk_z)
|
||||||
|
if nx > 15 or nx < 0:
|
||||||
|
return True
|
||||||
|
if nz > 15 or nz < 0:
|
||||||
|
return True
|
||||||
|
n_block_index = block_index_from_xyz(nx, ny, nz)
|
||||||
|
key = (n_chunk_x, n_chunk_z)
|
||||||
|
if key not in level_table:
|
||||||
|
return True
|
||||||
|
n_block_id = level_table[key].blocks[n_block_index]
|
||||||
|
return n_block_id != 0
|
||||||
|
|
||||||
|
x, y, z = xyz_from_block_index(block_index)
|
||||||
|
|
||||||
|
center_position = vec3_add((x, y, z), (chunk_x * 16, 0, chunk_z * 16))
|
||||||
|
|
||||||
|
for normal, triangles in faces_by_normal.items():
|
||||||
|
neighbor = vec3_add(normal, (x, y, z))
|
||||||
|
if not neighbor_exists(*neighbor):
|
||||||
|
yield from emit_face(center_position, block_id, triangles)
|
||||||
|
|
||||||
|
#yield chunk_x, chunk_z, block_index, block_id
|
||||||
|
#break
|
||||||
|
|
||||||
|
def devoxelize_region(level_table):
|
||||||
|
for chunk_x, chunk_z in level_table.keys():
|
||||||
|
for block_index in range(128 * 16 * 16):
|
||||||
|
yield from block_neighbors(level_table, chunk_x, chunk_z, block_index)
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
counts = defaultdict(int)
|
||||||
|
|
||||||
|
def linearized_vertex_buffer():
|
||||||
|
for vertex, i in sorted(vertex_buffer.items(), key=lambda kv: kv[1]):
|
||||||
|
yield vertex
|
||||||
|
|
||||||
|
def main(mcr_path, data_path):
|
||||||
|
with open(mcr_path, "rb") as f:
|
||||||
|
buf = f.read()
|
||||||
|
mem = memoryview(buf)
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
offset, locations = parse_locations(mem, offset)
|
||||||
|
offset, timestamps = parse_timestamps(mem, offset)
|
||||||
|
assert offset == 0x2000
|
||||||
|
|
||||||
|
level_table = {}
|
||||||
|
for location in locations:
|
||||||
|
try:
|
||||||
|
level = parse_location(mem, location)
|
||||||
|
except CountZeroException:
|
||||||
|
continue
|
||||||
|
x, z = level.x_pos, level.z_pos
|
||||||
|
level_table[(x, z)] = level
|
||||||
|
#with open(f"blocks__{x:02x}_{z:02x}.data", "wb") as f:
|
||||||
|
# f.write(level.blocks)
|
||||||
|
|
||||||
|
with open(data_path + ".idx", "wb") as f:
|
||||||
|
for index in devoxelize_region(level_table):
|
||||||
|
f.write(struct.pack("<I", index))
|
||||||
|
|
||||||
|
with open(data_path + ".vtx", "wb") as f:
|
||||||
|
for vertex in linearized_vertex_buffer():
|
||||||
|
vertex = [*vertex[0], *vertex[1], *vertex[2], vertex[3]]#, vertex[3]]
|
||||||
|
f.write(struct.pack("<fffffffff", *vertex))
|
||||||
|
|
||||||
|
#for chunk_x, chunk_z, block_index, block_id in devoxelize_region(level_table):
|
||||||
|
# #print(chunk_x, chunk_z, block_id)
|
||||||
|
# counts[block_id] += 1
|
||||||
|
# f.write(struct.pack("<bbBb", chunk_x, chunk_z, block_id, 0))
|
||||||
|
# f.write(struct.pack("<i", block_index))
|
||||||
|
|
||||||
|
mcr_path = sys.argv[1]
|
||||||
|
data_path = sys.argv[2]
|
||||||
|
|
||||||
|
main(mcr_path, data_path)
|
||||||
BIN
minecraft/terrain.data
Normal file
BIN
minecraft/terrain.data
Normal file
Binary file not shown.
BIN
minecraft/terrain.png
Normal file
BIN
minecraft/terrain.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
295
shader/test.frag
Normal file
295
shader/test.frag
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
in vec3 PixelNormal;
|
||||||
|
in vec2 PixelTexture;
|
||||||
|
in float PixelBlock;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D TerrainSampler;
|
||||||
|
|
||||||
|
/*layout (std140) uniform TexturesLayout
|
||||||
|
{
|
||||||
|
uint Textures[256];
|
||||||
|
};*/
|
||||||
|
int Textures[256] = int[256](
|
||||||
|
185,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
16,
|
||||||
|
4,
|
||||||
|
15,
|
||||||
|
17,
|
||||||
|
205,
|
||||||
|
205,
|
||||||
|
237,
|
||||||
|
237,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
20,
|
||||||
|
52,
|
||||||
|
48,
|
||||||
|
49,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
0,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
64,
|
||||||
|
185,
|
||||||
|
13,
|
||||||
|
12,
|
||||||
|
29,
|
||||||
|
28,
|
||||||
|
39,
|
||||||
|
38,
|
||||||
|
5,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
35,
|
||||||
|
36,
|
||||||
|
37,
|
||||||
|
80,
|
||||||
|
31,
|
||||||
|
65,
|
||||||
|
4,
|
||||||
|
27,
|
||||||
|
84,
|
||||||
|
50,
|
||||||
|
40,
|
||||||
|
43,
|
||||||
|
88,
|
||||||
|
87,
|
||||||
|
44,
|
||||||
|
61,
|
||||||
|
185,
|
||||||
|
81,
|
||||||
|
83,
|
||||||
|
128,
|
||||||
|
16,
|
||||||
|
185,
|
||||||
|
96,
|
||||||
|
6,
|
||||||
|
82,
|
||||||
|
6,
|
||||||
|
51,
|
||||||
|
51,
|
||||||
|
115,
|
||||||
|
99,
|
||||||
|
185,
|
||||||
|
66,
|
||||||
|
67,
|
||||||
|
66,
|
||||||
|
70,
|
||||||
|
72,
|
||||||
|
73,
|
||||||
|
74,
|
||||||
|
4,
|
||||||
|
102,
|
||||||
|
103,
|
||||||
|
104,
|
||||||
|
105,
|
||||||
|
14,
|
||||||
|
102,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185,
|
||||||
|
185
|
||||||
|
);
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 light_direction = normalize(vec3(-1, -0.5, 0.5));
|
||||||
|
float diffuse_intensity = max(dot(normalize(PixelNormal), light_direction), 0.0);
|
||||||
|
|
||||||
|
int terrain_ix = int(Textures[int(PixelBlock)]);
|
||||||
|
int terrain_x = terrain_ix % 16;
|
||||||
|
int terrain_y = terrain_ix / 16;
|
||||||
|
ivec2 coord = ivec2(terrain_x, terrain_y) * 16;
|
||||||
|
coord += ivec2(PixelTexture.xy * 16.0);
|
||||||
|
|
||||||
|
vec4 texture_color = texelFetch(TerrainSampler, coord, 0);
|
||||||
|
if (texture_color.w != 1.0) {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int(PixelBlock) == 18) // leaves
|
||||||
|
texture_color.xyz *= vec3(0.125, 0.494, 0.027);
|
||||||
|
|
||||||
|
FragColor = vec4(texture_color.xyz * vec3(diffuse_intensity), 1.0);
|
||||||
|
}
|
||||||
23
shader/test.vert
Normal file
23
shader/test.vert
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#version 330 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 Position;
|
||||||
|
layout (location = 1) in vec3 Normal;
|
||||||
|
layout (location = 2) in vec3 Texture;
|
||||||
|
|
||||||
|
out vec3 PixelNormal;
|
||||||
|
out vec2 PixelTexture;
|
||||||
|
out float PixelBlock;
|
||||||
|
|
||||||
|
uniform mat4 Transform;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//gl_Position = vec4(position, 1.0);
|
||||||
|
//ourColor = color;
|
||||||
|
|
||||||
|
PixelNormal = Normal.xzy;
|
||||||
|
PixelTexture = Texture.xy;
|
||||||
|
PixelBlock = Texture.z;
|
||||||
|
|
||||||
|
gl_Position = Transform * vec4(Position.xzy, 1.0);
|
||||||
|
}
|
||||||
53
src/main.c
Normal file
53
src/main.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "glad/gl.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
extern void load();
|
||||||
|
extern void draw();
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
||||||
|
|
||||||
|
GLFWwindow* window = glfwCreateWindow(1024, 1024, "LearnOpenGL", NULL, NULL);
|
||||||
|
if (window == NULL) {
|
||||||
|
const char* description;
|
||||||
|
glfwGetError(&description);
|
||||||
|
printf("Failed to create GLFW window: %s\n", description);
|
||||||
|
glfwTerminate();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
gladLoadGL(glfwGetProcAddress);
|
||||||
|
|
||||||
|
glViewport(0, 0, 1024, 1024);
|
||||||
|
|
||||||
|
load();
|
||||||
|
|
||||||
|
while(!glfwWindowShouldClose(window)) {
|
||||||
|
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||||
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
|
||||||
|
draw();
|
||||||
|
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
112
src/opengl.c
Normal file
112
src/opengl.c
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "glad/gl.h"
|
||||||
|
#include "opengl.h"
|
||||||
|
|
||||||
|
void * read_file(const char * filename, int * out_size)
|
||||||
|
{
|
||||||
|
FILE * f = fopen(filename, "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
fprintf(stderr, "fopen(%s): %s\n", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fseek_end_ret = fseek(f, 0, SEEK_END);
|
||||||
|
if (fseek_end_ret < 0) {
|
||||||
|
fprintf(stderr, "fseek(%s, SEEK_END): %s\n", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long size = ftell(f);
|
||||||
|
if (size < 0) {
|
||||||
|
fprintf(stderr, "ftell(%s): %s\n", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fseek_set_ret = fseek(f, 0, SEEK_SET);
|
||||||
|
if (fseek_set_ret < 0) {
|
||||||
|
fprintf(stderr, "lseek(%s, SEEK_SET): %s\n", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
rewind(f);
|
||||||
|
|
||||||
|
void * buf = malloc(size);
|
||||||
|
|
||||||
|
size_t read_size = fread(buf, 1, size, f);
|
||||||
|
if (read_size != size) {
|
||||||
|
fprintf(stderr, "fread(%s): %s\n", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_size = size;
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int compile(const char * vertex_source,
|
||||||
|
int vertex_source_size,
|
||||||
|
const char * fragment_source,
|
||||||
|
int fragment_source_size)
|
||||||
|
{
|
||||||
|
int compile_status;
|
||||||
|
char info_log[512];
|
||||||
|
|
||||||
|
// vertex shader
|
||||||
|
unsigned int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
glShaderSource(vertex_shader, 1, &vertex_source, &vertex_source_size);
|
||||||
|
glCompileShader(vertex_shader);
|
||||||
|
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compile_status);
|
||||||
|
if (!compile_status) {
|
||||||
|
glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
|
||||||
|
fprintf(stderr, "vertex shader compile: %s\n", info_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fragment shader
|
||||||
|
unsigned int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(fragment_shader, 1, &fragment_source, &fragment_source_size);
|
||||||
|
glCompileShader(fragment_shader);
|
||||||
|
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &compile_status);
|
||||||
|
if (!compile_status) {
|
||||||
|
glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
|
||||||
|
fprintf(stderr, "fragment shader compile: %s\n", info_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
// link shaders
|
||||||
|
unsigned int shader_program = glCreateProgram();
|
||||||
|
glAttachShader(shader_program, vertex_shader);
|
||||||
|
glAttachShader(shader_program, fragment_shader);
|
||||||
|
glLinkProgram(shader_program);
|
||||||
|
glGetProgramiv(shader_program, GL_LINK_STATUS, &compile_status);
|
||||||
|
if (!compile_status) {
|
||||||
|
glGetProgramInfoLog(shader_program, 512, NULL, info_log);
|
||||||
|
fprintf(stderr, "shader link: %s\n", info_log);
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteShader(vertex_shader);
|
||||||
|
glDeleteShader(fragment_shader);
|
||||||
|
|
||||||
|
return shader_program;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int compile_from_files(const char * vertex_path,
|
||||||
|
const char * fragment_path)
|
||||||
|
{
|
||||||
|
int vertex_source_size;
|
||||||
|
char * vertex_source = read_file(vertex_path, &vertex_source_size);
|
||||||
|
assert(vertex_source != NULL);
|
||||||
|
int fragment_source_size;
|
||||||
|
char * fragment_source = read_file(fragment_path, &fragment_source_size);
|
||||||
|
assert(fragment_source != NULL);
|
||||||
|
|
||||||
|
unsigned int program = compile(vertex_source, vertex_source_size,
|
||||||
|
fragment_source, fragment_source_size);
|
||||||
|
|
||||||
|
free(vertex_source);
|
||||||
|
free(fragment_source);
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
242
src/test.cpp
Normal file
242
src/test.cpp
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "glad/gl.h"
|
||||||
|
#include "opengl.h"
|
||||||
|
#include "directxmath/directxmath.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
struct location {
|
||||||
|
struct {
|
||||||
|
unsigned int position;
|
||||||
|
unsigned int normal;
|
||||||
|
unsigned int texture;
|
||||||
|
} attrib;
|
||||||
|
struct {
|
||||||
|
unsigned int transform;
|
||||||
|
unsigned int terrain_sampler;
|
||||||
|
} uniform;
|
||||||
|
};
|
||||||
|
|
||||||
|
// state
|
||||||
|
static unsigned int test_program;
|
||||||
|
static struct location location;
|
||||||
|
|
||||||
|
void load_program()
|
||||||
|
{
|
||||||
|
unsigned int program = compile_from_files("shader/test.vert",
|
||||||
|
"shader/test.frag");
|
||||||
|
|
||||||
|
location.attrib.position = glGetAttribLocation(program, "Position");
|
||||||
|
location.attrib.normal = glGetAttribLocation(program, "Normal");
|
||||||
|
location.attrib.texture = glGetAttribLocation(program, "Texture");
|
||||||
|
printf("attributes:\n position %u\n normal %u\n texture %u\n",
|
||||||
|
location.attrib.position,
|
||||||
|
location.attrib.normal,
|
||||||
|
location.attrib.texture);
|
||||||
|
|
||||||
|
location.uniform.transform = glGetUniformLocation(program, "Transform");
|
||||||
|
location.uniform.terrain_sampler = glGetUniformLocation(program, "TerrainSampler");
|
||||||
|
printf("uniforms:\n transform %u\n terrain_sampler %u\n",
|
||||||
|
location.uniform.transform,
|
||||||
|
location.uniform.terrain_sampler);
|
||||||
|
|
||||||
|
test_program = program;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int vertex_array_objects[4];
|
||||||
|
static unsigned int vertex_buffers[4];
|
||||||
|
static unsigned int index_buffers[4];
|
||||||
|
static unsigned int index_count[4];
|
||||||
|
|
||||||
|
const char * vertex_paths[] = {
|
||||||
|
"minecraft/region.0.0.vtx",
|
||||||
|
"minecraft/region.0.-1.vtx",
|
||||||
|
"minecraft/region.-1.0.vtx",
|
||||||
|
"minecraft/region.-1.-1.vtx",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * index_paths[] = {
|
||||||
|
"minecraft/region.0.0.idx",
|
||||||
|
"minecraft/region.0.-1.idx",
|
||||||
|
"minecraft/region.-1.0.idx",
|
||||||
|
"minecraft/region.-1.-1.idx",
|
||||||
|
};
|
||||||
|
|
||||||
|
void load_vertex_buffer(int i)
|
||||||
|
{
|
||||||
|
int vertex_buffer_data_size;
|
||||||
|
void * vertex_buffer_data = read_file(vertex_paths[i], &vertex_buffer_data_size);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers[i]);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_data_size, vertex_buffer_data, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
free(vertex_buffer_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_element_buffer(int i)
|
||||||
|
{
|
||||||
|
int index_buffer_data_size;
|
||||||
|
void * index_buffer_data = read_file(index_paths[i], &index_buffer_data_size);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffers[i]);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_data_size, index_buffer_data, GL_STATIC_DRAW);
|
||||||
|
index_count[i] = index_buffer_data_size / 4;
|
||||||
|
|
||||||
|
free(index_buffer_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_vertex_attributes()
|
||||||
|
{
|
||||||
|
glVertexAttribPointer(location.attrib.position,
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof (float)) * 9,
|
||||||
|
(void*)(0 * 4)
|
||||||
|
);
|
||||||
|
glVertexAttribPointer(location.attrib.normal,
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof (float)) * 9,
|
||||||
|
(void*)(3 * 4)
|
||||||
|
);
|
||||||
|
glVertexAttribPointer(location.attrib.texture,
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof (float)) * 9,
|
||||||
|
(void*)(6 * 4)
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(location.attrib.position);
|
||||||
|
glEnableVertexAttribArray(location.attrib.normal);
|
||||||
|
glEnableVertexAttribArray(location.attrib.texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_buffers()
|
||||||
|
{
|
||||||
|
glGenVertexArrays(4, vertex_array_objects);
|
||||||
|
glGenBuffers(4, index_buffers);
|
||||||
|
glGenBuffers(4, vertex_buffers);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
glBindVertexArray(vertex_array_objects[i]);
|
||||||
|
|
||||||
|
load_element_buffer(i);
|
||||||
|
load_vertex_buffer(i);
|
||||||
|
load_vertex_attributes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int texture;
|
||||||
|
|
||||||
|
void load_textures()
|
||||||
|
{
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
int texture_data_size;
|
||||||
|
void * texture_data = read_file("minecraft/terrain.data", &texture_data_size);
|
||||||
|
assert(texture_data != NULL);
|
||||||
|
|
||||||
|
int width = 256;
|
||||||
|
int height = 256;
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
|
||||||
|
|
||||||
|
free(texture_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int textures_ubo;
|
||||||
|
|
||||||
|
void load_texture_shader_storage()
|
||||||
|
{
|
||||||
|
unsigned int buffer;
|
||||||
|
glGenBuffers(1, &buffer);
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
|
||||||
|
|
||||||
|
int textures_data_size;
|
||||||
|
void * textures_data = read_file("minecraft/block_id_to_texture_id.data", &textures_data_size);
|
||||||
|
assert(textures_data != NULL);
|
||||||
|
|
||||||
|
printf("%d\n", textures_data_size);
|
||||||
|
|
||||||
|
glBufferData(GL_UNIFORM_BUFFER, textures_data_size, textures_data, GL_STATIC_DRAW);
|
||||||
|
free(textures_data);
|
||||||
|
|
||||||
|
textures_ubo = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void * SDL_GL_GetProcAddress(const char *proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void load()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "getproc %p\n", SDL_GL_GetProcAddress);
|
||||||
|
gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress);
|
||||||
|
|
||||||
|
load_program();
|
||||||
|
load_buffers();
|
||||||
|
load_textures();
|
||||||
|
//load_texture_shader_storage();
|
||||||
|
|
||||||
|
//unsigned int textures_layout = glGetUniformBlockIndex(test_program, "TexturesLayout");
|
||||||
|
//glUniformBlockBinding(test_program, textures_layout, 0);
|
||||||
|
//printf("textures_layout %d\n", textures_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float vx = 0.0;
|
||||||
|
static float vy = 0.0;
|
||||||
|
static float vz = 0.0;
|
||||||
|
|
||||||
|
void update(float lx, float ly, float ry)
|
||||||
|
{
|
||||||
|
vx += 2.5 * lx;
|
||||||
|
vy += -2.5 * ry;
|
||||||
|
vz += -2.5 * ly;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw()
|
||||||
|
{
|
||||||
|
XMVECTOR eye = XMVectorSet(vx + -50.0f, vz + -50.0f, vy + 150.0f, 0.0f);
|
||||||
|
XMVECTOR at = XMVectorSet(vx + 50.0f, vz + 50.0f, vy + 50.0f, 0.0f);
|
||||||
|
XMVECTOR up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
|
XMMATRIX view = XMMatrixLookAtRH(eye, at, up);
|
||||||
|
|
||||||
|
float fov_angle_y = XMConvertToRadians(45 * 0.75);
|
||||||
|
float aspect_ratio = 1.0;
|
||||||
|
float near_z = 1.0;
|
||||||
|
float far_z = 0.1;
|
||||||
|
XMMATRIX projection = XMMatrixPerspectiveFovRH(fov_angle_y, aspect_ratio, near_z, far_z);
|
||||||
|
XMMATRIX transform = view * projection;
|
||||||
|
|
||||||
|
glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
|
||||||
|
glClearDepth(-1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glUseProgram(test_program);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_GREATER);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
|
glUniformMatrix4fv(location.uniform.transform, 1, false, (float *)&transform);
|
||||||
|
glUniform1i(location.uniform.terrain_sampler, 0);
|
||||||
|
|
||||||
|
//glBindBuffer(GL_UNIFORM_BUFFER, textures_ubo);
|
||||||
|
//glBindBufferBase(GL_UNIFORM_BUFFER, 0, textures_ubo);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
glBindVertexArray(vertex_array_objects[i]);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, index_count[i], GL_UNSIGNED_INT, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user