mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-10 06:41:37 +00:00
Add dlight codebase to zdray
This commit is contained in:
parent
b4f22e7959
commit
405bb743a0
35 changed files with 13189 additions and 1 deletions
|
@ -144,6 +144,26 @@ set( SOURCES
|
|||
src/nodebuilder/nodebuild_gl.cpp
|
||||
src/nodebuilder/nodebuild_utility.cpp
|
||||
src/nodebuilder/nodebuild_classify_nosse2.cpp
|
||||
src/lightmap/lightmap.cpp
|
||||
src/lightmap/lightsurface.cpp
|
||||
src/lightmap/mapdata.cpp
|
||||
src/lightmap/surfaces.cpp
|
||||
src/lightmap/trace.cpp
|
||||
src/lightmap/wad.cpp
|
||||
src/lightmap/worker.cpp
|
||||
src/lightmap/kexlib/binfile.cpp
|
||||
src/lightmap/kexlib/kstring.cpp
|
||||
src/lightmap/kexlib/memheap.cpp
|
||||
src/lightmap/kexlib/parser.cpp
|
||||
src/lightmap/kexlib/math/angle.cpp
|
||||
src/lightmap/kexlib/math/bounds.cpp
|
||||
src/lightmap/kexlib/math/mathlib.cpp
|
||||
src/lightmap/kexlib/math/matrix.cpp
|
||||
src/lightmap/kexlib/math/plane.cpp
|
||||
src/lightmap/kexlib/math/pluecker.cpp
|
||||
src/lightmap/kexlib/math/quaternion.cpp
|
||||
src/lightmap/kexlib/math/random.cpp
|
||||
src/lightmap/kexlib/math/vector.cpp
|
||||
)
|
||||
if( WIN32 )
|
||||
set( SOURCES "${SOURCES}" src/viewer/view.cpp )
|
||||
|
@ -164,7 +184,22 @@ set( HEADERS
|
|||
src/framework/tarray.h
|
||||
src/framework/templates.h
|
||||
src/framework/zdray.h
|
||||
src/framework/xs_Float.h )
|
||||
src/framework/xs_Float.h
|
||||
src/lightmap/common.h
|
||||
src/lightmap/lightmap.h
|
||||
src/lightmap/lightsurface.h
|
||||
src/lightmap/mapdata.h
|
||||
src/lightmap/surfaces.h
|
||||
src/lightmap/trace.h
|
||||
src/lightmap/wad.h
|
||||
src/lightmap/worker.h
|
||||
src/lightmap/kexlib/array.h
|
||||
src/lightmap/kexlib/binfile.h
|
||||
src/lightmap/kexlib/kstring.h
|
||||
src/lightmap/kexlib/memheap.h
|
||||
src/lightmap/kexlib/parser.h
|
||||
src/lightmap/kexlib/math/mathlib.h
|
||||
)
|
||||
|
||||
if( SSE_MATTERS )
|
||||
if( FULL_SSE2 )
|
||||
|
@ -233,3 +268,6 @@ source_group("Sources\\Platform" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR
|
|||
source_group("Sources\\Platform\\Windows" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/.+")
|
||||
source_group("Sources\\Viewer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/viewer/.+")
|
||||
source_group("Sources\\Wad" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/wad/.+")
|
||||
source_group("Sources\\Lightmap" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/lightmap/.+")
|
||||
source_group("Sources\\Lightmap\\kexlib" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/lightmap/kexlib/.+")
|
||||
source_group("Sources\\Lightmap\\kexlib\\math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/lightmap/kexlib/math/.+")
|
||||
|
|
166
src/lightmap/common.h
Normal file
166
src/lightmap/common.h
Normal file
|
@ -0,0 +1,166 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4267) // warning C4267: 'argument': conversion from 'size_t' to 'int', possible loss of data
|
||||
#pragma warning(disable: 4244) // warning C4244: '=': conversion from '__int64' to 'int', possible loss of data
|
||||
#endif
|
||||
|
||||
// narrow down the windows preprocessor bullshit down to just one macro define
|
||||
#if defined(__WIN32__) || defined(__WIN32) || defined(_WIN32_) || defined(_WIN32) || defined(WIN32)
|
||||
#define KEX_WIN32
|
||||
#else
|
||||
#if defined(__APPLE__)
|
||||
// lets us know what version of Mac OS X we're compiling on
|
||||
#include "AvailabilityMacros.h"
|
||||
#include "TargetConditionals.h"
|
||||
#if TARGET_OS_IPHONE
|
||||
// if compiling for iPhone
|
||||
#define KEX_IPHONE
|
||||
#else
|
||||
// if not compiling for iPhone
|
||||
#define KEX_MACOSX
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
|
||||
# error KexLIB for Mac OS X only supports deploying on 10.5 and above.
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1050
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
|
||||
# error KexLIB for Mac OS X must be built with a 10.6 SDK or above.
|
||||
#endif // MAC_OS_X_VERSION_MAX_ALLOWED < 1060
|
||||
#endif // TARGET_OS_IPHONE
|
||||
#endif // defined(__APPLE__)
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef KEX_WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#define MAX_FILEPATH 256
|
||||
#define MAX_HASH 2048
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned int dtexture;
|
||||
typedef unsigned int rcolor;
|
||||
typedef char filepath_t[MAX_FILEPATH];
|
||||
|
||||
typedef union
|
||||
{
|
||||
int i;
|
||||
float f;
|
||||
} fint_t;
|
||||
|
||||
#define ASCII_SLASH 47
|
||||
#define ASCII_BACKSLASH 92
|
||||
|
||||
#ifdef KEX_WIN32
|
||||
#define DIR_SEPARATOR '\\'
|
||||
#define PATH_SEPARATOR ';'
|
||||
#else
|
||||
#define DIR_SEPARATOR '/'
|
||||
#define PATH_SEPARATOR ':'
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#define D_MININT INT_MIN
|
||||
#define D_MAXINT INT_MAX
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
#ifndef BETWEEN
|
||||
#define BETWEEN(l,u,x) ((l)>(x)?(l):(x)>(u)?(u):(x))
|
||||
#endif
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(num) (1<<(num))
|
||||
#endif
|
||||
|
||||
#if defined(KEX_WIN32) && !defined(__GNUC__)
|
||||
#define KDECL __cdecl
|
||||
#else
|
||||
#define KDECL
|
||||
#endif
|
||||
|
||||
#ifdef ALIGNED
|
||||
#undef ALIGNED
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGNED(x) __declspec(align(x))
|
||||
#define PACKED
|
||||
#elif defined(__GNUC__)
|
||||
#define ALIGNED(x) __attribute__ ((aligned(x)))
|
||||
#define PACKED __attribute__((packed))
|
||||
#else
|
||||
#define ALIGNED(x)
|
||||
#define PACKED
|
||||
#endif
|
||||
|
||||
// function inlining is available on most platforms, however,
|
||||
// the GNU C __inline__ is too common and conflicts with a
|
||||
// definition in other dependencies, so it needs to be factored
|
||||
// out into a custom macro definition
|
||||
|
||||
#if defined(__GNUC__) || defined(__APPLE__)
|
||||
#define d_inline __inline__
|
||||
#elif defined(_MSC_VER) || defined(KEX_WIN32)
|
||||
#define d_inline __forceinline
|
||||
#else
|
||||
#define d_inline
|
||||
#endif
|
||||
|
||||
#include "kexlib/memHeap.h"
|
||||
#include "kexlib/kstring.h"
|
||||
#include "kexlib/math/mathlib.h"
|
||||
|
||||
void Error(const char *error, ...);
|
||||
char *Va(const char *str, ...);
|
||||
void Delay(int ms);
|
||||
const int64_t GetSeconds(void);
|
||||
const kexStr &FilePath(void);
|
||||
|
||||
#endif
|
312
src/lightmap/kexlib/array.h
Normal file
312
src/lightmap/kexlib/array.h
Normal file
|
@ -0,0 +1,312 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __KEXARRAY_H__
|
||||
#define __KEXARRAY_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
template<class type>
|
||||
class kexArray
|
||||
{
|
||||
public:
|
||||
kexArray(void);
|
||||
~kexArray(void);
|
||||
|
||||
typedef int compare_t(const type*, const type*);
|
||||
|
||||
void Push(type o);
|
||||
void Pop(void);
|
||||
void Empty(void);
|
||||
void Init(void);
|
||||
void Resize(unsigned int size);
|
||||
type IndexOf(unsigned int index) const;
|
||||
bool Contains(const type check) const;
|
||||
void Splice(const unsigned int start, unsigned int len);
|
||||
void Sort(compare_t *function);
|
||||
void Sort(compare_t *function, unsigned int count);
|
||||
|
||||
const unsigned int Length(void) const { return length; }
|
||||
type GetData(const int index) { return data[index]; }
|
||||
|
||||
type &operator[](unsigned int index);
|
||||
kexArray<type> &operator=(const kexArray<type> &arr);
|
||||
|
||||
protected:
|
||||
type *data;
|
||||
unsigned int length;
|
||||
unsigned int aidx;
|
||||
};
|
||||
|
||||
//
|
||||
// kexArray::kexArray
|
||||
//
|
||||
template<class type>
|
||||
kexArray<type>::kexArray(void)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::~kexArray
|
||||
//
|
||||
template<class type>
|
||||
kexArray<type>::~kexArray(void)
|
||||
{
|
||||
Empty();
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Init
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Init(void)
|
||||
{
|
||||
data = NULL;
|
||||
length = 0;
|
||||
aidx = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Resize
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Resize(unsigned int size)
|
||||
{
|
||||
type *tmp;
|
||||
|
||||
if(size == length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(size <= 0 && length != 0)
|
||||
{
|
||||
delete[] data;
|
||||
data = NULL;
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(length == 0)
|
||||
{
|
||||
data = new type[size];
|
||||
length = size;
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = data;
|
||||
data = new type[size];
|
||||
|
||||
for(unsigned int i = 0; i < length; i++)
|
||||
{
|
||||
data[i] = tmp[i];
|
||||
}
|
||||
|
||||
length = size;
|
||||
delete[] tmp;
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Push
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Push(type o)
|
||||
{
|
||||
Resize(length+1);
|
||||
data[aidx++] = o;
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Pop
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Pop(void)
|
||||
{
|
||||
if(length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Resize(length-1);
|
||||
aidx--;
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Empty
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Empty(void)
|
||||
{
|
||||
if(data && length > 0)
|
||||
{
|
||||
delete[] data;
|
||||
data = NULL;
|
||||
length = 0;
|
||||
aidx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::IndexOf
|
||||
//
|
||||
template<class type>
|
||||
type kexArray<type>::IndexOf(unsigned int index) const
|
||||
{
|
||||
if(index >= length)
|
||||
{
|
||||
index = length-1;
|
||||
}
|
||||
|
||||
return data[index];
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Contains
|
||||
//
|
||||
template<class type>
|
||||
bool kexArray<type>::Contains(const type check) const
|
||||
{
|
||||
for(unsigned int i = 0; i < length; ++i)
|
||||
{
|
||||
if(data[i] == check)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Splice
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Splice(const unsigned int start, unsigned int len)
|
||||
{
|
||||
if(length == 0 || len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(len >= length)
|
||||
{
|
||||
len = length;
|
||||
}
|
||||
|
||||
type *tmp = new type[len];
|
||||
|
||||
for(unsigned int i = 0; i < len; i++)
|
||||
{
|
||||
tmp[i] = data[start+i];
|
||||
}
|
||||
|
||||
delete[] data;
|
||||
data = tmp;
|
||||
length = length - len;
|
||||
aidx = length-1;
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Sort
|
||||
//
|
||||
// Note that data will be shuffled around, so this could invalidate any
|
||||
// pointers that relies on the array/data
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Sort(compare_t *function)
|
||||
{
|
||||
if(data == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
typedef int compareCast(const void*, const void*);
|
||||
compareCast *cmpFunc = (compareCast*)function;
|
||||
|
||||
qsort((void*)data, length, sizeof(type), cmpFunc);
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::Sort
|
||||
//
|
||||
// Note that data will be shuffled around, so this could invalidate any
|
||||
// pointers that relies on the array/data
|
||||
//
|
||||
template<class type>
|
||||
void kexArray<type>::Sort(compare_t *function, unsigned int count)
|
||||
{
|
||||
if(data == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
typedef int compareCast(const void*, const void*);
|
||||
compareCast *cmpFunc = (compareCast*)function;
|
||||
|
||||
qsort((void*)data, count, sizeof(type), cmpFunc);
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::operator[]
|
||||
//
|
||||
template <class type>
|
||||
type &kexArray<type>::operator[](unsigned int index)
|
||||
{
|
||||
assert(index < length);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
//
|
||||
// kexArray::operator=
|
||||
//
|
||||
template <class type>
|
||||
kexArray<type> &kexArray<type>::operator=(const kexArray<type> &arr)
|
||||
{
|
||||
if(data)
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
data = NULL;
|
||||
length = arr.length;
|
||||
aidx = arr.aidx;
|
||||
|
||||
if(arr.length > 0)
|
||||
{
|
||||
data = new type[arr.length];
|
||||
|
||||
for(unsigned int i = 0; i < arr.length; i++)
|
||||
{
|
||||
data[i] = arr.data[i];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
399
src/lightmap/kexlib/binfile.cpp
Normal file
399
src/lightmap/kexlib/binfile.cpp
Normal file
|
@ -0,0 +1,399 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Binary file operations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "lightmap/common.h"
|
||||
#include "lightmap/kexlib/binFile.h"
|
||||
|
||||
//
|
||||
// kexBinFile::kexBinFile
|
||||
//
|
||||
|
||||
kexBinFile::kexBinFile(void)
|
||||
{
|
||||
this->handle = NULL;
|
||||
this->buffer = NULL;
|
||||
this->bufferOffset = 0;
|
||||
this->bOpened = false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::~kexBinFile
|
||||
//
|
||||
|
||||
kexBinFile::~kexBinFile(void)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Open
|
||||
//
|
||||
|
||||
bool kexBinFile::Open(const char *file, kexHeapBlock &heapBlock)
|
||||
{
|
||||
if((handle = fopen(file, "rb")))
|
||||
{
|
||||
size_t length;
|
||||
|
||||
fseek(handle, 0, SEEK_END);
|
||||
length = ftell(handle);
|
||||
fseek(handle, 0, SEEK_SET);
|
||||
|
||||
buffer = (byte*)Mem_Calloc(length+1, heapBlock);
|
||||
|
||||
if(fread(buffer, 1, length, handle) == length)
|
||||
{
|
||||
if(length > 0)
|
||||
{
|
||||
bOpened = true;
|
||||
bufferOffset = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Mem_Free(buffer);
|
||||
buffer = NULL;
|
||||
fclose(handle);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Create
|
||||
//
|
||||
|
||||
bool kexBinFile::Create(const char *file)
|
||||
{
|
||||
if((handle = fopen(file, "wb")))
|
||||
{
|
||||
bOpened = true;
|
||||
bufferOffset = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Close
|
||||
//
|
||||
|
||||
void kexBinFile::Close(void)
|
||||
{
|
||||
if(bOpened == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(handle)
|
||||
{
|
||||
fclose(handle);
|
||||
handle = NULL;
|
||||
if(buffer)
|
||||
{
|
||||
Mem_Free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bOpened = false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Exists
|
||||
//
|
||||
|
||||
bool kexBinFile::Exists(const char *file)
|
||||
{
|
||||
FILE *fstream;
|
||||
|
||||
fstream = fopen(file, "r");
|
||||
|
||||
if(fstream != NULL)
|
||||
{
|
||||
fclose(fstream);
|
||||
return true;
|
||||
}
|
||||
#ifdef KEX_WIN32
|
||||
else
|
||||
{
|
||||
// If we can't open because the file is a directory, the
|
||||
// "file" exists at least!
|
||||
if(errno == 21)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Duplicate
|
||||
//
|
||||
|
||||
void kexBinFile::Duplicate(const char *newFileName)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
if(bOpened == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
f = fopen(newFileName, "wb");
|
||||
|
||||
if(f == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(buffer, Length(), 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Length
|
||||
//
|
||||
|
||||
int kexBinFile::Length(void)
|
||||
{
|
||||
long savedpos;
|
||||
long length;
|
||||
|
||||
if(bOpened == false)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// save the current position in the file
|
||||
savedpos = ftell(handle);
|
||||
|
||||
// jump to the end and find the length
|
||||
fseek(handle, 0, SEEK_END);
|
||||
length = ftell(handle);
|
||||
|
||||
// go back to the old location
|
||||
fseek(handle, savedpos, SEEK_SET);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Read8
|
||||
//
|
||||
|
||||
byte kexBinFile::Read8(void)
|
||||
{
|
||||
byte result;
|
||||
result = buffer[bufferOffset++];
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Read16
|
||||
//
|
||||
|
||||
short kexBinFile::Read16(void)
|
||||
{
|
||||
int result;
|
||||
result = Read8();
|
||||
result |= Read8() << 8;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Read32
|
||||
//
|
||||
|
||||
int kexBinFile::Read32(void)
|
||||
{
|
||||
int result;
|
||||
result = Read8();
|
||||
result |= Read8() << 8;
|
||||
result |= Read8() << 16;
|
||||
result |= Read8() << 24;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::ReadFloat
|
||||
//
|
||||
|
||||
float kexBinFile::ReadFloat(void)
|
||||
{
|
||||
fint_t fi;
|
||||
fi.i = Read32();
|
||||
return fi.f;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::ReadVector
|
||||
//
|
||||
|
||||
kexVec3 kexBinFile::ReadVector(void)
|
||||
{
|
||||
kexVec3 vec;
|
||||
|
||||
vec.x = ReadFloat();
|
||||
vec.y = ReadFloat();
|
||||
vec.z = ReadFloat();
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::ReadString
|
||||
//
|
||||
|
||||
kexStr kexBinFile::ReadString(void)
|
||||
{
|
||||
kexStr str;
|
||||
char c = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(!(c = Read8()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
str += c;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Write8
|
||||
//
|
||||
|
||||
void kexBinFile::Write8(const byte val)
|
||||
{
|
||||
if(bOpened)
|
||||
{
|
||||
fwrite(&val, 1, 1, handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[bufferOffset] = val;
|
||||
}
|
||||
bufferOffset++;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Write16
|
||||
//
|
||||
|
||||
void kexBinFile::Write16(const short val)
|
||||
{
|
||||
Write8(val & 0xff);
|
||||
Write8((val >> 8) & 0xff);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::Write32
|
||||
//
|
||||
|
||||
void kexBinFile::Write32(const int val)
|
||||
{
|
||||
Write8(val & 0xff);
|
||||
Write8((val >> 8) & 0xff);
|
||||
Write8((val >> 16) & 0xff);
|
||||
Write8((val >> 24) & 0xff);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::WriteFloat
|
||||
//
|
||||
|
||||
void kexBinFile::WriteFloat(const float val)
|
||||
{
|
||||
fint_t fi;
|
||||
fi.f = val;
|
||||
Write32(fi.i);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::WriteVector
|
||||
//
|
||||
|
||||
void kexBinFile::WriteVector(const kexVec3 &val)
|
||||
{
|
||||
WriteFloat(val.x);
|
||||
WriteFloat(val.y);
|
||||
WriteFloat(val.z);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::WriteString
|
||||
//
|
||||
|
||||
void kexBinFile::WriteString(const kexStr &val)
|
||||
{
|
||||
const char *c = val.c_str();
|
||||
|
||||
for(int i = 0; i < val.Length(); i++)
|
||||
{
|
||||
Write8(c[i]);
|
||||
}
|
||||
|
||||
Write8(0);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::GetOffsetValue
|
||||
//
|
||||
|
||||
int kexBinFile::GetOffsetValue(int id)
|
||||
{
|
||||
return *(int*)(buffer + (id << 2));
|
||||
}
|
||||
|
||||
//
|
||||
// kexBinFile::GetOffset
|
||||
//
|
||||
|
||||
byte *kexBinFile::GetOffset(int id, byte *subdata, int *count)
|
||||
{
|
||||
byte *data = (subdata == NULL) ? buffer : subdata;
|
||||
|
||||
bufferOffset = GetOffsetValue(id);
|
||||
byte *dataOffs = &data[bufferOffset];
|
||||
|
||||
if(count)
|
||||
{
|
||||
*count = *(int*)(dataOffs);
|
||||
}
|
||||
|
||||
return dataOffs;
|
||||
}
|
79
src/lightmap/kexlib/binfile.h
Normal file
79
src/lightmap/kexlib/binfile.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __BINFILE_H__
|
||||
#define __BINFILE_H__
|
||||
|
||||
#include "lightmap/kexlib/math/mathlib.h"
|
||||
|
||||
class kexBinFile
|
||||
{
|
||||
public:
|
||||
kexBinFile(void);
|
||||
~kexBinFile(void);
|
||||
|
||||
bool Open(const char *file, kexHeapBlock &heapBlock = hb_static);
|
||||
bool Create(const char *file);
|
||||
void Close(void);
|
||||
bool Exists(const char *file);
|
||||
int Length(void);
|
||||
void Duplicate(const char *newFileName);
|
||||
|
||||
byte Read8(void);
|
||||
short Read16(void);
|
||||
int Read32(void);
|
||||
float ReadFloat(void);
|
||||
kexVec3 ReadVector(void);
|
||||
kexStr ReadString(void);
|
||||
|
||||
void Write8(const byte val);
|
||||
void Write16(const short val);
|
||||
void Write32(const int val);
|
||||
void WriteFloat(const float val);
|
||||
void WriteVector(const kexVec3 &val);
|
||||
void WriteString(const kexStr &val);
|
||||
|
||||
int GetOffsetValue(int id);
|
||||
byte *GetOffset(int id,
|
||||
byte *subdata = NULL,
|
||||
int *count = NULL);
|
||||
|
||||
FILE *Handle(void) const { return handle; }
|
||||
byte *Buffer(void) const { return buffer; }
|
||||
void SetBuffer(byte *ptr) { buffer = ptr; }
|
||||
byte *BufferAt(void) const { return &buffer[bufferOffset]; }
|
||||
bool Opened(void) const { return bOpened; }
|
||||
void SetOffset(const int offset) { bufferOffset = offset; }
|
||||
|
||||
private:
|
||||
FILE *handle;
|
||||
byte *buffer;
|
||||
unsigned int bufferOffset;
|
||||
bool bOpened;
|
||||
};
|
||||
|
||||
#endif
|
804
src/lightmap/kexlib/kstring.cpp
Normal file
804
src/lightmap/kexlib/kstring.cpp
Normal file
|
@ -0,0 +1,804 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: String Class
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <ctype.h>
|
||||
#include "kstring.h"
|
||||
|
||||
//
|
||||
// kexStr::Init
|
||||
//
|
||||
|
||||
void kexStr::Init(void)
|
||||
{
|
||||
length = 0;
|
||||
bufferLength = STRING_DEFAULT_SIZE;
|
||||
charPtr = defaultBuffer;
|
||||
charPtr[0] = '\0';
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::CheckSize
|
||||
//
|
||||
|
||||
void kexStr::CheckSize(int size, bool bKeepString)
|
||||
{
|
||||
if(size <= bufferLength)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Resize(size, bKeepString);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::CopyNew
|
||||
//
|
||||
|
||||
void kexStr::CopyNew(const char *string, int len)
|
||||
{
|
||||
CheckSize(len+1, false);
|
||||
strcpy(charPtr, string);
|
||||
length = len;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::kexStr
|
||||
//
|
||||
|
||||
kexStr::kexStr(void)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::kexStr
|
||||
//
|
||||
|
||||
kexStr::kexStr(const char *string)
|
||||
{
|
||||
Init();
|
||||
|
||||
if(string == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CopyNew(string, strlen(string));
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::kexStr
|
||||
//
|
||||
|
||||
kexStr::kexStr(const char *string, const int length)
|
||||
{
|
||||
Init();
|
||||
|
||||
if(string == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CopyNew(string, length);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::kexStr
|
||||
//
|
||||
|
||||
kexStr::kexStr(const kexStr &string)
|
||||
{
|
||||
Init();
|
||||
|
||||
if(string.charPtr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CopyNew(string.charPtr, string.Length());
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::~kexStr
|
||||
//
|
||||
|
||||
kexStr::~kexStr(void)
|
||||
{
|
||||
if(charPtr != defaultBuffer)
|
||||
{
|
||||
delete[] charPtr;
|
||||
charPtr = defaultBuffer;
|
||||
}
|
||||
|
||||
charPtr[0] = '\0';
|
||||
length = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Concat
|
||||
//
|
||||
|
||||
kexStr &kexStr::Concat(const char *string)
|
||||
{
|
||||
return Concat(string, strlen(string));
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Concat
|
||||
//
|
||||
|
||||
kexStr &kexStr::Concat(const char c)
|
||||
{
|
||||
CheckSize((length + 1)+1, true);
|
||||
charPtr[length++] = c;
|
||||
charPtr[length] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Concat
|
||||
//
|
||||
|
||||
kexStr &kexStr::Concat(const char *string, int len)
|
||||
{
|
||||
CheckSize((length + len)+1, true);
|
||||
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
charPtr[length+i] = string[i];
|
||||
}
|
||||
|
||||
length += len;
|
||||
charPtr[length] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Copy
|
||||
//
|
||||
|
||||
kexStr &kexStr::Copy(const kexStr &src, int len)
|
||||
{
|
||||
int i = 0;
|
||||
const char *p = src;
|
||||
CheckSize((length + len)+1, true);
|
||||
|
||||
while((len--) >= 0)
|
||||
{
|
||||
charPtr[i] = p[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Copy
|
||||
//
|
||||
|
||||
kexStr &kexStr::Copy(const kexStr &src)
|
||||
{
|
||||
return Copy(src, src.Length());
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator=
|
||||
//
|
||||
|
||||
kexStr &kexStr::operator=(const kexStr &str)
|
||||
{
|
||||
int len = str.Length();
|
||||
|
||||
CheckSize(len+1, false);
|
||||
strncpy(charPtr, str.charPtr, len);
|
||||
length = len;
|
||||
charPtr[length] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator=
|
||||
//
|
||||
|
||||
kexStr &kexStr::operator=(const char *str)
|
||||
{
|
||||
int len = strlen(str);
|
||||
|
||||
CheckSize(len+1, false);
|
||||
strncpy(charPtr, str, len);
|
||||
length = len;
|
||||
charPtr[length] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator=
|
||||
//
|
||||
|
||||
kexStr &kexStr::operator=(const bool b)
|
||||
{
|
||||
const char *str = b ? "true" : "false";
|
||||
int len = strlen(str);
|
||||
|
||||
CheckSize(len+1, false);
|
||||
strncpy(charPtr, str, len);
|
||||
length = len;
|
||||
charPtr[length] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+
|
||||
//
|
||||
|
||||
kexStr kexStr::operator+(const kexStr &str)
|
||||
{
|
||||
kexStr out(*this);
|
||||
|
||||
return out.Concat(str.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+
|
||||
//
|
||||
|
||||
kexStr kexStr::operator+(const char *str)
|
||||
{
|
||||
kexStr out(*this);
|
||||
|
||||
return out.Concat(str);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+
|
||||
//
|
||||
|
||||
kexStr kexStr::operator+(const bool b)
|
||||
{
|
||||
kexStr out(*this);
|
||||
|
||||
return out.Concat(b ? "true" : "false");
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+
|
||||
//
|
||||
|
||||
kexStr kexStr::operator+(const int i)
|
||||
{
|
||||
kexStr out(*this);
|
||||
|
||||
char tmp[64];
|
||||
sprintf(tmp, "%i", i);
|
||||
|
||||
return out.Concat(tmp);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+
|
||||
//
|
||||
|
||||
kexStr kexStr::operator+(const float f)
|
||||
{
|
||||
kexStr out(*this);
|
||||
|
||||
char tmp[64];
|
||||
sprintf(tmp, "%f", f);
|
||||
|
||||
return out.Concat(tmp);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+=
|
||||
//
|
||||
|
||||
kexStr &kexStr::operator+=(const kexStr &str)
|
||||
{
|
||||
return Concat(str.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+=
|
||||
//
|
||||
|
||||
kexStr &kexStr::operator+=(const char *str)
|
||||
{
|
||||
return Concat(str);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+=
|
||||
//
|
||||
|
||||
kexStr &kexStr::operator+=(const char c)
|
||||
{
|
||||
return Concat(c);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator+=
|
||||
//
|
||||
|
||||
kexStr &kexStr::operator+=(const bool b)
|
||||
{
|
||||
return Concat(b ? "true" : "false");
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::operator[]
|
||||
//
|
||||
|
||||
const char kexStr::operator[](int index) const
|
||||
{
|
||||
assert(index >= 0 && index < length);
|
||||
return charPtr[index];
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Resize
|
||||
//
|
||||
|
||||
void kexStr::Resize(int size, bool bKeepString)
|
||||
{
|
||||
|
||||
if(size <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int newsize = size + ((32 - (size & 31)) & 31);
|
||||
char *newbuffer = new char[newsize];
|
||||
|
||||
if(bKeepString)
|
||||
{
|
||||
strncpy(newbuffer, charPtr, length);
|
||||
}
|
||||
|
||||
if(charPtr != defaultBuffer)
|
||||
{
|
||||
delete[] charPtr;
|
||||
}
|
||||
|
||||
charPtr = newbuffer;
|
||||
bufferLength = newsize;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::IndexOf
|
||||
//
|
||||
|
||||
int kexStr::IndexOf(const char *pattern) const
|
||||
{
|
||||
int patlen = strlen(pattern);
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
while(i + j < Length())
|
||||
{
|
||||
if(charPtr[i + j] == pattern[j])
|
||||
{
|
||||
if(++j == patlen)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::IndexOf
|
||||
//
|
||||
|
||||
int kexStr::IndexOf(const char *string, const char *pattern)
|
||||
{
|
||||
int patlen = strlen(pattern);
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
while(i + j < (int)strlen(string))
|
||||
{
|
||||
if(string[i + j] == pattern[j])
|
||||
{
|
||||
if(++j == patlen)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::IndexOf
|
||||
//
|
||||
|
||||
int kexStr::IndexOf(const kexStr &pattern) const
|
||||
{
|
||||
return IndexOf(pattern.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::NormalizeSlashes
|
||||
//
|
||||
|
||||
kexStr &kexStr::NormalizeSlashes(void)
|
||||
{
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
if((charPtr[i] == '/' || charPtr[i] == '\\') && charPtr[i] != DIR_SEPARATOR)
|
||||
{
|
||||
charPtr[i] = DIR_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::StripPath
|
||||
//
|
||||
|
||||
kexStr &kexStr::StripPath(void)
|
||||
{
|
||||
int pos = 0;
|
||||
int i = 0;
|
||||
|
||||
pos = length;
|
||||
|
||||
for(i = length - 1; charPtr[i] != '\\' && charPtr[i] != '/'; i--, pos--)
|
||||
{
|
||||
if(pos <= 0)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
length = length - pos;
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
charPtr[i] = charPtr[pos+i];
|
||||
}
|
||||
|
||||
CheckSize(length, true);
|
||||
charPtr[length] = '\0';
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::StripExtension
|
||||
//
|
||||
|
||||
kexStr &kexStr::StripExtension(void)
|
||||
{
|
||||
int pos = IndexOf(".");
|
||||
|
||||
if(pos == -1)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
length = pos;
|
||||
CheckSize(length, true);
|
||||
charPtr[length] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::StripFile
|
||||
//
|
||||
|
||||
kexStr &kexStr::StripFile(void)
|
||||
{
|
||||
int pos = 0;
|
||||
int i = 0;
|
||||
|
||||
if(IndexOf(".") == -1)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
pos = length;
|
||||
|
||||
for(i = length - 1; charPtr[i] != '\\' && charPtr[i] != '/'; i--, pos--)
|
||||
{
|
||||
if(pos <= 0)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
length = pos;
|
||||
CheckSize(length, true);
|
||||
charPtr[length] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Hash
|
||||
//
|
||||
|
||||
int kexStr::Hash(void)
|
||||
{
|
||||
unsigned int hash = 0;
|
||||
char *str = (char*)charPtr;
|
||||
char c;
|
||||
|
||||
while((c = *str++))
|
||||
{
|
||||
hash = c + (hash << 6) + (hash << 16) - hash;
|
||||
}
|
||||
|
||||
return hash & (MAX_HASH-1);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Hash
|
||||
//
|
||||
|
||||
int kexStr::Hash(const char *s)
|
||||
{
|
||||
unsigned int hash = 0;
|
||||
char *str = (char*)s;
|
||||
char c;
|
||||
|
||||
while((c = *str++))
|
||||
{
|
||||
hash = c + (hash << 6) + (hash << 16) - hash;
|
||||
}
|
||||
|
||||
return hash & (MAX_HASH-1);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Format
|
||||
//
|
||||
|
||||
char *kexStr::Format(const char *str, ...)
|
||||
{
|
||||
va_list v;
|
||||
static char vastr[1024];
|
||||
|
||||
va_start(v, str);
|
||||
vsprintf(vastr, str,v);
|
||||
va_end(v);
|
||||
|
||||
return vastr;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Substr
|
||||
//
|
||||
|
||||
kexStr kexStr::Substr(int start, int len) const
|
||||
{
|
||||
kexStr str;
|
||||
int l = Length();
|
||||
|
||||
if(l <= 0 || start >= l)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
if(start + len >= l)
|
||||
{
|
||||
len = l - start;
|
||||
}
|
||||
|
||||
return str.Concat((const char*)&charPtr[start], len);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Split
|
||||
//
|
||||
|
||||
void kexStr::Split(kexStrList &list, const char seperator)
|
||||
{
|
||||
int splitLen = 0;
|
||||
int startOffs = 0;
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
if(charPtr[i] == seperator)
|
||||
{
|
||||
if(splitLen == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
list.Push(kexStr(&charPtr[startOffs], splitLen));
|
||||
startOffs += (splitLen+1);
|
||||
splitLen = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
splitLen++;
|
||||
}
|
||||
|
||||
if(splitLen != 0 && startOffs != 0)
|
||||
{
|
||||
list.Push(kexStr(&charPtr[startOffs], splitLen));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Atoi
|
||||
//
|
||||
|
||||
int kexStr::Atoi(void)
|
||||
{
|
||||
return atoi(charPtr);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Atof
|
||||
//
|
||||
|
||||
float kexStr::Atof(void)
|
||||
{
|
||||
return (float)atof(charPtr);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::WriteToFile
|
||||
//
|
||||
|
||||
void kexStr::WriteToFile(const char *file)
|
||||
{
|
||||
if(length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *f = fopen(file, "w");
|
||||
fprintf(f, "%s", charPtr);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::ToUpper
|
||||
//
|
||||
|
||||
kexStr &kexStr::ToUpper(void)
|
||||
{
|
||||
char c;
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
c = charPtr[i];
|
||||
if(c >= 'a' && c <= 'z')
|
||||
{
|
||||
c -= 'a'-'A';
|
||||
}
|
||||
charPtr[i] = c;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::ToLower
|
||||
//
|
||||
|
||||
kexStr &kexStr::ToLower(void)
|
||||
{
|
||||
char c;
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
c = charPtr[i];
|
||||
if(c >= 'A' && c <= 'Z')
|
||||
{
|
||||
c += 32;
|
||||
}
|
||||
charPtr[i] = c;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::CompareCase
|
||||
//
|
||||
|
||||
bool kexStr::CompareCase(const char *s1, const char *s2)
|
||||
{
|
||||
while(*s1 && *s2)
|
||||
{
|
||||
if(*s1 != *s2)
|
||||
{
|
||||
return (*s2 - *s1) != 0;
|
||||
}
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
if(*s1 != *s2)
|
||||
{
|
||||
return (*s2 - *s1) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::CompareCase
|
||||
//
|
||||
|
||||
bool kexStr::CompareCase(const kexStr &a, const kexStr &b)
|
||||
{
|
||||
return CompareCase(a.c_str(), b.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Compare
|
||||
//
|
||||
|
||||
bool kexStr::Compare(const char *s1, const char *s2)
|
||||
{
|
||||
const byte *us1 = (const byte*)s1;
|
||||
const byte *us2 = (const byte*)s2;
|
||||
|
||||
while(tolower(*us1) == tolower(*us2))
|
||||
{
|
||||
if(*us1++ == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
us2++;
|
||||
}
|
||||
|
||||
return (tolower(*us1) - tolower(*us2)) != 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexStr::Compare
|
||||
//
|
||||
|
||||
bool kexStr::Compare(const kexStr &a, const kexStr &b)
|
||||
{
|
||||
return Compare(a.c_str(), b.c_str());
|
||||
}
|
131
src/lightmap/kexlib/kstring.h
Normal file
131
src/lightmap/kexlib/kstring.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __KSTRING_H__
|
||||
#define __KSTRING_H__
|
||||
|
||||
#include <string.h>
|
||||
#include "lightmap/common.h"
|
||||
#include "array.h"
|
||||
|
||||
class kexStr;
|
||||
|
||||
typedef kexArray<kexStr> kexStrList;
|
||||
|
||||
class kexStr
|
||||
{
|
||||
public:
|
||||
kexStr(void);
|
||||
kexStr(const char *string);
|
||||
kexStr(const char *string, const int length);
|
||||
kexStr(const kexStr &string);
|
||||
~kexStr(void);
|
||||
|
||||
void CheckSize(int size, bool bKeepString);
|
||||
int IndexOf(const char *pattern) const;
|
||||
int IndexOf(const kexStr &pattern) const;
|
||||
kexStr &Concat(const char *string);
|
||||
kexStr &Concat(const char *string, int len);
|
||||
kexStr &Concat(const char c);
|
||||
kexStr &NormalizeSlashes(void);
|
||||
kexStr &StripPath(void);
|
||||
kexStr &StripExtension(void);
|
||||
kexStr &StripFile(void);
|
||||
kexStr &Copy(const kexStr &src, int len);
|
||||
kexStr &Copy(const kexStr &src);
|
||||
kexStr &ToUpper(void);
|
||||
kexStr &ToLower(void);
|
||||
int Hash(void);
|
||||
kexStr Substr(int start, int len) const;
|
||||
void Split(kexStrList &list, const char seperator);
|
||||
int Atoi(void);
|
||||
float Atof(void);
|
||||
void WriteToFile(const char *file);
|
||||
|
||||
int Length(void) const { return length; }
|
||||
const char *c_str(void) const { return charPtr; }
|
||||
|
||||
kexStr &operator=(const kexStr &str);
|
||||
kexStr &operator=(const char *str);
|
||||
kexStr &operator=(const bool b);
|
||||
kexStr operator+(const kexStr &str);
|
||||
kexStr operator+(const char *str);
|
||||
kexStr operator+(const bool b);
|
||||
kexStr operator+(const int i);
|
||||
kexStr operator+(const float f);
|
||||
kexStr &operator+=(const kexStr &str);
|
||||
kexStr &operator+=(const char *str);
|
||||
kexStr &operator+=(const char c);
|
||||
kexStr &operator+=(const bool b);
|
||||
const char operator[](int index) const;
|
||||
|
||||
friend bool operator==(const kexStr &a, const kexStr &b);
|
||||
friend bool operator==(const char *a, const kexStr &b);
|
||||
friend bool operator==(const kexStr &a, const char *b);
|
||||
|
||||
operator const char *(void) const { return c_str(); }
|
||||
operator const char *(void) { return c_str(); }
|
||||
|
||||
static bool CompareCase(const char *s1, const char *s2);
|
||||
static bool CompareCase(const kexStr &a, const kexStr &b);
|
||||
static bool Compare(const char *s1, const char *s2);
|
||||
static bool Compare(const kexStr &a, const kexStr &b);
|
||||
static int IndexOf(const char *string, const char *pattern);
|
||||
static int Hash(const char *s);
|
||||
static char *Format(const char *str, ...);
|
||||
|
||||
private:
|
||||
void Resize(int size, bool bKeepString);
|
||||
void CopyNew(const char *string, int len);
|
||||
|
||||
protected:
|
||||
void Init(void);
|
||||
|
||||
static const int STRING_DEFAULT_SIZE = 32;
|
||||
|
||||
char *charPtr;
|
||||
char defaultBuffer[STRING_DEFAULT_SIZE];
|
||||
int length;
|
||||
int bufferLength;
|
||||
};
|
||||
|
||||
d_inline bool operator==(const kexStr &a, const kexStr &b)
|
||||
{
|
||||
return (!strcmp(a.charPtr, b.charPtr));
|
||||
}
|
||||
|
||||
d_inline bool operator==(const char *a, const kexStr &b)
|
||||
{
|
||||
return (!strcmp(a, b.charPtr));
|
||||
}
|
||||
|
||||
d_inline bool operator==(const kexStr &a, const char *b)
|
||||
{
|
||||
return (!strcmp(a.charPtr, b));
|
||||
}
|
||||
|
||||
#endif
|
405
src/lightmap/kexlib/math/angle.cpp
Normal file
405
src/lightmap/kexlib/math/angle.cpp
Normal file
|
@ -0,0 +1,405 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Angle operations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
#define FULLCIRCLE (M_PI * 2)
|
||||
|
||||
//
|
||||
// kexAngle::kexAngle
|
||||
//
|
||||
|
||||
kexAngle::kexAngle(void)
|
||||
{
|
||||
this->yaw = 0;
|
||||
this->pitch = 0;
|
||||
this->roll = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::kexAngle
|
||||
//
|
||||
|
||||
kexAngle::kexAngle(const float yaw, const float pitch, const float roll)
|
||||
{
|
||||
this->yaw = yaw;
|
||||
this->pitch = pitch;
|
||||
this->roll = roll;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::kexAngle
|
||||
//
|
||||
|
||||
kexAngle::kexAngle(const kexVec3 &vector)
|
||||
{
|
||||
this->yaw = vector.x;
|
||||
this->pitch = vector.y;
|
||||
this->roll = vector.z;
|
||||
|
||||
Clamp180();
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::kexAngle
|
||||
//
|
||||
|
||||
kexAngle::kexAngle(const kexAngle &an)
|
||||
{
|
||||
this->yaw = an.yaw;
|
||||
this->pitch = an.pitch;
|
||||
this->roll = an.roll;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::Clamp180
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::Clamp180(void)
|
||||
{
|
||||
#define CLAMP180(x) \
|
||||
if(x < -M_PI) for(; x < -M_PI; x = x + FULLCIRCLE); \
|
||||
if(x > M_PI) for(; x > M_PI; x = x - FULLCIRCLE)
|
||||
CLAMP180(yaw);
|
||||
CLAMP180(pitch);
|
||||
CLAMP180(roll);
|
||||
#undef CLAMP180
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::Clamp180Invert
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::Clamp180Invert(void)
|
||||
{
|
||||
#define CLAMP180(x) \
|
||||
for(; x < -M_PI; x = x + FULLCIRCLE); \
|
||||
for(; x > M_PI; x = x - FULLCIRCLE)
|
||||
CLAMP180(yaw);
|
||||
CLAMP180(pitch);
|
||||
CLAMP180(roll);
|
||||
#undef CLAMP180
|
||||
|
||||
yaw = -yaw;
|
||||
pitch = -pitch;
|
||||
roll = -roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::Clamp180InvertSum
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::Clamp180InvertSum(const kexAngle &angle)
|
||||
{
|
||||
kexAngle an = angle;
|
||||
|
||||
an.Clamp180Invert();
|
||||
|
||||
an.yaw += this->yaw;
|
||||
an.pitch += this->pitch;
|
||||
an.roll += this->roll;
|
||||
|
||||
an.Clamp180Invert();
|
||||
|
||||
this->yaw = an.yaw;
|
||||
this->pitch = an.pitch;
|
||||
this->roll = an.roll;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::Round
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::Round(void)
|
||||
{
|
||||
#define ROUND(x) \
|
||||
x = DEG2RAD((360.0f / 65536.0f) * \
|
||||
((int)(RAD2DEG(x) * (65536.0f / 360.0f)) & 65535))
|
||||
yaw = ROUND(yaw);
|
||||
pitch = ROUND(pitch);
|
||||
roll = ROUND(roll);
|
||||
#undef ROUND
|
||||
|
||||
return Clamp180();
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::Diff
|
||||
//
|
||||
|
||||
kexAngle kexAngle::Diff(kexAngle &angle)
|
||||
{
|
||||
float an;
|
||||
kexAngle out;
|
||||
|
||||
Clamp180();
|
||||
angle.Clamp180();
|
||||
|
||||
#define DIFF(x) \
|
||||
if(x <= angle.x) { \
|
||||
an = angle.x + FULLCIRCLE; \
|
||||
if(x - angle.x > an - x) { \
|
||||
out.x = x - an; \
|
||||
} \
|
||||
else { \
|
||||
out.x = x - angle.x; \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
an = angle.x - FULLCIRCLE; \
|
||||
if(angle.x - x <= x - an) { \
|
||||
out.x = x - angle.x; \
|
||||
} \
|
||||
else { \
|
||||
out.x = x - an; \
|
||||
} \
|
||||
}
|
||||
DIFF(yaw);
|
||||
DIFF(pitch);
|
||||
DIFF(roll);
|
||||
#undef DIFF
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::ToAxis
|
||||
//
|
||||
|
||||
void kexAngle::ToAxis(kexVec3 *forward, kexVec3 *up, kexVec3 *right)
|
||||
{
|
||||
float sy = kexMath::Sin(yaw);
|
||||
float cy = kexMath::Cos(yaw);
|
||||
float sp = kexMath::Sin(pitch);
|
||||
float cp = kexMath::Cos(pitch);
|
||||
float sr = kexMath::Sin(roll);
|
||||
float cr = kexMath::Cos(roll);
|
||||
|
||||
if(forward)
|
||||
{
|
||||
forward->x = sy * cp;
|
||||
forward->y = sp;
|
||||
forward->z = cy * cp;
|
||||
}
|
||||
if(right)
|
||||
{
|
||||
right->x = sr * sp * sy + cr * cy;
|
||||
right->y = sr * cp;
|
||||
right->z = sr * sp * cy + cr * -sy;
|
||||
}
|
||||
if(up)
|
||||
{
|
||||
up->x = cr * sp * sy + -sr * cy;
|
||||
up->y = cr * cp;
|
||||
up->z = cr * sp * cy + -sr * -sy;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::ToForwardAxis
|
||||
//
|
||||
|
||||
kexVec3 kexAngle::ToForwardAxis(void)
|
||||
{
|
||||
kexVec3 vec;
|
||||
|
||||
ToAxis(&vec, NULL, NULL);
|
||||
return vec;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::ToUpAxis
|
||||
//
|
||||
|
||||
kexVec3 kexAngle::ToUpAxis(void)
|
||||
{
|
||||
kexVec3 vec;
|
||||
|
||||
ToAxis(NULL, &vec, NULL);
|
||||
return vec;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::ToRightAxis
|
||||
//
|
||||
|
||||
kexVec3 kexAngle::ToRightAxis(void)
|
||||
{
|
||||
kexVec3 vec;
|
||||
|
||||
ToAxis(NULL, NULL, &vec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::ToVec3
|
||||
//
|
||||
|
||||
const kexVec3 &kexAngle::ToVec3(void) const
|
||||
{
|
||||
return *reinterpret_cast<const kexVec3*>(&yaw);
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::ToVec3
|
||||
//
|
||||
|
||||
kexVec3 &kexAngle::ToVec3(void)
|
||||
{
|
||||
return *reinterpret_cast<kexVec3*>(&yaw);
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::ToQuat
|
||||
//
|
||||
|
||||
kexQuat kexAngle::ToQuat(void)
|
||||
{
|
||||
return
|
||||
(kexQuat(pitch, kexVec3::vecRight) *
|
||||
(kexQuat(yaw, kexVec3::vecUp) *
|
||||
kexQuat(roll, kexVec3::vecForward)));
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator+
|
||||
//
|
||||
|
||||
kexAngle kexAngle::operator+(const kexAngle &angle)
|
||||
{
|
||||
return kexAngle(yaw + angle.yaw, pitch + angle.pitch, roll + angle.roll);
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator-
|
||||
//
|
||||
|
||||
kexAngle kexAngle::operator-(const kexAngle &angle)
|
||||
{
|
||||
return kexAngle(yaw - angle.yaw, pitch - angle.pitch, roll - angle.roll);
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator-
|
||||
//
|
||||
|
||||
kexAngle kexAngle::operator-(void)
|
||||
{
|
||||
return kexAngle(-yaw, -pitch, -roll);
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator+=
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::operator+=(const kexAngle &angle)
|
||||
{
|
||||
yaw += angle.yaw;
|
||||
pitch += angle.pitch;
|
||||
roll += angle.roll;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator-=
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::operator-=(const kexAngle &angle)
|
||||
{
|
||||
yaw -= angle.yaw;
|
||||
pitch -= angle.pitch;
|
||||
roll -= angle.roll;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator=
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::operator=(const kexAngle &angle)
|
||||
{
|
||||
yaw = angle.yaw;
|
||||
pitch = angle.pitch;
|
||||
roll = angle.roll;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator=
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::operator=(const kexVec3 &vector)
|
||||
{
|
||||
yaw = vector.x;
|
||||
pitch = vector.y;
|
||||
roll = vector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator=
|
||||
//
|
||||
|
||||
kexAngle &kexAngle::operator=(const float *vecs)
|
||||
{
|
||||
yaw = vecs[0];
|
||||
pitch = vecs[1];
|
||||
roll = vecs[2];
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator[]
|
||||
//
|
||||
|
||||
float kexAngle::operator[](int index) const
|
||||
{
|
||||
assert(index >= 0 && index < 3);
|
||||
return (&yaw)[index];
|
||||
}
|
||||
|
||||
//
|
||||
// kexAngle::operator[]
|
||||
//
|
||||
|
||||
float &kexAngle::operator[](int index)
|
||||
{
|
||||
assert(index >= 0 && index < 3);
|
||||
return (&yaw)[index];
|
||||
}
|
520
src/lightmap/kexlib/math/bounds.cpp
Normal file
520
src/lightmap/kexlib/math/bounds.cpp
Normal file
|
@ -0,0 +1,520 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Bounding box operations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
//
|
||||
// kexBBox::kexBBox
|
||||
//
|
||||
|
||||
kexBBox::kexBBox(void)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::kexBBox
|
||||
//
|
||||
|
||||
kexBBox::kexBBox(const kexVec3 &vMin, const kexVec3 &vMax)
|
||||
{
|
||||
this->min = vMin;
|
||||
this->max = vMax;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::Clear
|
||||
//
|
||||
|
||||
void kexBBox::Clear(void)
|
||||
{
|
||||
min.Set(M_INFINITY, M_INFINITY, M_INFINITY);
|
||||
max.Set(-M_INFINITY, -M_INFINITY, -M_INFINITY);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::AddPoint
|
||||
//
|
||||
|
||||
void kexBBox::AddPoint(const kexVec3 &vec)
|
||||
{
|
||||
float lowx = min.x;
|
||||
float lowy = min.y;
|
||||
float lowz = min.z;
|
||||
float hix = max.x;
|
||||
float hiy = max.y;
|
||||
float hiz = max.z;
|
||||
|
||||
if(vec.x < lowx) { lowx = vec.x; }
|
||||
if(vec.y < lowy) { lowy = vec.y; }
|
||||
if(vec.z < lowz) { lowz = vec.z; }
|
||||
if(vec.x > hix) { hix = vec.x; }
|
||||
if(vec.y > hiy) { hiy = vec.y; }
|
||||
if(vec.z > hiz) { hiz = vec.z; }
|
||||
|
||||
min.Set(lowx, lowy, lowz);
|
||||
max.Set(hix, hiy, hiz);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::Center
|
||||
//
|
||||
|
||||
kexVec3 kexBBox::Center(void) const
|
||||
{
|
||||
return kexVec3(
|
||||
(max.x + min.x) * 0.5f,
|
||||
(max.y + min.y) * 0.5f,
|
||||
(max.z + min.z) * 0.5f);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::Radius
|
||||
//
|
||||
|
||||
float kexBBox::Radius(void) const
|
||||
{
|
||||
int i;
|
||||
float r = 0;
|
||||
float r1;
|
||||
float r2;
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
r1 = kexMath::Fabs(min[i]);
|
||||
r2 = kexMath::Fabs(max[i]);
|
||||
|
||||
if(r1 > r2)
|
||||
{
|
||||
r += r1 * r1;
|
||||
}
|
||||
else
|
||||
{
|
||||
r += r2 * r2;
|
||||
}
|
||||
}
|
||||
|
||||
return kexMath::Sqrt(r);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::PointInside
|
||||
//
|
||||
|
||||
bool kexBBox::PointInside(const kexVec3 &vec) const
|
||||
{
|
||||
return !(vec[0] < min[0] || vec[1] < min[1] || vec[2] < min[2] ||
|
||||
vec[0] > max[0] || vec[1] > max[1] || vec[2] > max[2]);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::IntersectingBox
|
||||
//
|
||||
|
||||
bool kexBBox::IntersectingBox(const kexBBox &box) const
|
||||
{
|
||||
return !(box.max[0] < min[0] || box.max[1] < min[1] || box.max[2] < min[2] ||
|
||||
box.min[0] > max[0] || box.min[1] > max[1] || box.min[2] > max[2]);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::IntersectingBox2D
|
||||
//
|
||||
|
||||
bool kexBBox::IntersectingBox2D(const kexBBox &box) const
|
||||
{
|
||||
return !(box.max[0] < min[0] || box.max[2] < min[2] ||
|
||||
box.min[0] > max[0] || box.min[2] > max[2]);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::DistanceToPlane
|
||||
//
|
||||
|
||||
float kexBBox::DistanceToPlane(kexPlane &plane)
|
||||
{
|
||||
kexVec3 c;
|
||||
float distStart;
|
||||
float distEnd;
|
||||
float dist = 0;
|
||||
|
||||
c = Center();
|
||||
|
||||
distStart = plane.Distance(c);
|
||||
distEnd = kexMath::Fabs((max.x - c.x) * plane.a) +
|
||||
kexMath::Fabs((max.y - c.y) * plane.b) +
|
||||
kexMath::Fabs((max.z - c.z) * plane.c);
|
||||
|
||||
dist = distStart - distEnd;
|
||||
|
||||
if(dist > 0)
|
||||
{
|
||||
// in front
|
||||
return dist;
|
||||
}
|
||||
|
||||
dist = distStart + distEnd;
|
||||
|
||||
if(dist < 0)
|
||||
{
|
||||
// behind
|
||||
return dist;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator+
|
||||
//
|
||||
|
||||
kexBBox kexBBox::operator+(const float radius) const
|
||||
{
|
||||
kexVec3 vmin = min;
|
||||
kexVec3 vmax = max;
|
||||
|
||||
vmin.x -= radius;
|
||||
vmin.y -= radius;
|
||||
vmin.z -= radius;
|
||||
|
||||
vmax.x += radius;
|
||||
vmax.y += radius;
|
||||
vmax.z += radius;
|
||||
|
||||
return kexBBox(vmin, vmax);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator+=
|
||||
//
|
||||
|
||||
kexBBox &kexBBox::operator+=(const float radius)
|
||||
{
|
||||
min.x -= radius;
|
||||
min.y -= radius;
|
||||
min.z -= radius;
|
||||
max.x += radius;
|
||||
max.y += radius;
|
||||
max.z += radius;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator+
|
||||
//
|
||||
|
||||
kexBBox kexBBox::operator+(const kexVec3 &vec) const
|
||||
{
|
||||
kexVec3 vmin = min;
|
||||
kexVec3 vmax = max;
|
||||
|
||||
vmin.x += vec.x;
|
||||
vmin.y += vec.y;
|
||||
vmin.z += vec.z;
|
||||
|
||||
vmax.x += vec.x;
|
||||
vmax.y += vec.y;
|
||||
vmax.z += vec.z;
|
||||
|
||||
return kexBBox(vmin, vmax);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator-
|
||||
//
|
||||
|
||||
kexBBox kexBBox::operator-(const float radius) const
|
||||
{
|
||||
kexVec3 vmin = min;
|
||||
kexVec3 vmax = max;
|
||||
|
||||
vmin.x += radius;
|
||||
vmin.y += radius;
|
||||
vmin.z += radius;
|
||||
|
||||
vmax.x -= radius;
|
||||
vmax.y -= radius;
|
||||
vmax.z -= radius;
|
||||
|
||||
return kexBBox(vmin, vmax);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator-
|
||||
//
|
||||
|
||||
kexBBox kexBBox::operator-(const kexVec3 &vec) const
|
||||
{
|
||||
kexVec3 vmin = min;
|
||||
kexVec3 vmax = max;
|
||||
|
||||
vmin.x -= vec.x;
|
||||
vmin.y -= vec.y;
|
||||
vmin.z -= vec.z;
|
||||
|
||||
vmax.x -= vec.x;
|
||||
vmax.y -= vec.y;
|
||||
vmax.z -= vec.z;
|
||||
|
||||
return kexBBox(vmin, vmax);
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator-=
|
||||
//
|
||||
|
||||
kexBBox &kexBBox::operator-=(const float radius)
|
||||
{
|
||||
min.x += radius;
|
||||
min.y += radius;
|
||||
min.z += radius;
|
||||
max.x -= radius;
|
||||
max.y -= radius;
|
||||
max.z -= radius;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator*
|
||||
//
|
||||
|
||||
kexBBox kexBBox::operator*(const kexMatrix &matrix) const
|
||||
{
|
||||
kexVec3 c = Center();
|
||||
kexVec3 ct = c * matrix;
|
||||
kexBBox box(ct, ct);
|
||||
|
||||
kexMatrix mtx(matrix);
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
mtx.vectors[i].x = kexMath::Fabs(mtx.vectors[i].x);
|
||||
mtx.vectors[i].y = kexMath::Fabs(mtx.vectors[i].y);
|
||||
mtx.vectors[i].z = kexMath::Fabs(mtx.vectors[i].z);
|
||||
}
|
||||
|
||||
kexVec3 ht = (max - c) * mtx;
|
||||
box.min -= ht;
|
||||
box.max += ht;
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator*=
|
||||
//
|
||||
|
||||
kexBBox &kexBBox::operator*=(const kexMatrix &matrix)
|
||||
{
|
||||
kexVec3 c = Center();
|
||||
kexVec3 ct = c * matrix;
|
||||
|
||||
kexMatrix mtx(matrix);
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
mtx.vectors[i].x = kexMath::Fabs(mtx.vectors[i].x);
|
||||
mtx.vectors[i].y = kexMath::Fabs(mtx.vectors[i].y);
|
||||
mtx.vectors[i].z = kexMath::Fabs(mtx.vectors[i].z);
|
||||
}
|
||||
|
||||
kexVec3 ht = (max - c) * mtx;
|
||||
|
||||
min = (ct - ht);
|
||||
max = (ct + ht);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator*
|
||||
//
|
||||
|
||||
kexBBox kexBBox::operator*(const kexVec3 &vec) const
|
||||
{
|
||||
kexBBox box = *this;
|
||||
|
||||
if(vec.x < 0) { box.min.x += (vec.x-1); }
|
||||
else { box.max.x += (vec.x+1); }
|
||||
if(vec.y < 0) { box.min.y += (vec.y-1); }
|
||||
else { box.max.y += (vec.y+1); }
|
||||
if(vec.z < 0) { box.min.z += (vec.z-1); }
|
||||
else { box.max.z += (vec.z+1); }
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator*=
|
||||
//
|
||||
|
||||
kexBBox &kexBBox::operator*=(const kexVec3 &vec)
|
||||
{
|
||||
if(vec.x < 0) { min.x += (vec.x-1); }
|
||||
else { max.x += (vec.x+1); }
|
||||
if(vec.y < 0) { min.y += (vec.y-1); }
|
||||
else { max.y += (vec.y+1); }
|
||||
if(vec.z < 0) { min.z += (vec.z-1); }
|
||||
else { max.z += (vec.z+1); }
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator=
|
||||
//
|
||||
|
||||
kexBBox &kexBBox::operator=(const kexBBox &bbox)
|
||||
{
|
||||
min = bbox.min;
|
||||
max = bbox.max;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator[]
|
||||
//
|
||||
|
||||
kexVec3 kexBBox::operator[](int index) const
|
||||
{
|
||||
assert(index >= 0 && index < 2);
|
||||
return index == 0 ? min : max;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::operator[]
|
||||
//
|
||||
|
||||
kexVec3 &kexBBox::operator[](int index)
|
||||
{
|
||||
assert(index >= 0 && index < 2);
|
||||
return index == 0 ? min : max;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox:LineIntersect
|
||||
//
|
||||
|
||||
bool kexBBox::LineIntersect(const kexVec3 &start, const kexVec3 &end)
|
||||
{
|
||||
float ld[3];
|
||||
kexVec3 center = Center();
|
||||
kexVec3 extents = max - center;
|
||||
kexVec3 lineDir = (end - start) * 0.5f;
|
||||
kexVec3 lineCenter = lineDir + start;
|
||||
kexVec3 dir = lineCenter - center;
|
||||
|
||||
ld[0] = kexMath::Fabs(lineDir.x);
|
||||
if(kexMath::Fabs(dir.x) > extents.x + ld[0]) { return false; }
|
||||
ld[1] = kexMath::Fabs(lineDir.y);
|
||||
if(kexMath::Fabs(dir.y) > extents.y + ld[1]) { return false; }
|
||||
ld[2] = kexMath::Fabs(lineDir.z);
|
||||
if(kexMath::Fabs(dir.z) > extents.z + ld[2]) { return false; }
|
||||
|
||||
kexVec3 cross = lineDir.Cross(dir);
|
||||
|
||||
if(kexMath::Fabs(cross.x) > extents.y * ld[2] + extents.z * ld[1]) { return false; }
|
||||
if(kexMath::Fabs(cross.y) > extents.x * ld[2] + extents.z * ld[0]) { return false; }
|
||||
if(kexMath::Fabs(cross.z) > extents.x * ld[1] + extents.y * ld[0]) { return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::ToPoints
|
||||
//
|
||||
// Assumes points is an array of 24
|
||||
//
|
||||
|
||||
void kexBBox::ToPoints(float *points) const
|
||||
{
|
||||
points[0 * 3 + 0] = max[0];
|
||||
points[0 * 3 + 1] = min[1];
|
||||
points[0 * 3 + 2] = min[2];
|
||||
points[1 * 3 + 0] = max[0];
|
||||
points[1 * 3 + 1] = min[1];
|
||||
points[1 * 3 + 2] = max[2];
|
||||
points[2 * 3 + 0] = min[0];
|
||||
points[2 * 3 + 1] = min[1];
|
||||
points[2 * 3 + 2] = max[2];
|
||||
points[3 * 3 + 0] = min[0];
|
||||
points[3 * 3 + 1] = min[1];
|
||||
points[3 * 3 + 2] = min[2];
|
||||
points[4 * 3 + 0] = max[0];
|
||||
points[4 * 3 + 1] = max[1];
|
||||
points[4 * 3 + 2] = min[2];
|
||||
points[5 * 3 + 0] = max[0];
|
||||
points[5 * 3 + 1] = max[1];
|
||||
points[5 * 3 + 2] = max[2];
|
||||
points[6 * 3 + 0] = min[0];
|
||||
points[6 * 3 + 1] = max[1];
|
||||
points[6 * 3 + 2] = max[2];
|
||||
points[7 * 3 + 0] = min[0];
|
||||
points[7 * 3 + 1] = max[1];
|
||||
points[7 * 3 + 2] = min[2];
|
||||
}
|
||||
|
||||
//
|
||||
// kexBBox::ToVectors
|
||||
//
|
||||
// Assumes vectors is an array of 8
|
||||
//
|
||||
|
||||
void kexBBox::ToVectors(kexVec3 *vectors) const
|
||||
{
|
||||
vectors[0][0] = max[0];
|
||||
vectors[0][1] = min[1];
|
||||
vectors[0][2] = min[2];
|
||||
vectors[1][0] = max[0];
|
||||
vectors[1][1] = min[1];
|
||||
vectors[1][2] = max[2];
|
||||
vectors[2][0] = min[0];
|
||||
vectors[2][1] = min[1];
|
||||
vectors[2][2] = max[2];
|
||||
vectors[3][0] = min[0];
|
||||
vectors[3][1] = min[1];
|
||||
vectors[3][2] = min[2];
|
||||
vectors[4][0] = max[0];
|
||||
vectors[4][1] = max[1];
|
||||
vectors[4][2] = min[2];
|
||||
vectors[5][0] = max[0];
|
||||
vectors[5][1] = max[1];
|
||||
vectors[5][2] = max[2];
|
||||
vectors[6][0] = min[0];
|
||||
vectors[6][1] = max[1];
|
||||
vectors[6][2] = max[2];
|
||||
vectors[7][0] = min[0];
|
||||
vectors[7][1] = max[1];
|
||||
vectors[7][2] = min[2];
|
||||
}
|
99
src/lightmap/kexlib/math/mathlib.cpp
Normal file
99
src/lightmap/kexlib/math/mathlib.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Math functions
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "lightmap/common.h"
|
||||
#include "mathlib.h"
|
||||
|
||||
//
|
||||
// kexMath::RoundPowerOfTwo
|
||||
//
|
||||
|
||||
int kexMath::RoundPowerOfTwo(int x)
|
||||
{
|
||||
int mask = 1;
|
||||
|
||||
while(mask < 0x40000000)
|
||||
{
|
||||
if(x == mask || (x & (mask-1)) == x)
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::CubicCurve
|
||||
//
|
||||
|
||||
void kexMath::CubicCurve(const kexVec3 &start, const kexVec3 &end, const float time,
|
||||
const kexVec3 &point, kexVec3 *vec)
|
||||
{
|
||||
int i;
|
||||
float xyz[3];
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
xyz[i] = kexMath::Pow(1-time, 2) * start[i] +
|
||||
(2 * (1-time)) * time * point[i] + kexMath::Pow(time, 2) * end[i];
|
||||
}
|
||||
|
||||
vec->x = xyz[0];
|
||||
vec->y = xyz[1];
|
||||
vec->z = xyz[2];
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::QuadraticCurve
|
||||
//
|
||||
|
||||
void kexMath::QuadraticCurve(const kexVec3 &start, const kexVec3 &end, const float time,
|
||||
const kexVec3 &pt1, const kexVec3 &pt2, kexVec3 *vec)
|
||||
{
|
||||
int i;
|
||||
float xyz[3];
|
||||
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
xyz[i] = kexMath::Pow(1-time, 3) * start[i] + (3 * kexMath::Pow(1-time, 2)) *
|
||||
time * pt1[i] + (3 * (1-time)) * kexMath::Pow(time, 2) * pt2[i] +
|
||||
kexMath::Pow(time, 3) * end[i];
|
||||
}
|
||||
|
||||
vec->x = xyz[0];
|
||||
vec->y = xyz[1];
|
||||
vec->z = xyz[2];
|
||||
}
|
||||
|
661
src/lightmap/kexlib/math/mathlib.h
Normal file
661
src/lightmap/kexlib/math/mathlib.h
Normal file
|
@ -0,0 +1,661 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __MATHLIB_H__
|
||||
#define __MATHLIB_H__
|
||||
|
||||
#include <math.h>
|
||||
#include "lightmap/common.h"
|
||||
|
||||
#ifdef M_PI
|
||||
#undef M_PI
|
||||
#endif
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795f
|
||||
#define M_RAD (M_PI / 180.0f)
|
||||
#define M_DEG (180.0f / M_PI)
|
||||
#define M_INFINITY 1e30f
|
||||
|
||||
#define DEG2RAD(x) ((x) * M_RAD)
|
||||
#define RAD2DEG(x) ((x) * M_DEG)
|
||||
|
||||
#define FLOATSIGNBIT(f) (reinterpret_cast<const unsigned int&>(f) >> 31)
|
||||
|
||||
class kexVec2;
|
||||
class kexVec3;
|
||||
class kexVec4;
|
||||
class kexMatrix;
|
||||
class kexAngle;
|
||||
class kexStr;
|
||||
|
||||
class kexMath
|
||||
{
|
||||
public:
|
||||
static float Sin(float x);
|
||||
static float Cos(float x);
|
||||
static float Tan(float x);
|
||||
static float ATan2(float x, float y);
|
||||
static float ACos(float x);
|
||||
static float Sqrt(float x);
|
||||
static float Pow(float x, float y);
|
||||
static float Log(float x);
|
||||
static float Floor(float x);
|
||||
static float Ceil(float x);
|
||||
static float Deg2Rad(float x);
|
||||
static float Rad2Deg(float x);
|
||||
|
||||
static int Abs(int x);
|
||||
static float Fabs(float x);
|
||||
static int RoundPowerOfTwo(int x);
|
||||
static float InvSqrt(float x);
|
||||
static void Clamp(float &f, const float min, const float max);
|
||||
static void Clamp(int &i, const int min, const int max);
|
||||
static void Clamp(byte &b, const byte min, const byte max);
|
||||
static void Clamp(kexVec3 &f, const float min, const float max);
|
||||
|
||||
static void CubicCurve(const kexVec3 &start, const kexVec3 &end, const float time,
|
||||
const kexVec3 &point, kexVec3 *vec);
|
||||
static void QuadraticCurve(const kexVec3 &start, const kexVec3 &end, const float time,
|
||||
const kexVec3 &pt1, const kexVec3 &pt2, kexVec3 *vec);
|
||||
};
|
||||
|
||||
class kexRand
|
||||
{
|
||||
public:
|
||||
static void SetSeed(const int randSeed);
|
||||
static int SysRand(void);
|
||||
static int Int(void);
|
||||
static int Max(const int max);
|
||||
static float Float(void);
|
||||
static float CFloat(void);
|
||||
|
||||
private:
|
||||
static int seed;
|
||||
};
|
||||
|
||||
class kexQuat
|
||||
{
|
||||
public:
|
||||
kexQuat(void);
|
||||
|
||||
explicit kexQuat(const float angle, const float x, const float y, const float z);
|
||||
explicit kexQuat(const float angle, kexVec3 &vector);
|
||||
explicit kexQuat(const float angle, const kexVec3 &vector);
|
||||
|
||||
void Set(const float x, const float y, const float z, const float w);
|
||||
void Clear(void);
|
||||
float Dot(const kexQuat &quat) const;
|
||||
float UnitSq(void) const;
|
||||
float Unit(void) const;
|
||||
kexQuat &Normalize(void);
|
||||
kexQuat Slerp(const kexQuat &quat, float movement) const;
|
||||
kexQuat RotateFrom(const kexVec3 &location, const kexVec3 &target, float maxAngle);
|
||||
kexQuat Inverse(void) const;
|
||||
|
||||
kexQuat operator+(const kexQuat &quat);
|
||||
kexQuat &operator+=(const kexQuat &quat);
|
||||
kexQuat operator-(const kexQuat &quat);
|
||||
kexQuat &operator-=(const kexQuat &quat);
|
||||
kexQuat operator*(const kexQuat &quat);
|
||||
kexQuat operator*(const float val) const;
|
||||
kexQuat &operator*=(const kexQuat &quat);
|
||||
kexQuat &operator*=(const float val);
|
||||
kexQuat &operator=(const kexQuat &quat);
|
||||
kexQuat &operator=(const kexVec4 &vec);
|
||||
kexQuat &operator=(const float *vecs);
|
||||
kexVec3 operator|(const kexVec3 &vector);
|
||||
|
||||
const kexVec3 &ToVec3(void) const;
|
||||
kexVec3 &ToVec3(void);
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
class kexVec2
|
||||
{
|
||||
public:
|
||||
kexVec2(void);
|
||||
explicit kexVec2(const float x, const float y);
|
||||
|
||||
void Set(const float x, const float y);
|
||||
void Clear(void);
|
||||
float Dot(const kexVec2 &vec) const;
|
||||
static float Dot(const kexVec2 &vec1, const kexVec2 &vec2);
|
||||
float CrossScalar(const kexVec2 &vec) const;
|
||||
kexVec2 Cross(const kexVec2 &vec) const;
|
||||
kexVec2 &Cross(const kexVec2 &vec1, const kexVec2 &vec2);
|
||||
float Dot(const kexVec3 &vec) const;
|
||||
static float Dot(const kexVec3 &vec1, const kexVec3 &vec2);
|
||||
kexVec2 Cross(const kexVec3 &vec) const;
|
||||
kexVec2 &Cross(const kexVec3 &vec1, const kexVec3 &vec2);
|
||||
float UnitSq(void) const;
|
||||
float Unit(void) const;
|
||||
float DistanceSq(const kexVec2 &vec) const;
|
||||
float Distance(const kexVec2 &vec) const;
|
||||
kexVec2 &Normalize(void);
|
||||
kexVec2 Lerp(const kexVec2 &next, float movement) const;
|
||||
kexVec2 &Lerp(const kexVec2 &next, const float movement);
|
||||
kexVec2 &Lerp(const kexVec2 &start, const kexVec2 &next, float movement);
|
||||
kexStr ToString(void) const;
|
||||
float ToYaw(void) const;
|
||||
float *ToFloatPtr(void);
|
||||
kexVec3 ToVec3(void);
|
||||
|
||||
kexVec2 operator+(const kexVec2 &vec);
|
||||
kexVec2 operator+(const kexVec2 &vec) const;
|
||||
kexVec2 operator+(kexVec2 &vec);
|
||||
kexVec2 operator-(void) const;
|
||||
kexVec2 operator-(const kexVec2 &vec) const;
|
||||
kexVec2 operator*(const kexVec2 &vec);
|
||||
kexVec2 operator*(const float val);
|
||||
kexVec2 operator*(const float val) const;
|
||||
kexVec2 operator/(const kexVec2 &vec);
|
||||
kexVec2 operator/(const float val);
|
||||
kexVec2 &operator=(kexVec3 &vec);
|
||||
kexVec2 &operator=(const kexVec2 &vec);
|
||||
kexVec2 &operator=(const kexVec3 &vec);
|
||||
kexVec2 &operator=(const float *vecs);
|
||||
kexVec2 &operator+=(const kexVec2 &vec);
|
||||
kexVec2 &operator-=(const kexVec2 &vec);
|
||||
kexVec2 &operator*=(const kexVec2 &vec);
|
||||
kexVec2 &operator*=(const float val);
|
||||
kexVec2 &operator/=(const kexVec2 &vec);
|
||||
kexVec2 &operator/=(const float val);
|
||||
kexVec2 operator*(const kexMatrix &mtx);
|
||||
kexVec2 operator*(const kexMatrix &mtx) const;
|
||||
kexVec2 &operator*=(const kexMatrix &mtx);
|
||||
float operator[](int index) const;
|
||||
float &operator[](int index);
|
||||
bool operator==(const kexVec2 &vec);
|
||||
|
||||
operator float *(void) { return reinterpret_cast<float*>(&x); }
|
||||
|
||||
static kexVec2 vecZero;
|
||||
static const kexVec2 vecRight;
|
||||
static const kexVec2 vecUp;
|
||||
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
class kexVec3
|
||||
{
|
||||
public:
|
||||
kexVec3(void);
|
||||
explicit kexVec3(const float x, const float y, const float z);
|
||||
|
||||
void Set(const float x, const float y, const float z);
|
||||
void Clear(void);
|
||||
float Dot(const kexVec3 &vec) const;
|
||||
static float Dot(const kexVec3 &vec1, const kexVec3 &vec2);
|
||||
kexVec3 Cross(const kexVec3 &vec) const;
|
||||
kexVec3 &Cross(const kexVec3 &vec1, const kexVec3 &vec2);
|
||||
float UnitSq(void) const;
|
||||
float Unit(void) const;
|
||||
float DistanceSq(const kexVec3 &vec) const;
|
||||
float Distance(const kexVec3 &vec) const;
|
||||
kexVec3 &Normalize(void);
|
||||
kexAngle PointAt(kexVec3 &location) const;
|
||||
kexVec3 Lerp(const kexVec3 &next, float movement) const;
|
||||
kexVec3 &Lerp(const kexVec3 &start, const kexVec3 &next, float movement);
|
||||
kexQuat ToQuat(void);
|
||||
float ToYaw(void) const;
|
||||
float ToPitch(void) const;
|
||||
kexStr ToString(void) const;
|
||||
float *ToFloatPtr(void);
|
||||
kexVec2 ToVec2(void);
|
||||
kexVec2 ToVec2(void) const;
|
||||
kexVec3 ScreenProject(kexMatrix &proj, kexMatrix &model,
|
||||
const int width, const int height,
|
||||
const int wx, const int wy);
|
||||
|
||||
kexVec3 operator+(const kexVec3 &vec);
|
||||
kexVec3 operator+(const kexVec3 &vec) const;
|
||||
kexVec3 operator+(kexVec3 &vec);
|
||||
kexVec3 operator-(void) const;
|
||||
kexVec3 operator-(const kexVec3 &vec) const;
|
||||
kexVec3 operator*(const kexVec3 &vec);
|
||||
kexVec3 operator*(const float val);
|
||||
kexVec3 operator*(const float val) const;
|
||||
kexVec3 operator/(const kexVec3 &vec);
|
||||
kexVec3 operator/(const float val);
|
||||
kexVec3 operator*(const kexQuat &quat);
|
||||
kexVec3 operator*(const kexMatrix &mtx);
|
||||
kexVec3 operator*(const kexMatrix &mtx) const;
|
||||
kexVec3 &operator=(const kexVec3 &vec);
|
||||
kexVec3 &operator=(const float *vecs);
|
||||
kexVec3 &operator+=(const kexVec3 &vec);
|
||||
kexVec3 &operator-=(const kexVec3 &vec);
|
||||
kexVec3 &operator*=(const kexVec3 &vec);
|
||||
kexVec3 &operator*=(const float val);
|
||||
kexVec3 &operator/=(const kexVec3 &vec);
|
||||
kexVec3 &operator/=(const float val);
|
||||
kexVec3 &operator*=(const kexQuat &quat);
|
||||
kexVec3 &operator*=(const kexMatrix &mtx);
|
||||
float operator[](int index) const;
|
||||
float &operator[](int index);
|
||||
|
||||
operator float *(void) { return reinterpret_cast<float*>(&x); }
|
||||
|
||||
static const kexVec3 vecForward;
|
||||
static const kexVec3 vecUp;
|
||||
static const kexVec3 vecRight;
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
class kexVec4
|
||||
{
|
||||
public:
|
||||
kexVec4(void);
|
||||
explicit kexVec4(const float x, const float y, const float z, const float w);
|
||||
|
||||
void Set(const float x, const float y, const float z, const float w);
|
||||
void Clear(void);
|
||||
float *ToFloatPtr(void);
|
||||
|
||||
const kexVec3 &ToVec3(void) const;
|
||||
kexVec3 &ToVec3(void);
|
||||
kexVec4 operator|(const kexMatrix &mtx);
|
||||
kexVec4 &operator|=(const kexMatrix &mtx);
|
||||
float operator[](int index) const;
|
||||
float &operator[](int index);
|
||||
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
class kexMatrix
|
||||
{
|
||||
public:
|
||||
kexMatrix(void);
|
||||
kexMatrix(const kexMatrix &mtx);
|
||||
kexMatrix(const float x, const float y, const float z);
|
||||
kexMatrix(const kexQuat &quat);
|
||||
kexMatrix(const float angle, const int axis);
|
||||
|
||||
kexMatrix &Identity(void);
|
||||
kexMatrix &Identity(const float x, const float y, const float z);
|
||||
kexMatrix &SetTranslation(const float x, const float y, const float z);
|
||||
kexMatrix &SetTranslation(const kexVec3 &vector);
|
||||
kexMatrix &AddTranslation(const float x, const float y, const float z);
|
||||
kexMatrix &AddTranslation(const kexVec3 &vector);
|
||||
kexMatrix &Scale(const float x, const float y, const float z);
|
||||
kexMatrix &Scale(const kexVec3 &vector);
|
||||
static kexMatrix Scale(const kexMatrix &mtx, const float x, const float y, const float z);
|
||||
kexMatrix &Transpose(void);
|
||||
static kexMatrix Transpose(const kexMatrix &mtx);
|
||||
static kexMatrix Invert(kexMatrix &mtx);
|
||||
kexQuat ToQuat(void);
|
||||
float *ToFloatPtr(void);
|
||||
void SetViewProjection(float aspect, float fov, float zNear, float zFar);
|
||||
void SetOrtho(float left, float right,
|
||||
float bottom, float top,
|
||||
float zNear, float zFar);
|
||||
|
||||
kexMatrix operator*(const kexVec3 &vector);
|
||||
kexMatrix &operator*=(const kexVec3 &vector);
|
||||
kexMatrix operator*(const kexMatrix &matrix);
|
||||
kexMatrix &operator*=(const kexMatrix &matrix);
|
||||
friend kexMatrix operator*(const kexMatrix &m1, const kexMatrix &m2);
|
||||
kexMatrix &operator=(const kexMatrix &matrix);
|
||||
kexMatrix &operator=(const float *m);
|
||||
kexMatrix operator|(const kexMatrix &matrix);
|
||||
|
||||
kexVec4 vectors[4];
|
||||
};
|
||||
|
||||
class kexPluecker
|
||||
{
|
||||
public:
|
||||
kexPluecker(void);
|
||||
kexPluecker(const kexVec3 &start, const kexVec3 &end, bool bRay = false);
|
||||
|
||||
void Clear(void);
|
||||
void SetLine(const kexVec3 &start, const kexVec3 &end);
|
||||
void SetRay(const kexVec3 &start, const kexVec3 &dir);
|
||||
float InnerProduct(const kexPluecker &pluecker) const;
|
||||
|
||||
float p[6];
|
||||
};
|
||||
|
||||
class kexPlane
|
||||
{
|
||||
public:
|
||||
kexPlane(void);
|
||||
kexPlane(const float a, const float b, const float c, const float d);
|
||||
kexPlane(const kexVec3 &pt1, const kexVec3 &pt2, const kexVec3 &pt3);
|
||||
kexPlane(const kexVec3 &normal, const kexVec3 &point);
|
||||
kexPlane(const kexPlane &plane);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AXIS_YZ = 0,
|
||||
AXIS_XZ,
|
||||
AXIS_XY
|
||||
} planeAxis_t;
|
||||
|
||||
const kexVec3 &Normal(void) const;
|
||||
kexVec3 &Normal(void);
|
||||
kexPlane &SetNormal(const kexVec3 &normal);
|
||||
kexPlane &SetNormal(const kexVec3 &pt1, const kexVec3 &pt2, const kexVec3 &pt3);
|
||||
float Distance(const kexVec3 &point);
|
||||
kexPlane &SetDistance(const kexVec3 &point);
|
||||
bool IsFacing(const float yaw);
|
||||
float ToYaw(void);
|
||||
float ToPitch(void);
|
||||
kexQuat ToQuat(void);
|
||||
const kexVec4 &ToVec4(void) const;
|
||||
kexVec4 &ToVec4(void);
|
||||
const planeAxis_t BestAxis(void) const;
|
||||
kexVec3 GetInclination(void);
|
||||
|
||||
kexPlane &operator|(const kexQuat &quat);
|
||||
kexPlane &operator|=(const kexQuat &quat);
|
||||
kexPlane &operator|(const kexMatrix &mtx);
|
||||
kexPlane &operator|=(const kexMatrix &mtx);
|
||||
|
||||
float a;
|
||||
float b;
|
||||
float c;
|
||||
float d;
|
||||
};
|
||||
|
||||
class kexAngle
|
||||
{
|
||||
public:
|
||||
kexAngle(void);
|
||||
kexAngle(const float yaw, const float pitch, const float roll);
|
||||
kexAngle(const kexVec3 &vector);
|
||||
kexAngle(const kexAngle &an);
|
||||
|
||||
kexAngle &Round(void);
|
||||
kexAngle &Clamp180(void);
|
||||
kexAngle &Clamp180Invert(void);
|
||||
kexAngle &Clamp180InvertSum(const kexAngle &angle);
|
||||
kexAngle Diff(kexAngle &angle);
|
||||
void ToAxis(kexVec3 *forward, kexVec3 *up, kexVec3 *right);
|
||||
kexVec3 ToForwardAxis(void);
|
||||
kexVec3 ToUpAxis(void);
|
||||
kexVec3 ToRightAxis(void);
|
||||
const kexVec3 &ToVec3(void) const;
|
||||
kexVec3 &ToVec3(void);
|
||||
kexQuat ToQuat(void);
|
||||
|
||||
kexAngle operator+(const kexAngle &angle);
|
||||
kexAngle operator-(const kexAngle &angle);
|
||||
kexAngle &operator+=(const kexAngle &angle);
|
||||
kexAngle &operator-=(const kexAngle &angle);
|
||||
kexAngle &operator=(const kexAngle &angle);
|
||||
kexAngle &operator=(const kexVec3 &vector);
|
||||
kexAngle &operator=(const float *vecs);
|
||||
kexAngle operator-(void);
|
||||
float operator[](int index) const;
|
||||
float &operator[](int index);
|
||||
|
||||
float yaw;
|
||||
float pitch;
|
||||
float roll;
|
||||
};
|
||||
|
||||
class kexBBox
|
||||
{
|
||||
public:
|
||||
kexBBox(void);
|
||||
explicit kexBBox(const kexVec3 &vMin, const kexVec3 &vMax);
|
||||
|
||||
void Clear(void);
|
||||
kexVec3 Center(void) const;
|
||||
float Radius(void) const;
|
||||
void AddPoint(const kexVec3 &vec);
|
||||
bool PointInside(const kexVec3 &vec) const;
|
||||
bool IntersectingBox(const kexBBox &box) const;
|
||||
bool IntersectingBox2D(const kexBBox &box) const;
|
||||
float DistanceToPlane(kexPlane &plane);
|
||||
bool LineIntersect(const kexVec3 &start, const kexVec3 &end);
|
||||
void ToPoints(float *points) const;
|
||||
void ToVectors(kexVec3 *vectors) const;
|
||||
|
||||
kexBBox operator+(const float radius) const;
|
||||
kexBBox &operator+=(const float radius);
|
||||
kexBBox operator+(const kexVec3 &vec) const;
|
||||
kexBBox operator-(const float radius) const;
|
||||
kexBBox operator-(const kexVec3 &vec) const;
|
||||
kexBBox &operator-=(const float radius);
|
||||
kexBBox operator*(const kexMatrix &matrix) const;
|
||||
kexBBox &operator*=(const kexMatrix &matrix);
|
||||
kexBBox operator*(const kexVec3 &vec) const;
|
||||
kexBBox &operator*=(const kexVec3 &vec);
|
||||
kexBBox &operator=(const kexBBox &bbox);
|
||||
kexVec3 operator[](int index) const;
|
||||
kexVec3 &operator[](int index);
|
||||
|
||||
kexVec3 min;
|
||||
kexVec3 max;
|
||||
};
|
||||
|
||||
//
|
||||
// kexMath::Sin
|
||||
//
|
||||
|
||||
d_inline float kexMath::Sin(float x)
|
||||
{
|
||||
return sinf(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Cos
|
||||
//
|
||||
|
||||
d_inline float kexMath::Cos(float x)
|
||||
{
|
||||
return cosf(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Tan
|
||||
//
|
||||
|
||||
d_inline float kexMath::Tan(float x)
|
||||
{
|
||||
return tanf(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::ATan2
|
||||
//
|
||||
|
||||
d_inline float kexMath::ATan2(float x, float y)
|
||||
{
|
||||
return atan2f(x, y);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::ACos
|
||||
//
|
||||
|
||||
d_inline float kexMath::ACos(float x)
|
||||
{
|
||||
return acosf(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Sqrt
|
||||
//
|
||||
|
||||
d_inline float kexMath::Sqrt(float x)
|
||||
{
|
||||
return x * InvSqrt(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Pow
|
||||
//
|
||||
|
||||
d_inline float kexMath::Pow(float x, float y)
|
||||
{
|
||||
return powf(x, y);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Log
|
||||
//
|
||||
|
||||
d_inline float kexMath::Log(float x)
|
||||
{
|
||||
return logf(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Floor
|
||||
//
|
||||
|
||||
d_inline float kexMath::Floor(float x)
|
||||
{
|
||||
return floorf(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Ceil
|
||||
//
|
||||
|
||||
d_inline float kexMath::Ceil(float x)
|
||||
{
|
||||
return ceilf(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Deg2Rad
|
||||
//
|
||||
|
||||
d_inline float kexMath::Deg2Rad(float x)
|
||||
{
|
||||
return DEG2RAD(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Rad2Deg
|
||||
//
|
||||
|
||||
d_inline float kexMath::Rad2Deg(float x)
|
||||
{
|
||||
return RAD2DEG(x);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Abs
|
||||
//
|
||||
|
||||
d_inline int kexMath::Abs(int x)
|
||||
{
|
||||
int y = x >> 31;
|
||||
return ((x ^ y) - y);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Fabs
|
||||
//
|
||||
|
||||
d_inline float kexMath::Fabs(float x)
|
||||
{
|
||||
int tmp = *reinterpret_cast<int*>(&x);
|
||||
tmp &= 0x7FFFFFFF;
|
||||
return *reinterpret_cast<float*>(&tmp);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::InvSqrt
|
||||
//
|
||||
|
||||
d_inline float kexMath::InvSqrt(float x)
|
||||
{
|
||||
unsigned int i;
|
||||
float r;
|
||||
float y;
|
||||
|
||||
y = x * 0.5f;
|
||||
i = *reinterpret_cast<unsigned int*>(&x);
|
||||
i = 0x5f3759df - (i >> 1);
|
||||
r = *reinterpret_cast<float*>(&i);
|
||||
r = r * (1.5f - r * r * y);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Clamp
|
||||
//
|
||||
|
||||
d_inline void kexMath::Clamp(float &f, const float min, const float max)
|
||||
{
|
||||
if(f < min) { f = min; }
|
||||
if(f > max) { f = max; }
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Clamp
|
||||
//
|
||||
|
||||
d_inline void kexMath::Clamp(byte &b, const byte min, const byte max)
|
||||
{
|
||||
if(b < min) { b = min; }
|
||||
if(b > max) { b = max; }
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Clamp
|
||||
//
|
||||
|
||||
d_inline void kexMath::Clamp(int &i, const int min, const int max)
|
||||
{
|
||||
if(i < min) { i = min; }
|
||||
if(i > max) { i = max; }
|
||||
}
|
||||
|
||||
//
|
||||
// kexMath::Clamp
|
||||
//
|
||||
|
||||
d_inline void kexMath::Clamp(kexVec3 &v, const float min, const float max)
|
||||
{
|
||||
if(v.x < min) { v.x = min; }
|
||||
if(v.x > max) { v.x = max; }
|
||||
if(v.y < min) { v.y = min; }
|
||||
if(v.y > max) { v.y = max; }
|
||||
if(v.z < min) { v.z = min; }
|
||||
if(v.z > max) { v.z = max; }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
717
src/lightmap/kexlib/math/matrix.cpp
Normal file
717
src/lightmap/kexlib/math/matrix.cpp
Normal file
|
@ -0,0 +1,717 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Matrix (left handed) operations
|
||||
//
|
||||
// Reference:
|
||||
// _________________
|
||||
// | 0 4 8 12 |
|
||||
// | 1 5 9 13 |
|
||||
// | 2 6 10 14 |
|
||||
// | 3 7 11 15 |
|
||||
// _________________
|
||||
//
|
||||
// translation
|
||||
// _________________
|
||||
// | 0 4 8 x |
|
||||
// | 1 5 9 y |
|
||||
// | 2 6 10 z |
|
||||
// | 3 7 11 15 |
|
||||
// _________________
|
||||
//
|
||||
// rotation x
|
||||
// _________________
|
||||
// |(1) 4 8 x |
|
||||
// | 1 xc -xs y |
|
||||
// | 2 xs xs z |
|
||||
// | 3 7 11 (1) |
|
||||
// _________________
|
||||
//
|
||||
// rotation y
|
||||
// _________________
|
||||
// | yc 4 ys 12 |
|
||||
// | 1 (1) 9 13 |
|
||||
// |-ys 6 yc 14 |
|
||||
// | 3 7 11 (1) |
|
||||
// _________________
|
||||
//
|
||||
// rotation z
|
||||
// _________________
|
||||
// | zc -zs 8 12 |
|
||||
// | zs zc 9 13 |
|
||||
// | 2 6 (1) 14 |
|
||||
// | 3 7 11 (1) |
|
||||
// _________________
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
//
|
||||
// kexMatrix::kexMatrix
|
||||
//
|
||||
|
||||
kexMatrix::kexMatrix(void)
|
||||
{
|
||||
Identity();
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::kexMatrix
|
||||
//
|
||||
|
||||
kexMatrix::kexMatrix(const kexMatrix &mtx)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
vectors[i].x = mtx.vectors[i].x;
|
||||
vectors[i].y = mtx.vectors[i].y;
|
||||
vectors[i].z = mtx.vectors[i].z;
|
||||
vectors[i].w = mtx.vectors[i].w;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::kexMatrix
|
||||
//
|
||||
|
||||
kexMatrix::kexMatrix(const float x, const float y, const float z)
|
||||
{
|
||||
Identity(x, y, z);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::kexMatrix
|
||||
//
|
||||
|
||||
kexMatrix::kexMatrix(const kexQuat &quat)
|
||||
{
|
||||
float xx = quat.x * quat.x;
|
||||
float yx = quat.y * quat.x;
|
||||
float zx = quat.z * quat.x;
|
||||
float wx = quat.w * quat.x;
|
||||
float yy = quat.y * quat.y;
|
||||
float zy = quat.z * quat.y;
|
||||
float wy = quat.w * quat.y;
|
||||
float zz = quat.z * quat.z;
|
||||
float wz = quat.w * quat.z;
|
||||
float ww = quat.w * quat.w;
|
||||
|
||||
vectors[0].Set(
|
||||
((ww + xx) - yy) - zz,
|
||||
(wz + wz) + (yx + yx),
|
||||
(zx + zx) - (wy + wy),
|
||||
0);
|
||||
vectors[1].Set(
|
||||
(yx + yx) - (wz + wz),
|
||||
(yy + (ww - xx)) - zz,
|
||||
(wx + wx) + (zy + zy),
|
||||
0);
|
||||
vectors[2].Set(
|
||||
(wy + wy + zx + zx),
|
||||
(zy + zy) - (wx + wx),
|
||||
((ww - xx) - yy) + zz,
|
||||
0);
|
||||
vectors[3].Set(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::kexMatrix
|
||||
//
|
||||
|
||||
kexMatrix::kexMatrix(const float angle, const int axis)
|
||||
{
|
||||
float s;
|
||||
float c;
|
||||
|
||||
s = kexMath::Sin(angle);
|
||||
c = kexMath::Cos(angle);
|
||||
|
||||
Identity();
|
||||
|
||||
switch(axis)
|
||||
{
|
||||
case 0:
|
||||
this->vectors[0].x = c;
|
||||
this->vectors[0].z = -s;
|
||||
this->vectors[3].x = s;
|
||||
this->vectors[3].z = c;
|
||||
break;
|
||||
case 1:
|
||||
this->vectors[1].y = c;
|
||||
this->vectors[1].z = s;
|
||||
this->vectors[2].y = -s;
|
||||
this->vectors[2].z = c;
|
||||
break;
|
||||
case 2:
|
||||
this->vectors[0].x = c;
|
||||
this->vectors[0].y = s;
|
||||
this->vectors[1].x = -s;
|
||||
this->vectors[1].y = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Identity
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::Identity(void)
|
||||
{
|
||||
vectors[0].Set(1, 0, 0, 0);
|
||||
vectors[1].Set(0, 1, 0, 0);
|
||||
vectors[2].Set(0, 0, 1, 0);
|
||||
vectors[3].Set(0, 0, 0, 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Identity
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::Identity(const float x, const float y, const float z)
|
||||
{
|
||||
vectors[0].Set(x, 0, 0, 0);
|
||||
vectors[1].Set(0, y, 0, 0);
|
||||
vectors[2].Set(0, 0, z, 0);
|
||||
vectors[3].Set(0, 0, 0, 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::SetTranslation
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::SetTranslation(const float x, const float y, const float z)
|
||||
{
|
||||
vectors[3].ToVec3().Set(x, y, z);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::SetTranslation
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::SetTranslation(const kexVec3 &vector)
|
||||
{
|
||||
vectors[3].ToVec3() = vector;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::AddTranslation
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::AddTranslation(const float x, const float y, const float z)
|
||||
{
|
||||
vectors[3].x += x;
|
||||
vectors[3].y += y;
|
||||
vectors[3].z += z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::AddTranslation
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::AddTranslation(const kexVec3 &vector)
|
||||
{
|
||||
vectors[3].ToVec3() += vector;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Scale
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::Scale(const float x, const float y, const float z)
|
||||
{
|
||||
vectors[0].ToVec3() *= x;
|
||||
vectors[1].ToVec3() *= y;
|
||||
vectors[2].ToVec3() *= z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Scale
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::Scale(const kexVec3 &vector)
|
||||
{
|
||||
vectors[0].ToVec3() *= vector.x;
|
||||
vectors[1].ToVec3() *= vector.y;
|
||||
vectors[2].ToVec3() *= vector.z;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Scale
|
||||
//
|
||||
|
||||
kexMatrix kexMatrix::Scale(const kexMatrix &mtx, const float x, const float y, const float z)
|
||||
{
|
||||
kexMatrix out;
|
||||
|
||||
out.vectors[0].ToVec3() = mtx.vectors[0].ToVec3() * x;
|
||||
out.vectors[1].ToVec3() = mtx.vectors[1].ToVec3() * y;
|
||||
out.vectors[2].ToVec3() = mtx.vectors[2].ToVec3() * z;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Transpose
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::Transpose(void)
|
||||
{
|
||||
kexVec3 v1 = vectors[1].ToVec3();
|
||||
kexVec3 v2 = vectors[2].ToVec3();
|
||||
|
||||
vectors[1].ToVec3() = v2;
|
||||
vectors[2].ToVec3() = v1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Transpose
|
||||
//
|
||||
|
||||
kexMatrix kexMatrix::Transpose(const kexMatrix &mtx)
|
||||
{
|
||||
kexMatrix out;
|
||||
|
||||
out.vectors[0].ToVec3() = mtx.vectors[0].ToVec3();
|
||||
out.vectors[1].ToVec3() = mtx.vectors[2].ToVec3();
|
||||
out.vectors[2].ToVec3() = mtx.vectors[1].ToVec3();
|
||||
out.vectors[3].ToVec3() = mtx.vectors[3].ToVec3();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::Invert
|
||||
//
|
||||
|
||||
kexMatrix kexMatrix::Invert(kexMatrix &mtx)
|
||||
{
|
||||
float d;
|
||||
float *m;
|
||||
|
||||
m = mtx.ToFloatPtr();
|
||||
|
||||
d = m[ 0] * m[10] * m[ 5] -
|
||||
m[ 0] * m[ 9] * m[ 6] -
|
||||
m[ 1] * m[ 4] * m[10] +
|
||||
m[ 2] * m[ 4] * m[ 9] +
|
||||
m[ 1] * m[ 6] * m[ 8] -
|
||||
m[ 2] * m[ 5] * m[ 8];
|
||||
|
||||
if(d != 0.0f)
|
||||
{
|
||||
kexMatrix inv;
|
||||
|
||||
d = (1.0f / d);
|
||||
|
||||
inv.vectors[0].x = ( m[10] * m[ 5] - m[ 9] * m[ 6]) * d;
|
||||
inv.vectors[0].y = -((m[ 1] * m[10] - m[ 2] * m[ 9]) * d);
|
||||
inv.vectors[0].z = ( m[ 1] * m[ 6] - m[ 2] * m[ 5]) * d;
|
||||
inv.vectors[0].w = 0;
|
||||
inv.vectors[1].x = ( m[ 6] * m[ 8] - m[ 4] * m[10]) * d;
|
||||
inv.vectors[1].y = ( m[ 0] * m[10] - m[ 2] * m[ 8]) * d;
|
||||
inv.vectors[1].z = -((m[ 0] * m[ 6] - m[ 2] * m[ 4]) * d);
|
||||
inv.vectors[1].w = 0;
|
||||
inv.vectors[2].x = -((m[ 5] * m[ 8] - m[ 4] * m[ 9]) * d);
|
||||
inv.vectors[2].y = ( m[ 1] * m[ 8] - m[ 0] * m[ 9]) * d;
|
||||
inv.vectors[2].z = -((m[ 1] * m[ 4] - m[ 0] * m[ 5]) * d);
|
||||
inv.vectors[2].w = 0;
|
||||
inv.vectors[3].x = (
|
||||
( m[13] * m[10] - m[14] * m[ 9]) * m[ 4]
|
||||
+ m[14] * m[ 5] * m[ 8]
|
||||
- m[13] * m[ 6] * m[ 8]
|
||||
- m[12] * m[10] * m[ 5]
|
||||
+ m[12] * m[ 9] * m[ 6]) * d;
|
||||
inv.vectors[3].y = (
|
||||
m[ 0] * m[14] * m[ 9]
|
||||
- m[ 0] * m[13] * m[10]
|
||||
- m[14] * m[ 1] * m[ 8]
|
||||
+ m[13] * m[ 2] * m[ 8]
|
||||
+ m[12] * m[ 1] * m[10]
|
||||
- m[12] * m[ 2] * m[ 9]) * d;
|
||||
inv.vectors[3].z = -(
|
||||
( m[ 0] * m[14] * m[ 5]
|
||||
- m[ 0] * m[13] * m[ 6]
|
||||
- m[14] * m[ 1] * m[ 4]
|
||||
+ m[13] * m[ 2] * m[ 4]
|
||||
+ m[12] * m[ 1] * m[ 6]
|
||||
- m[12] * m[ 2] * m[ 5]) * d);
|
||||
inv.vectors[3].w = 1.0f;
|
||||
|
||||
return inv;
|
||||
}
|
||||
|
||||
return mtx;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::SetViewProjection
|
||||
//
|
||||
|
||||
void kexMatrix::SetViewProjection(float aspect, float fov, float zNear, float zFar)
|
||||
{
|
||||
float top = zNear * kexMath::Tan(fov * M_PI / 360.0f);
|
||||
float bottom = -top;
|
||||
float left = bottom * aspect;
|
||||
float right = top * aspect;
|
||||
|
||||
vectors[0].x = (2 * zNear) / (right - left);
|
||||
vectors[1].y = (2 * zNear) / (top - bottom);
|
||||
vectors[3].z = -(2 * zFar * zNear) / (zFar - zNear);
|
||||
|
||||
vectors[2].x = (right + left) / (right - left);
|
||||
vectors[2].y = (top + bottom) / (top - bottom);
|
||||
vectors[2].z = -(zFar + zNear) / (zFar - zNear);
|
||||
|
||||
vectors[0].y = 0;
|
||||
vectors[0].z = 0;
|
||||
vectors[0].w = 0;
|
||||
vectors[1].x = 0;
|
||||
vectors[1].w = 0;
|
||||
vectors[1].z = 0;
|
||||
vectors[2].w = -1;
|
||||
vectors[3].x = 0;
|
||||
vectors[3].y = 0;
|
||||
vectors[3].w = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::SetOrtho
|
||||
//
|
||||
|
||||
void kexMatrix::SetOrtho(float left, float right,
|
||||
float bottom, float top,
|
||||
float zNear, float zFar)
|
||||
{
|
||||
vectors[0].x = 2 / (right - left);
|
||||
vectors[1].y = 2 / (top - bottom);
|
||||
vectors[2].z = -2 / (zFar - zNear);
|
||||
|
||||
vectors[3].x = -(right + left) / (right - left);
|
||||
vectors[3].y = -(top + bottom) / (top - bottom);
|
||||
vectors[3].z = -(zFar + zNear) / (zFar - zNear);
|
||||
vectors[3].w = 1;
|
||||
|
||||
vectors[0].y = 0;
|
||||
vectors[0].z = 0;
|
||||
vectors[0].w = 0;
|
||||
vectors[1].x = 0;
|
||||
vectors[1].z = 0;
|
||||
vectors[1].w = 0;
|
||||
vectors[2].x = 0;
|
||||
vectors[2].y = 0;
|
||||
vectors[2].w = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::ToQuat
|
||||
//
|
||||
|
||||
kexQuat kexMatrix::ToQuat(void)
|
||||
{
|
||||
float t;
|
||||
float d;
|
||||
float mx;
|
||||
float my;
|
||||
float mz;
|
||||
float m21;
|
||||
float m20;
|
||||
float m10;
|
||||
kexQuat q;
|
||||
|
||||
mx = vectors[0][0];
|
||||
my = vectors[1][1];
|
||||
mz = vectors[2][2];
|
||||
|
||||
m21 = (vectors[2][1] - vectors[1][2]);
|
||||
m20 = (vectors[2][0] - vectors[0][2]);
|
||||
m10 = (vectors[1][0] - vectors[0][1]);
|
||||
|
||||
t = 1.0f + mx + my + mz;
|
||||
|
||||
if(t > 0)
|
||||
{
|
||||
d = 0.5f / kexMath::Sqrt(t);
|
||||
q.x = m21 * d;
|
||||
q.y = m20 * d;
|
||||
q.z = m10 * d;
|
||||
q.w = 0.25f / d;
|
||||
}
|
||||
else if(mx > my && mx > mz)
|
||||
{
|
||||
d = kexMath::Sqrt(1.0f + mx - my - mz) * 2;
|
||||
q.x = 0.5f / d;
|
||||
q.y = m10 / d;
|
||||
q.z = m20 / d;
|
||||
q.w = m21 / d;
|
||||
}
|
||||
else if(my > mz)
|
||||
{
|
||||
d = kexMath::Sqrt(1.0f + my - mx - mz) * 2;
|
||||
q.x = m10 / d;
|
||||
q.y = 0.5f / d;
|
||||
q.z = m21 / d;
|
||||
q.w = m20 / d;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = kexMath::Sqrt(1.0f + mz - mx - my) * 2;
|
||||
q.x = m20 / d;
|
||||
q.y = m21 / d;
|
||||
q.z = 0.5f / d;
|
||||
q.w = m10 / d;
|
||||
}
|
||||
|
||||
q.Normalize();
|
||||
return q;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator*
|
||||
//
|
||||
|
||||
kexMatrix kexMatrix::operator*(const kexVec3 &vector)
|
||||
{
|
||||
kexMatrix out(*this);
|
||||
|
||||
out.vectors[3].ToVec3() +=
|
||||
vectors[0].ToVec3() * vector.x +
|
||||
vectors[1].ToVec3() * vector.y +
|
||||
vectors[2].ToVec3() * vector.z;
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator*=
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::operator*=(const kexVec3 &vector)
|
||||
{
|
||||
vectors[3].ToVec3() +=
|
||||
vectors[0].ToVec3() * vector.x +
|
||||
vectors[1].ToVec3() * vector.y +
|
||||
vectors[2].ToVec3() * vector.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::ToFloatPtr
|
||||
//
|
||||
|
||||
float *kexMatrix::ToFloatPtr(void)
|
||||
{
|
||||
return reinterpret_cast<float*>(vectors);
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator*
|
||||
//
|
||||
|
||||
kexMatrix kexMatrix::operator*(const kexMatrix &matrix)
|
||||
{
|
||||
kexMatrix out;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
out.vectors[i].x =
|
||||
vectors[i].x * matrix.vectors[0].x +
|
||||
vectors[i].y * matrix.vectors[1].x +
|
||||
vectors[i].z * matrix.vectors[2].x +
|
||||
vectors[i].w * matrix.vectors[3].x;
|
||||
out.vectors[i].y =
|
||||
vectors[i].x * matrix.vectors[0].y +
|
||||
vectors[i].y * matrix.vectors[1].y +
|
||||
vectors[i].z * matrix.vectors[2].y +
|
||||
vectors[i].w * matrix.vectors[3].y;
|
||||
out.vectors[i].z =
|
||||
vectors[i].x * matrix.vectors[0].z +
|
||||
vectors[i].y * matrix.vectors[1].z +
|
||||
vectors[i].z * matrix.vectors[2].z +
|
||||
vectors[i].w * matrix.vectors[3].z;
|
||||
out.vectors[i].w =
|
||||
vectors[i].x * matrix.vectors[0].w +
|
||||
vectors[i].y * matrix.vectors[1].w +
|
||||
vectors[i].z * matrix.vectors[2].w +
|
||||
vectors[i].w * matrix.vectors[3].w;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator*=
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::operator*=(const kexMatrix &matrix)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
vectors[i].x =
|
||||
vectors[i].x * matrix.vectors[0].x +
|
||||
vectors[i].y * matrix.vectors[1].x +
|
||||
vectors[i].z * matrix.vectors[2].x +
|
||||
vectors[i].w * matrix.vectors[3].x;
|
||||
vectors[i].y =
|
||||
vectors[i].x * matrix.vectors[0].y +
|
||||
vectors[i].y * matrix.vectors[1].y +
|
||||
vectors[i].z * matrix.vectors[2].y +
|
||||
vectors[i].w * matrix.vectors[3].y;
|
||||
vectors[i].z =
|
||||
vectors[i].x * matrix.vectors[0].z +
|
||||
vectors[i].y * matrix.vectors[1].z +
|
||||
vectors[i].z * matrix.vectors[2].z +
|
||||
vectors[i].w * matrix.vectors[3].z;
|
||||
vectors[i].w =
|
||||
vectors[i].x * matrix.vectors[0].w +
|
||||
vectors[i].y * matrix.vectors[1].w +
|
||||
vectors[i].z * matrix.vectors[2].w +
|
||||
vectors[i].w * matrix.vectors[3].w;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator*
|
||||
//
|
||||
|
||||
kexMatrix operator*(const kexMatrix &m1, const kexMatrix &m2)
|
||||
{
|
||||
kexMatrix out;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
out.vectors[i].x =
|
||||
m1.vectors[i].x * m2.vectors[0].x +
|
||||
m1.vectors[i].y * m2.vectors[1].x +
|
||||
m1.vectors[i].z * m2.vectors[2].x +
|
||||
m1.vectors[i].w * m2.vectors[3].x;
|
||||
out.vectors[i].y =
|
||||
m1.vectors[i].x * m2.vectors[0].y +
|
||||
m1.vectors[i].y * m2.vectors[1].y +
|
||||
m1.vectors[i].z * m2.vectors[2].y +
|
||||
m1.vectors[i].w * m2.vectors[3].y;
|
||||
out.vectors[i].z =
|
||||
m1.vectors[i].x * m2.vectors[0].z +
|
||||
m1.vectors[i].y * m2.vectors[1].z +
|
||||
m1.vectors[i].z * m2.vectors[2].z +
|
||||
m1.vectors[i].w * m2.vectors[3].z;
|
||||
out.vectors[i].w =
|
||||
m1.vectors[i].x * m2.vectors[0].w +
|
||||
m1.vectors[i].y * m2.vectors[1].w +
|
||||
m1.vectors[i].z * m2.vectors[2].w +
|
||||
m1.vectors[i].w * m2.vectors[3].w;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator|
|
||||
//
|
||||
|
||||
kexMatrix kexMatrix::operator|(const kexMatrix &matrix)
|
||||
{
|
||||
kexMatrix out;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
out.vectors[i].x =
|
||||
vectors[i].x * matrix.vectors[0].x +
|
||||
vectors[i].y * matrix.vectors[1].x +
|
||||
vectors[i].z * matrix.vectors[2].x;
|
||||
out.vectors[i].y =
|
||||
vectors[i].x * matrix.vectors[0].y +
|
||||
vectors[i].y * matrix.vectors[1].y +
|
||||
vectors[i].z * matrix.vectors[2].y;
|
||||
out.vectors[i].z =
|
||||
vectors[i].x * matrix.vectors[0].z +
|
||||
vectors[i].y * matrix.vectors[1].z +
|
||||
vectors[i].z * matrix.vectors[2].z;
|
||||
}
|
||||
|
||||
out.vectors[3].x =
|
||||
vectors[3].x * matrix.vectors[0].x +
|
||||
vectors[3].y * matrix.vectors[1].x +
|
||||
vectors[3].z * matrix.vectors[2].x + matrix.vectors[3].x;
|
||||
out.vectors[3].y =
|
||||
vectors[3].x * matrix.vectors[0].y +
|
||||
vectors[3].y * matrix.vectors[1].y +
|
||||
vectors[3].z * matrix.vectors[2].y + matrix.vectors[3].y;
|
||||
out.vectors[3].z =
|
||||
vectors[3].x * matrix.vectors[0].z +
|
||||
vectors[3].y * matrix.vectors[1].z +
|
||||
vectors[3].z * matrix.vectors[2].z + matrix.vectors[3].z;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator=
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::operator=(const kexMatrix &matrix)
|
||||
{
|
||||
vectors[0] = matrix.vectors[0];
|
||||
vectors[1] = matrix.vectors[1];
|
||||
vectors[2] = matrix.vectors[2];
|
||||
vectors[3] = matrix.vectors[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexMatrix::operator=
|
||||
//
|
||||
|
||||
kexMatrix &kexMatrix::operator=(const float *m)
|
||||
{
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
for(int j = 0; j < 4; j++)
|
||||
{
|
||||
vectors[i][j] = m[i * 4 + j];
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
251
src/lightmap/kexlib/math/plane.cpp
Normal file
251
src/lightmap/kexlib/math/plane.cpp
Normal file
|
@ -0,0 +1,251 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Plane operations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
//
|
||||
// kexPlane::kexPlane
|
||||
//
|
||||
|
||||
kexPlane::kexPlane(void)
|
||||
{
|
||||
this->a = 0;
|
||||
this->b = 0;
|
||||
this->c = 0;
|
||||
this->d = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::kexPlane
|
||||
//
|
||||
|
||||
kexPlane::kexPlane(const float a, const float b, const float c, const float d)
|
||||
{
|
||||
this->a = a;
|
||||
this->b = b;
|
||||
this->c = c;
|
||||
this->d = d;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::kexPlane
|
||||
//
|
||||
|
||||
kexPlane::kexPlane(const kexVec3 &pt1, const kexVec3 &pt2, const kexVec3 &pt3)
|
||||
{
|
||||
SetNormal(pt1, pt2, pt3);
|
||||
this->d = kexVec3::Dot(pt1, Normal());
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::kexPlane
|
||||
//
|
||||
|
||||
kexPlane::kexPlane(const kexVec3 &normal, const kexVec3 &point)
|
||||
{
|
||||
this->a = normal.x;
|
||||
this->b = normal.y;
|
||||
this->c = normal.z;
|
||||
this->d = point.Dot(normal);
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::kexPlane
|
||||
//
|
||||
|
||||
kexPlane::kexPlane(const kexPlane &plane)
|
||||
{
|
||||
this->a = plane.a;
|
||||
this->b = plane.b;
|
||||
this->c = plane.c;
|
||||
this->d = plane.d;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::SetNormal
|
||||
//
|
||||
|
||||
kexPlane &kexPlane::SetNormal(const kexVec3 &normal)
|
||||
{
|
||||
Normal() = normal;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::SetNormal
|
||||
//
|
||||
|
||||
kexPlane &kexPlane::SetNormal(const kexVec3 &pt1, const kexVec3 &pt2, const kexVec3 &pt3)
|
||||
{
|
||||
Normal() = (pt2 - pt1).Cross(pt3 - pt2).Normalize();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::Normal
|
||||
//
|
||||
|
||||
kexVec3 const &kexPlane::Normal(void) const
|
||||
{
|
||||
return *reinterpret_cast<const kexVec3*>(&a);
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::Normal
|
||||
//
|
||||
|
||||
kexVec3 &kexPlane::Normal(void)
|
||||
{
|
||||
return *reinterpret_cast<kexVec3*>(&a);
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::Distance
|
||||
//
|
||||
|
||||
float kexPlane::Distance(const kexVec3 &point)
|
||||
{
|
||||
return point.Dot(Normal());
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::SetDistance
|
||||
//
|
||||
|
||||
kexPlane &kexPlane::SetDistance(const kexVec3 &point)
|
||||
{
|
||||
this->d = point.Dot(Normal());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::IsFacing
|
||||
//
|
||||
|
||||
bool kexPlane::IsFacing(const float yaw)
|
||||
{
|
||||
return -kexMath::Sin(yaw) * a + -kexMath::Cos(yaw) * b < 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::ToYaw
|
||||
//
|
||||
|
||||
float kexPlane::ToYaw(void)
|
||||
{
|
||||
float d = Normal().Unit();
|
||||
|
||||
if(d != 0)
|
||||
{
|
||||
float phi;
|
||||
phi = kexMath::ACos(b / d);
|
||||
if(a <= 0)
|
||||
{
|
||||
phi = -phi;
|
||||
}
|
||||
|
||||
return phi;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::ToPitch
|
||||
//
|
||||
|
||||
float kexPlane::ToPitch(void)
|
||||
{
|
||||
return kexMath::ACos(kexVec3::vecUp.Dot(Normal()));
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::ToQuat
|
||||
//
|
||||
|
||||
kexQuat kexPlane::ToQuat(void)
|
||||
{
|
||||
kexVec3 cross = kexVec3::vecUp.Cross(Normal()).Normalize();
|
||||
return kexQuat(kexMath::ACos(kexVec3::vecUp.Dot(Normal())), cross);
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::ToVec4
|
||||
//
|
||||
|
||||
kexVec4 const &kexPlane::ToVec4(void) const
|
||||
{
|
||||
return *reinterpret_cast<const kexVec4*>(&a);
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::ToVec4
|
||||
//
|
||||
|
||||
kexVec4 &kexPlane::ToVec4(void)
|
||||
{
|
||||
return *reinterpret_cast<kexVec4*>(&a);
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::BestAxis
|
||||
//
|
||||
|
||||
const kexPlane::planeAxis_t kexPlane::BestAxis(void) const
|
||||
{
|
||||
float na = kexMath::Fabs(a);
|
||||
float nb = kexMath::Fabs(b);
|
||||
float nc = kexMath::Fabs(c);
|
||||
|
||||
// figure out what axis the plane lies on
|
||||
if(na >= nb && na >= nc)
|
||||
{
|
||||
return AXIS_YZ;
|
||||
}
|
||||
else if(nb >= na && nb >= nc)
|
||||
{
|
||||
return AXIS_XZ;
|
||||
}
|
||||
|
||||
return AXIS_XY;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPlane::GetInclination
|
||||
//
|
||||
|
||||
kexVec3 kexPlane::GetInclination(void)
|
||||
{
|
||||
kexVec3 dir = Normal() * kexVec3::vecUp.Dot(Normal());
|
||||
return (kexVec3::vecUp - dir).Normalize();
|
||||
}
|
107
src/lightmap/kexlib/math/pluecker.cpp
Normal file
107
src/lightmap/kexlib/math/pluecker.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Pluecker operations
|
||||
// This stuff makes my brain hurt...
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
//
|
||||
// kexPluecker::kexPluecker
|
||||
//
|
||||
|
||||
kexPluecker::kexPluecker(void)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
//
|
||||
// kexPluecker::kexPluecker
|
||||
//
|
||||
|
||||
kexPluecker::kexPluecker(const kexVec3 &start, const kexVec3 &end, bool bRay)
|
||||
{
|
||||
bRay ? SetRay(start, end) : SetLine(start, end);
|
||||
}
|
||||
|
||||
//
|
||||
// kexPluecker::Clear
|
||||
//
|
||||
|
||||
void kexPluecker::Clear(void)
|
||||
{
|
||||
p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPluecker::SetLine
|
||||
//
|
||||
|
||||
void kexPluecker::SetLine(const kexVec3 &start, const kexVec3 &end)
|
||||
{
|
||||
p[0] = start.x * end.y - end.x * start.y;
|
||||
p[1] = start.x * end.z - end.x * start.z;
|
||||
p[3] = start.y * end.z - end.y * start.z;
|
||||
|
||||
p[2] = start.x - end.x;
|
||||
p[5] = end.y - start.y;
|
||||
p[4] = start.z - end.z;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPluecker::SetRay
|
||||
//
|
||||
|
||||
void kexPluecker::SetRay(const kexVec3 &start, const kexVec3 &dir)
|
||||
{
|
||||
p[0] = start.x * dir.y - dir.x * start.y;
|
||||
p[1] = start.x * dir.z - dir.x * start.z;
|
||||
p[3] = start.y * dir.z - dir.y * start.z;
|
||||
|
||||
p[2] = -dir.x;
|
||||
p[5] = dir.y;
|
||||
p[4] = -dir.z;
|
||||
}
|
||||
|
||||
//
|
||||
// kexPluecker::InnerProduct
|
||||
//
|
||||
|
||||
float kexPluecker::InnerProduct(const kexPluecker &pluecker) const
|
||||
{
|
||||
return
|
||||
p[0] * pluecker.p[4] +
|
||||
p[1] * pluecker.p[5] +
|
||||
p[2] * pluecker.p[3] +
|
||||
p[4] * pluecker.p[0] +
|
||||
p[5] * pluecker.p[1] +
|
||||
p[3] * pluecker.p[2];
|
||||
}
|
446
src/lightmap/kexlib/math/quaternion.cpp
Normal file
446
src/lightmap/kexlib/math/quaternion.cpp
Normal file
|
@ -0,0 +1,446 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Quaternion operations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
//
|
||||
// kexQuat::kexQuat
|
||||
//
|
||||
|
||||
kexQuat::kexQuat(void)
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::kexQuat
|
||||
//
|
||||
|
||||
kexQuat::kexQuat(const float angle, const float x, const float y, const float z)
|
||||
{
|
||||
float s = kexMath::Sin(angle * 0.5f);
|
||||
float c = kexMath::Cos(angle * 0.5f);
|
||||
|
||||
this->x = x * s;
|
||||
this->y = y * s;
|
||||
this->z = z * s;
|
||||
this->w = c;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::kexQuat
|
||||
//
|
||||
|
||||
kexQuat::kexQuat(const float angle, kexVec3 &vector)
|
||||
{
|
||||
float s = kexMath::Sin(angle * 0.5f);
|
||||
float c = kexMath::Cos(angle * 0.5f);
|
||||
|
||||
this->x = vector.x * s;
|
||||
this->y = vector.y * s;
|
||||
this->z = vector.z * s;
|
||||
this->w = c;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::kexQuat
|
||||
//
|
||||
|
||||
kexQuat::kexQuat(const float angle, const kexVec3 &vector)
|
||||
{
|
||||
float s = kexMath::Sin(angle * 0.5f);
|
||||
float c = kexMath::Cos(angle * 0.5f);
|
||||
|
||||
this->x = vector.x * s;
|
||||
this->y = vector.y * s;
|
||||
this->z = vector.z * s;
|
||||
this->w = c;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::Set
|
||||
//
|
||||
|
||||
void kexQuat::Set(const float x, const float y, const float z, const float w)
|
||||
{
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
this->w = w;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::Clear
|
||||
//
|
||||
|
||||
void kexQuat::Clear(void)
|
||||
{
|
||||
x = y = z = 0.0f;
|
||||
w = 1.0f;
|
||||
}
|
||||
|
||||
//
|
||||
// kexVec3::UnitSq
|
||||
//
|
||||
|
||||
float kexQuat::UnitSq(void) const
|
||||
{
|
||||
return x * x + y * y + z * z + w * w;
|
||||
}
|
||||
|
||||
//
|
||||
// kexVec3::Unit
|
||||
//
|
||||
|
||||
float kexQuat::Unit(void) const
|
||||
{
|
||||
return kexMath::Sqrt(UnitSq());
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::Normalize
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::Normalize(void)
|
||||
{
|
||||
float d = Unit();
|
||||
if(d != 0.0f)
|
||||
{
|
||||
d = 1.0f / d;
|
||||
*this *= d;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::Inverse
|
||||
//
|
||||
|
||||
kexQuat kexQuat::Inverse(void) const
|
||||
{
|
||||
kexQuat out;
|
||||
out.Set(-x, -y, -z, -w);
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator+
|
||||
//
|
||||
|
||||
kexQuat kexQuat::operator+(const kexQuat &quat)
|
||||
{
|
||||
kexQuat out;
|
||||
out.x = x + quat.x;
|
||||
out.y = y + quat.y;
|
||||
out.z = z + quat.z;
|
||||
out.w = w + quat.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator+=
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::operator+=(const kexQuat &quat)
|
||||
{
|
||||
x += quat.x;
|
||||
y += quat.y;
|
||||
z += quat.z;
|
||||
w += quat.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator-
|
||||
//
|
||||
|
||||
kexQuat kexQuat::operator-(const kexQuat &quat)
|
||||
{
|
||||
kexQuat out;
|
||||
out.x = x - quat.x;
|
||||
out.y = y - quat.y;
|
||||
out.z = z - quat.z;
|
||||
out.w = w - quat.w;
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator-=
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::operator-=(const kexQuat &quat)
|
||||
{
|
||||
x -= quat.x;
|
||||
y -= quat.y;
|
||||
z -= quat.z;
|
||||
w -= quat.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator*
|
||||
//
|
||||
|
||||
kexQuat kexQuat::operator*(const kexQuat &quat)
|
||||
{
|
||||
kexQuat out;
|
||||
|
||||
out.x = x * quat.w - y * quat.z + quat.x * w + quat.y * z;
|
||||
out.y = x * quat.z + y * quat.w - quat.x * z + w * quat.y;
|
||||
out.z = quat.x * y + w * quat.z + z * quat.w - x * quat.y;
|
||||
out.w = w * quat.w - quat.y * y + z * quat.z + quat.x * x;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator*=
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::operator*=(const kexQuat &quat)
|
||||
{
|
||||
float tx = x;
|
||||
float ty = y;
|
||||
float tz = z;
|
||||
float tw = w;
|
||||
|
||||
x = tx * quat.w - ty * quat.z + quat.x * tw + quat.y * z;
|
||||
y = tx * quat.z + ty * quat.w - quat.x * tz + tw * quat.y;
|
||||
z = quat.x * ty + tw * quat.z + tz * quat.w - tx * quat.y;
|
||||
w = tw * quat.w - quat.y * ty + tz * quat.z + quat.x * x;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator*
|
||||
//
|
||||
|
||||
kexQuat kexQuat::operator*(const float val) const
|
||||
{
|
||||
kexQuat out;
|
||||
out.x = x * val;
|
||||
out.y = y * val;
|
||||
out.z = z * val;
|
||||
out.w = w * val;
|
||||
return out;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator*=
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::operator*=(const float val)
|
||||
{
|
||||
x *= val;
|
||||
y *= val;
|
||||
z *= val;
|
||||
w *= val;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator|
|
||||
//
|
||||
|
||||
kexVec3 kexQuat::operator|(const kexVec3 &vector)
|
||||
{
|
||||
float xx = x * x;
|
||||
float yx = y * x;
|
||||
float zx = z * x;
|
||||
float wx = w * x;
|
||||
float yy = y * y;
|
||||
float zy = z * y;
|
||||
float wy = w * y;
|
||||
float zz = z * z;
|
||||
float wz = w * z;
|
||||
float ww = w * w;
|
||||
|
||||
return kexVec3(
|
||||
((yx + yx) - (wz + wz)) * vector.y +
|
||||
((wy + wy + zx + zx)) * vector.z +
|
||||
(((ww + xx) - yy) - zz) * vector.x,
|
||||
((yy + (ww - xx)) - zz) * vector.y +
|
||||
((zy + zy) - (wx + wx)) * vector.z +
|
||||
((wz + wz) + (yx + yx)) * vector.x,
|
||||
((wx + wx) + (zy + zy)) * vector.y +
|
||||
(((ww - xx) - yy) + zz) * vector.z +
|
||||
((zx + zx) - (wy + wy)) * vector.x
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::Dot
|
||||
//
|
||||
|
||||
float kexQuat::Dot(const kexQuat &quat) const
|
||||
{
|
||||
return (x * quat.x + y * quat.y + z * quat.z + w * quat.w);
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::Slerp
|
||||
//
|
||||
|
||||
kexQuat kexQuat::Slerp(const kexQuat &quat, float movement) const
|
||||
{
|
||||
kexQuat rdest = quat;
|
||||
float d1 = Dot(quat);
|
||||
float d2 = Dot(quat.Inverse());
|
||||
|
||||
if(d1 < d2)
|
||||
{
|
||||
rdest = quat.Inverse();
|
||||
d1 = d2;
|
||||
}
|
||||
|
||||
if(d1 <= 0.7071067811865001f)
|
||||
{
|
||||
float halfcos = kexMath::ACos(d1);
|
||||
float halfsin = kexMath::Sin(halfcos);
|
||||
|
||||
if(halfsin == 0)
|
||||
{
|
||||
kexQuat out;
|
||||
out.Set(x, y, z, w);
|
||||
return out;
|
||||
}
|
||||
else
|
||||
{
|
||||
float d;
|
||||
float ms1;
|
||||
float ms2;
|
||||
|
||||
d = 1.0f / halfsin;
|
||||
ms1 = kexMath::Sin((1.0f - movement) * halfcos) * d;
|
||||
ms2 = kexMath::Sin(halfcos * movement) * d;
|
||||
|
||||
if(ms2 < 0)
|
||||
{
|
||||
rdest = quat.Inverse();
|
||||
}
|
||||
|
||||
return *this * ms1 + rdest * ms2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kexQuat out = (rdest - *this) * movement + *this;
|
||||
out.Normalize();
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::RotateFrom
|
||||
//
|
||||
|
||||
kexQuat kexQuat::RotateFrom(const kexVec3 &location, const kexVec3 &target, float maxAngle)
|
||||
{
|
||||
kexVec3 axis;
|
||||
kexVec3 dir;
|
||||
kexVec3 cp;
|
||||
kexQuat prot;
|
||||
float an;
|
||||
|
||||
dir = (*this | kexVec3::vecForward);
|
||||
axis = (target - location).Normalize();
|
||||
cp = dir.Cross(axis).Normalize();
|
||||
|
||||
an = kexMath::ACos(axis.Dot(dir));
|
||||
|
||||
if(maxAngle != 0 && an >= maxAngle)
|
||||
{
|
||||
an = maxAngle;
|
||||
}
|
||||
|
||||
return (*this * kexQuat(an, cp));
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator=
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::operator=(const kexQuat &quat)
|
||||
{
|
||||
x = quat.x;
|
||||
y = quat.y;
|
||||
z = quat.z;
|
||||
w = quat.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator=
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::operator=(const kexVec4 &vec)
|
||||
{
|
||||
x = vec.x;
|
||||
y = vec.y;
|
||||
z = vec.z;
|
||||
w = vec.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::operator=
|
||||
//
|
||||
|
||||
kexQuat &kexQuat::operator=(const float *vecs)
|
||||
{
|
||||
x = vecs[0];
|
||||
y = vecs[1];
|
||||
z = vecs[2];
|
||||
w = vecs[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::ToVec3
|
||||
//
|
||||
|
||||
kexVec3 const &kexQuat::ToVec3(void) const
|
||||
{
|
||||
return *reinterpret_cast<const kexVec3*>(this);
|
||||
}
|
||||
|
||||
//
|
||||
// kexQuat::ToVec3
|
||||
//
|
||||
|
||||
kexVec3 &kexQuat::ToVec3(void)
|
||||
{
|
||||
return *reinterpret_cast<kexVec3*>(this);
|
||||
}
|
99
src/lightmap/kexlib/math/random.cpp
Normal file
99
src/lightmap/kexlib/math/random.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Random operations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <math.h>
|
||||
#include "mathlib.h"
|
||||
|
||||
#define RANDOM_MAX 0x7FFF
|
||||
|
||||
int kexRand::seed = 0;
|
||||
|
||||
//
|
||||
// kexRand::SetSeed
|
||||
//
|
||||
|
||||
void kexRand::SetSeed(const int randSeed)
|
||||
{
|
||||
seed = randSeed;
|
||||
}
|
||||
|
||||
//
|
||||
// kexRand::SysRand
|
||||
//
|
||||
|
||||
int kexRand::SysRand(void)
|
||||
{
|
||||
return rand();
|
||||
}
|
||||
|
||||
//
|
||||
// kexRand::Int
|
||||
//
|
||||
|
||||
int kexRand::Int(void)
|
||||
{
|
||||
seed = 1479838765 - 1471521965 * seed;
|
||||
return seed & RANDOM_MAX;
|
||||
}
|
||||
|
||||
//
|
||||
// kexRand::Max
|
||||
//
|
||||
|
||||
int kexRand::Max(const int max)
|
||||
{
|
||||
if(max == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Int() % max;
|
||||
}
|
||||
|
||||
//
|
||||
// kexRand::Float
|
||||
//
|
||||
|
||||
float kexRand::Float(void)
|
||||
{
|
||||
return (float)Max(RANDOM_MAX+1) / ((float)RANDOM_MAX+1);
|
||||
}
|
||||
|
||||
//
|
||||
// kexRand::CFloat
|
||||
//
|
||||
|
||||
float kexRand::CFloat(void)
|
||||
{
|
||||
return (float)(Max(20000) - 10000) * 0.0001f;
|
||||
}
|
||||
|
1268
src/lightmap/kexlib/math/vector.cpp
Normal file
1268
src/lightmap/kexlib/math/vector.cpp
Normal file
File diff suppressed because it is too large
Load diff
403
src/lightmap/kexlib/memheap.cpp
Normal file
403
src/lightmap/kexlib/memheap.cpp
Normal file
|
@ -0,0 +1,403 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Memory Heap Management
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "lightmap/common.h"
|
||||
|
||||
int kexHeap::numHeapBlocks = 0;
|
||||
int kexHeap::currentHeapBlockID = -1;
|
||||
|
||||
kexHeapBlock *kexHeap::currentHeapBlock = NULL;
|
||||
kexHeapBlock *kexHeap::blockList = NULL;
|
||||
|
||||
//
|
||||
// common heap block types
|
||||
//
|
||||
kexHeapBlock hb_static("static", false, NULL, NULL);
|
||||
kexHeapBlock hb_auto("auto", false, NULL, NULL);
|
||||
kexHeapBlock hb_file("file", false, NULL, NULL);
|
||||
kexHeapBlock hb_object("object", false, NULL, NULL);
|
||||
|
||||
//
|
||||
// kexHeapBlock::kexHeapBlock
|
||||
//
|
||||
|
||||
kexHeapBlock::kexHeapBlock(const char *name, bool bGarbageCollect,
|
||||
blockFunc_t funcFree, blockFunc_t funcGC)
|
||||
{
|
||||
this->name = (char*)name;
|
||||
this->freeFunc = funcFree;
|
||||
this->gcFunc = funcGC;
|
||||
this->blocks = NULL;
|
||||
this->bGC = bGarbageCollect;
|
||||
this->purgeID = kexHeap::numHeapBlocks++;
|
||||
|
||||
// add heap block to main block list
|
||||
if(kexHeap::blockList)
|
||||
{
|
||||
if(kexHeap::blockList->prev)
|
||||
{
|
||||
kexHeap::blockList->prev->next = this;
|
||||
this->prev = kexHeap::blockList->prev;
|
||||
this->next = NULL;
|
||||
kexHeap::blockList->prev = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
kexHeap::blockList->prev = this;
|
||||
kexHeap::blockList->next = this;
|
||||
this->prev = kexHeap::blockList;
|
||||
this->next = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
kexHeap::blockList = this;
|
||||
this->prev = NULL;
|
||||
this->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeapBlock::~kexHeapBlock
|
||||
//
|
||||
|
||||
kexHeapBlock::~kexHeapBlock(void)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeapBlock::operator[]
|
||||
//
|
||||
// Should be used with kexHeap::blockList only
|
||||
//
|
||||
|
||||
kexHeapBlock *kexHeapBlock::operator[](int index)
|
||||
{
|
||||
if(kexHeap::currentHeapBlockID == index)
|
||||
{
|
||||
return kexHeap::currentHeapBlock;
|
||||
}
|
||||
|
||||
kexHeapBlock *heapBlock = this;
|
||||
|
||||
for(int i = 0; i < index; i++)
|
||||
{
|
||||
heapBlock = heapBlock->next;
|
||||
if(heapBlock == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
kexHeap::currentHeapBlockID = index;
|
||||
kexHeap::currentHeapBlock = heapBlock;
|
||||
|
||||
return heapBlock;
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::AddBlock
|
||||
//
|
||||
|
||||
void kexHeap::AddBlock(memBlock_t *block, kexHeapBlock *heapBlock)
|
||||
{
|
||||
block->prev = NULL;
|
||||
block->next = heapBlock->blocks;
|
||||
heapBlock->blocks = block;
|
||||
|
||||
block->heapBlock = heapBlock;
|
||||
|
||||
if(block->next != NULL)
|
||||
{
|
||||
block->next->prev = block;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::RemoveBlock
|
||||
//
|
||||
|
||||
void kexHeap::RemoveBlock(memBlock_t *block)
|
||||
{
|
||||
if(block->prev == NULL)
|
||||
{
|
||||
block->heapBlock->blocks = block->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
block->prev->next = block->next;
|
||||
}
|
||||
|
||||
if(block->next != NULL)
|
||||
{
|
||||
block->next->prev = block->prev;
|
||||
}
|
||||
|
||||
block->heapBlock = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::GetBlock
|
||||
//
|
||||
|
||||
memBlock_t *kexHeap::GetBlock(void *ptr, const char *file, int line)
|
||||
{
|
||||
memBlock_t* block;
|
||||
|
||||
block = (memBlock_t*)((byte*)ptr - sizeof(memBlock_t));
|
||||
|
||||
if(block->heapTag != kexHeap::HeapTag)
|
||||
{
|
||||
Error("kexHeap::GetBlock: found a pointer without heap tag (%s:%d)", file, line);
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Malloc
|
||||
//
|
||||
|
||||
void *kexHeap::Malloc(int size, kexHeapBlock &heapBlock, const char *file, int line)
|
||||
{
|
||||
memBlock_t *newblock;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
newblock = NULL;
|
||||
|
||||
if(!(newblock = (memBlock_t*)malloc(sizeof(memBlock_t) + size)))
|
||||
{
|
||||
Error("kexHeap::Malloc: failed on allocation of %u bytes (%s:%d)", size, file, line);
|
||||
}
|
||||
|
||||
newblock->purgeID = heapBlock.purgeID;
|
||||
newblock->heapTag = kexHeap::HeapTag;
|
||||
newblock->size = size;
|
||||
newblock->ptrRef = NULL;
|
||||
|
||||
kexHeap::AddBlock(newblock, &heapBlock);
|
||||
|
||||
return ((byte*)newblock) + sizeof(memBlock_t);
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Calloc
|
||||
//
|
||||
|
||||
void *kexHeap::Calloc(int size, kexHeapBlock &heapBlock, const char *file, int line)
|
||||
{
|
||||
return memset(kexHeap::Malloc(size, heapBlock, file, line), 0, size);
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Realloc
|
||||
//
|
||||
|
||||
void *kexHeap::Realloc(void *ptr, int size, kexHeapBlock &heapBlock, const char *file, int line)
|
||||
{
|
||||
memBlock_t *block;
|
||||
memBlock_t *newblock;
|
||||
|
||||
if(!ptr)
|
||||
{
|
||||
return kexHeap::Malloc(size, heapBlock, file, line);
|
||||
}
|
||||
|
||||
assert(size >= 0);
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
kexHeap::Free(ptr, file, line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block = kexHeap::GetBlock(ptr, file, line);
|
||||
newblock = NULL;
|
||||
|
||||
kexHeap::RemoveBlock(block);
|
||||
|
||||
block->next = NULL;
|
||||
block->prev = NULL;
|
||||
|
||||
if(block->ptrRef)
|
||||
{
|
||||
*block->ptrRef = NULL;
|
||||
}
|
||||
|
||||
if(!(newblock = (memBlock_t*)realloc(block, sizeof(memBlock_t) + size)))
|
||||
{
|
||||
Error("kexHeap::Realloc: failed on allocation of %u bytes (%s:%d)", size, file, line);
|
||||
}
|
||||
|
||||
newblock->purgeID = heapBlock.purgeID;
|
||||
newblock->heapTag = kexHeap::HeapTag;
|
||||
newblock->size = size;
|
||||
newblock->ptrRef = NULL;
|
||||
|
||||
kexHeap::AddBlock(newblock, &heapBlock);
|
||||
|
||||
return ((byte*)newblock) + sizeof(memBlock_t);
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Alloca
|
||||
//
|
||||
|
||||
void *kexHeap::Alloca(int size, const char *file, int line)
|
||||
{
|
||||
return size == 0 ? NULL : kexHeap::Calloc(size, hb_auto, file, line);
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Free
|
||||
//
|
||||
|
||||
void kexHeap::Free(void *ptr, const char *file, int line)
|
||||
{
|
||||
memBlock_t* block;
|
||||
|
||||
block = kexHeap::GetBlock(ptr, file, line);
|
||||
if(block->ptrRef)
|
||||
{
|
||||
*block->ptrRef = NULL;
|
||||
}
|
||||
|
||||
kexHeap::RemoveBlock(block);
|
||||
|
||||
// free back to system
|
||||
free(block);
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Purge
|
||||
//
|
||||
|
||||
void kexHeap::Purge(kexHeapBlock &heapBlock, const char *file, int line)
|
||||
{
|
||||
memBlock_t *block;
|
||||
memBlock_t *next;
|
||||
|
||||
for(block = heapBlock.blocks; block != NULL;)
|
||||
{
|
||||
next = block->next;
|
||||
|
||||
if(block->heapTag != kexHeap::HeapTag)
|
||||
{
|
||||
Error("kexHeap::Purge: Purging without heap tag (%s:%d)", file, line);
|
||||
}
|
||||
|
||||
if(block->ptrRef)
|
||||
{
|
||||
*block->ptrRef = NULL;
|
||||
}
|
||||
|
||||
free(block);
|
||||
block = next;
|
||||
}
|
||||
|
||||
heapBlock.blocks = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::SetCacheRef
|
||||
//
|
||||
|
||||
void kexHeap::SetCacheRef(void **ptr, const char *file, int line)
|
||||
{
|
||||
kexHeap::GetBlock(*ptr, file, line)->ptrRef = ptr;
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::GarbageCollect
|
||||
//
|
||||
|
||||
void kexHeap::GarbageCollect(const char *file, int line)
|
||||
{
|
||||
kexHeap::Purge(hb_auto, file, line);
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::CheckBlocks
|
||||
//
|
||||
|
||||
void kexHeap::CheckBlocks(const char *file, int line)
|
||||
{
|
||||
memBlock_t *block;
|
||||
memBlock_t *prev;
|
||||
kexHeapBlock *heapBlock;
|
||||
|
||||
for(heapBlock = kexHeap::blockList; heapBlock; heapBlock = heapBlock->next)
|
||||
{
|
||||
prev = NULL;
|
||||
|
||||
for(block = heapBlock->blocks; block != NULL; block = block->next)
|
||||
{
|
||||
if(block->heapTag != kexHeap::HeapTag)
|
||||
{
|
||||
Error("kexHeap::CheckBlocks: found block without heap tag (%s:%d)", file, line);
|
||||
}
|
||||
if(block->prev != prev)
|
||||
{
|
||||
Error("kexHeap::CheckBlocks: bad link list found (%s:%d)", file, line);
|
||||
}
|
||||
|
||||
prev = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Touch
|
||||
//
|
||||
|
||||
void kexHeap::Touch(void *ptr, const char *file, int line)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexHeap::Usage
|
||||
//
|
||||
|
||||
int kexHeap::Usage(const kexHeapBlock &heapBlock)
|
||||
{
|
||||
int bytes = 0;
|
||||
memBlock_t *block;
|
||||
|
||||
for(block = heapBlock.blocks; block != NULL; block = block->next)
|
||||
{
|
||||
bytes += block->size;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
114
src/lightmap/kexlib/memheap.h
Normal file
114
src/lightmap/kexlib/memheap.h
Normal file
|
@ -0,0 +1,114 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __MEM_HEAP_H__
|
||||
#define __MEM_HEAP_H__
|
||||
|
||||
typedef void (*blockFunc_t)(void*);
|
||||
|
||||
class kexHeapBlock;
|
||||
|
||||
typedef struct memBlock_s
|
||||
{
|
||||
int heapTag;
|
||||
int purgeID;
|
||||
int size;
|
||||
kexHeapBlock *heapBlock;
|
||||
void **ptrRef;
|
||||
struct memBlock_s *prev;
|
||||
struct memBlock_s *next;
|
||||
} memBlock_t;
|
||||
|
||||
class kexHeapBlock
|
||||
{
|
||||
public:
|
||||
kexHeapBlock(const char *name, bool bGarbageCollect,
|
||||
blockFunc_t funcFree, blockFunc_t funcGC);
|
||||
~kexHeapBlock(void);
|
||||
|
||||
kexHeapBlock *operator[](int index);
|
||||
|
||||
char *name;
|
||||
memBlock_t *blocks;
|
||||
bool bGC;
|
||||
blockFunc_t freeFunc;
|
||||
blockFunc_t gcFunc;
|
||||
int purgeID;
|
||||
kexHeapBlock *prev;
|
||||
kexHeapBlock *next;
|
||||
};
|
||||
|
||||
class kexHeap
|
||||
{
|
||||
public:
|
||||
static void *Malloc(int size, kexHeapBlock &heapBlock, const char *file, int line);
|
||||
static void *Calloc(int size, kexHeapBlock &heapBlock, const char *file, int line);
|
||||
static void *Realloc(void *ptr, int size, kexHeapBlock &heapBlock, const char *file, int line);
|
||||
static void *Alloca(int size, const char *file, int line);
|
||||
static void Free(void *ptr, const char *file, int line);
|
||||
static void Purge(kexHeapBlock &heapBlock, const char *file, int line);
|
||||
static void GarbageCollect(const char *file, int line);
|
||||
static void CheckBlocks(const char *file, int line);
|
||||
static void Touch(void *ptr, const char *file, int line);
|
||||
static int Usage(const kexHeapBlock &heapBlock);
|
||||
static void SetCacheRef(void **ptr, const char *file, int line);
|
||||
|
||||
static int numHeapBlocks;
|
||||
static kexHeapBlock *currentHeapBlock;
|
||||
static int currentHeapBlockID;
|
||||
static kexHeapBlock *blockList;
|
||||
|
||||
private:
|
||||
static void AddBlock(memBlock_t *block, kexHeapBlock *heapBlock);
|
||||
static void RemoveBlock(memBlock_t *block);
|
||||
static memBlock_t *GetBlock(void *ptr, const char *file, int line);
|
||||
|
||||
static const int HeapTag = 0x03151983;
|
||||
};
|
||||
|
||||
extern kexHeapBlock hb_static;
|
||||
extern kexHeapBlock hb_auto;
|
||||
extern kexHeapBlock hb_file;
|
||||
extern kexHeapBlock hb_object;
|
||||
|
||||
#define Mem_Malloc(s, hb) (kexHeap::Malloc(s, hb, __FILE__,__LINE__))
|
||||
#define Mem_Calloc(s, hb) (kexHeap::Calloc(s, hb, __FILE__,__LINE__))
|
||||
#define Mem_Realloc(p, s, hb) (kexHeap::Realloc(p, s, hb, __FILE__,__LINE__))
|
||||
#define Mem_Alloca(s) (kexHeap::Alloca(s, __FILE__,__LINE__))
|
||||
#define Mem_Free(p) (kexHeap::Free(p, __FILE__,__LINE__))
|
||||
#define Mem_Purge(hb) (kexHeap::Purge(hb, __FILE__,__LINE__))
|
||||
#define Mem_GC() (kexHeap::GarbageCollect(__FILE__,__LINE__))
|
||||
#define Mem_CheckBlocks() (kexHeap::CheckBlocks(__FILE__,__LINE__))
|
||||
#define Mem_Touch(p) (kexHeap::Touch(p, __FILE__,__LINE__))
|
||||
#define Mem_CacheRef(p) (kexHeap::SetCacheRef(p, __FILE__,__LINE__))
|
||||
|
||||
#define Mem_AllocStatic(s) (Mem_Calloc(s, hb_static))
|
||||
|
||||
#define Mem_Strdup(s, hb) (strcpy((char*)Mem_Malloc(strlen(s)+1, hb), s))
|
||||
#define Mem_Strdupa(s) (strcpy((char*)Mem_Alloca(strlen(s)+1), s))
|
||||
|
||||
#endif
|
1134
src/lightmap/kexlib/parser.cpp
Normal file
1134
src/lightmap/kexlib/parser.cpp
Normal file
File diff suppressed because it is too large
Load diff
175
src/lightmap/kexlib/parser.h
Normal file
175
src/lightmap/kexlib/parser.h
Normal file
|
@ -0,0 +1,175 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __PARSER_H__
|
||||
#define __PARSER_H__
|
||||
|
||||
#define MAX_NESTED_PARSERS 128
|
||||
#define MAX_NESTED_FILENAMES 128
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TK_NONE,
|
||||
TK_NUMBER,
|
||||
TK_STRING,
|
||||
TK_POUND,
|
||||
TK_COLON,
|
||||
TK_SEMICOLON,
|
||||
TK_PERIOD,
|
||||
TK_QUOTE,
|
||||
TK_FORWARDSLASH,
|
||||
TK_EQUAL,
|
||||
TK_LBRACK,
|
||||
TK_RBRACK,
|
||||
TK_LPAREN,
|
||||
TK_RPAREN,
|
||||
TK_LSQBRACK,
|
||||
TK_RSQBRACK,
|
||||
TK_COMMA,
|
||||
TK_IDENIFIER,
|
||||
TK_DEFINE,
|
||||
TK_UNDEF,
|
||||
TK_INCLUDE,
|
||||
TK_SETDIR,
|
||||
TK_EOF
|
||||
} tokentype_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AT_SHORT,
|
||||
AT_INTEGER,
|
||||
AT_FLOAT,
|
||||
AT_DOUBLE,
|
||||
AT_VECTOR
|
||||
} arraytype_t;
|
||||
|
||||
#define SC_TOKEN_LEN 512
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int id;
|
||||
const char *token;
|
||||
} sctokens_t;
|
||||
|
||||
class kexLexer
|
||||
{
|
||||
public:
|
||||
kexLexer(const char *filename, char *buf, int bufSize);
|
||||
~kexLexer(void);
|
||||
|
||||
bool CheckState(void);
|
||||
void CheckKeywords(void);
|
||||
void MustMatchToken(int type);
|
||||
void ExpectNextToken(int type);
|
||||
bool Find(void);
|
||||
char GetChar(void);
|
||||
void Rewind(void);
|
||||
void SkipLine(void);
|
||||
bool Matches(const char *string);
|
||||
int GetNumber(void);
|
||||
double GetFloat(void);
|
||||
kexVec3 GetVector3(void);
|
||||
kexVec4 GetVector4(void);
|
||||
kexVec3 GetVectorString3(void);
|
||||
kexVec4 GetVectorString4(void);
|
||||
void GetString(void);
|
||||
int GetIDForTokenList(const sctokens_t *tokenlist, const char *token);
|
||||
void ExpectTokenListID(const sctokens_t *tokenlist, int id);
|
||||
void AssignFromTokenList(const sctokens_t *tokenlist,
|
||||
char *str, int id, bool expect);
|
||||
void AssignFromTokenList(const sctokens_t *tokenlist,
|
||||
unsigned int *var, int id, bool expect);
|
||||
void AssignFromTokenList(const sctokens_t *tokenlist,
|
||||
unsigned short *var, int id, bool expect);
|
||||
void AssignFromTokenList(const sctokens_t *tokenlist,
|
||||
float *var, int id, bool expect);
|
||||
void AssignVectorFromTokenList(const sctokens_t *tokenlist,
|
||||
float *var, int id, bool expect);
|
||||
void AssignFromTokenList(const sctokens_t *tokenlist,
|
||||
arraytype_t type, void **data, int count,
|
||||
int id, bool expect, kexHeapBlock &hb);
|
||||
|
||||
int LinePos(void) { return linepos; }
|
||||
int RowPos(void) { return rowpos; }
|
||||
int BufferPos(void) { return buffpos; }
|
||||
int BufferSize(void) { return buffsize; }
|
||||
char *Buffer(void) { return buffer; }
|
||||
char *StringToken(void) { return stringToken; }
|
||||
const char *Token(void) const { return token; }
|
||||
const int TokenType(void) const { return tokentype; }
|
||||
|
||||
private:
|
||||
void ClearToken(void);
|
||||
void GetNumberToken(char initial);
|
||||
void GetLetterToken(char initial);
|
||||
void GetSymbolToken(char c);
|
||||
void GetStringToken(void);
|
||||
|
||||
char token[SC_TOKEN_LEN];
|
||||
char stringToken[MAX_FILEPATH];
|
||||
char* buffer;
|
||||
char* pointer_start;
|
||||
char* pointer_end;
|
||||
int linepos;
|
||||
int rowpos;
|
||||
int buffpos;
|
||||
int buffsize;
|
||||
int tokentype;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
class kexParser
|
||||
{
|
||||
public:
|
||||
kexParser(void);
|
||||
~kexParser(void);
|
||||
|
||||
kexLexer *Open(const char *filename);
|
||||
void Close(void);
|
||||
void HandleError(const char *msg, ...);
|
||||
void PushLexer(const char *filename, char *buf, int bufSize);
|
||||
void PopLexer(void);
|
||||
void PushFileName(const char *name);
|
||||
void PopFileName(void);
|
||||
byte *CharCode(void) { return charcode; }
|
||||
const kexLexer *CurrentLexer(void) const { return currentLexer; }
|
||||
|
||||
private:
|
||||
int OpenExternalFile(const char *name, byte **buffer) const;
|
||||
const char *GetNestedFileName(void) const;
|
||||
|
||||
kexLexer *currentLexer;
|
||||
kexLexer *lexers[MAX_NESTED_PARSERS];
|
||||
int numLexers;
|
||||
byte charcode[256];
|
||||
char nestedFilenames[MAX_NESTED_FILENAMES][MAX_FILEPATH];
|
||||
int numNestedFilenames;
|
||||
};
|
||||
|
||||
extern kexParser *parser;
|
||||
|
||||
#endif
|
1213
src/lightmap/lightmap.cpp
Normal file
1213
src/lightmap/lightmap.cpp
Normal file
File diff suppressed because it is too large
Load diff
93
src/lightmap/lightmap.h
Normal file
93
src/lightmap/lightmap.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __LIGHTMAP_H__
|
||||
#define __LIGHTMAP_H__
|
||||
|
||||
#include "surfaces.h"
|
||||
|
||||
#define LIGHTMAP_MAX_SIZE 1024
|
||||
|
||||
class kexTrace;
|
||||
|
||||
class kexLightmapBuilder
|
||||
{
|
||||
public:
|
||||
kexLightmapBuilder(void);
|
||||
~kexLightmapBuilder(void);
|
||||
|
||||
void BuildSurfaceParams(surface_t *surface);
|
||||
void TraceSurface(surface_t *surface);
|
||||
void CreateLightGrid(void);
|
||||
void CreateLightmaps(kexDoomMap &doomMap);
|
||||
void LightSurface(const int surfid);
|
||||
void LightGrid(const int gridid);
|
||||
void WriteTexturesToTGA(void);
|
||||
void AddLightGridLump(kexWadFile &wadFile);
|
||||
void AddLightmapLumps(kexWadFile &wadFile);
|
||||
|
||||
int samples;
|
||||
float ambience;
|
||||
int textureWidth;
|
||||
int textureHeight;
|
||||
|
||||
static const kexVec3 gridSize;
|
||||
|
||||
private:
|
||||
void NewTexture(void);
|
||||
bool MakeRoomForBlock(const int width, const int height, int *x, int *y, int *num);
|
||||
kexBBox GetBoundsFromSurface(const surface_t *surface);
|
||||
kexVec3 LightTexelSample(kexTrace &trace, const kexVec3 &origin, surface_t *surface);
|
||||
kexVec3 LightCellSample(const int gridid, kexTrace &trace,
|
||||
const kexVec3 &origin, const mapSubSector_t *sub);
|
||||
bool EmitFromCeiling(kexTrace &trace, const surface_t *surface, const kexVec3 &origin,
|
||||
const kexVec3 &normal, float *dist);
|
||||
void ExportTexelsToObjFile(FILE *f, const kexVec3 &org, int indices);
|
||||
void WriteBlock(FILE *f, const int i, const kexVec3 &org, int indices, kexBBox &box);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte marked;
|
||||
byte sunShadow;
|
||||
kexVec3 color;
|
||||
} gridMap_t;
|
||||
|
||||
kexDoomMap *map;
|
||||
kexArray<byte*> textures;
|
||||
int **allocBlocks;
|
||||
int numTextures;
|
||||
int extraSamples;
|
||||
int tracedTexels;
|
||||
int numLightGrids;
|
||||
gridMap_t *gridMap;
|
||||
mapSubSector_t **gridSectors;
|
||||
kexBBox worldGrid;
|
||||
kexBBox gridBound;
|
||||
kexVec3 gridBlock;
|
||||
};
|
||||
|
||||
#endif
|
464
src/lightmap/lightsurface.cpp
Normal file
464
src/lightmap/lightsurface.cpp
Normal file
|
@ -0,0 +1,464 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Special surfaces that contains origin points used for
|
||||
// emitting light. Surfaces can be subdivided for more
|
||||
// accurate light casting
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "common.h"
|
||||
#include "mapData.h"
|
||||
#include "trace.h"
|
||||
#include "lightSurface.h"
|
||||
|
||||
//
|
||||
// kexLightSurface::kexLightSurface
|
||||
//
|
||||
|
||||
kexLightSurface::kexLightSurface(void)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexLightSurface::~kexLightSurface
|
||||
//
|
||||
|
||||
kexLightSurface::~kexLightSurface(void)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexLightSurface::Init
|
||||
//
|
||||
|
||||
void kexLightSurface::Init(const surfaceLightDef_t &lightSurfaceDef,
|
||||
surface_t *surface,
|
||||
const bool bWall,
|
||||
const bool bNoCenterPoint)
|
||||
{
|
||||
this->outerCone = lightSurfaceDef.outerCone;
|
||||
this->innerCone = lightSurfaceDef.innerCone;
|
||||
this->falloff = lightSurfaceDef.falloff;
|
||||
this->intensity = lightSurfaceDef.intensity;
|
||||
this->distance = lightSurfaceDef.distance;
|
||||
this->rgb = lightSurfaceDef.rgb;
|
||||
this->surface = surface;
|
||||
this->bWall = bWall;
|
||||
this->bNoCenterPoint = bNoCenterPoint;
|
||||
}
|
||||
|
||||
//
|
||||
// kexLightSurface::CreateCenterOrigin
|
||||
//
|
||||
// Creates a single origin point if we're not
|
||||
// intending on subdividing this light surface
|
||||
//
|
||||
|
||||
void kexLightSurface::CreateCenterOrigin(void)
|
||||
{
|
||||
if(!bWall)
|
||||
{
|
||||
kexVec3 center;
|
||||
|
||||
for(int i = 0; i < surface->numVerts; ++i)
|
||||
{
|
||||
center += surface->verts[i];
|
||||
}
|
||||
|
||||
origins.Push(center / (float)surface->numVerts);
|
||||
}
|
||||
else
|
||||
{
|
||||
origins.Push(kexVec3((surface->verts[1].x + surface->verts[0].x) * 0.5f,
|
||||
(surface->verts[1].y + surface->verts[0].y) * 0.5f,
|
||||
(surface->verts[2].z + surface->verts[0].z) * 0.5f));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexLightSurface::Clip
|
||||
//
|
||||
// Splits surface vertices into two groups while adding new ones
|
||||
// caused by the split
|
||||
//
|
||||
|
||||
void kexLightSurface::Clip(vertexBatch_t &points, const kexVec3 &normal, float dist,
|
||||
vertexBatch_t *frontPoints, vertexBatch_t *backPoints)
|
||||
{
|
||||
kexArray<float> dists;
|
||||
kexArray<char> sides;
|
||||
|
||||
// determines what sides the vertices lies on
|
||||
for(unsigned int i = 0; i < points.Length(); ++i)
|
||||
{
|
||||
float d = points[i].Dot(normal) - dist;
|
||||
|
||||
dists.Push(d);
|
||||
|
||||
if(d > 0.1f)
|
||||
{
|
||||
sides.Push(1); // front
|
||||
}
|
||||
else if(d < -0.1f)
|
||||
{
|
||||
sides.Push(-1); // directly on the split plane
|
||||
}
|
||||
else
|
||||
{
|
||||
sides.Push(0); // back
|
||||
}
|
||||
}
|
||||
|
||||
// add points
|
||||
for(unsigned int i = 0; i < points.Length(); ++i)
|
||||
{
|
||||
int next;
|
||||
float frac;
|
||||
kexVec3 pt1, pt2, pt3;
|
||||
|
||||
switch(sides[i])
|
||||
{
|
||||
case -1:
|
||||
backPoints->Push(points[i]);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
frontPoints->Push(points[i]);
|
||||
break;
|
||||
|
||||
default:
|
||||
frontPoints->Push(points[i]);
|
||||
backPoints->Push(points[i]);
|
||||
|
||||
// point is on the split plane so no new split vertex is needed
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// check if the edge crosses the split plane
|
||||
next = (i + 1) % points.Length();
|
||||
|
||||
if(sides[next] == 0 || sides[next] == sides[i])
|
||||
{
|
||||
// didn't cross
|
||||
continue;
|
||||
}
|
||||
|
||||
pt1 = points[i];
|
||||
pt2 = points[next];
|
||||
|
||||
// insert a new point caused by the split
|
||||
frac = dists[i] / (dists[i] - dists[next]);
|
||||
pt3 = pt1.Lerp(pt2, frac);
|
||||
|
||||
frontPoints->Push(pt3);
|
||||
backPoints->Push(pt3);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexLightSurface::SubdivideRecursion
|
||||
//
|
||||
// Recursively divides the surface
|
||||
//
|
||||
|
||||
bool kexLightSurface::SubdivideRecursion(vertexBatch_t &surfPoints, float divide,
|
||||
kexArray<vertexBatch_t*> &points)
|
||||
{
|
||||
kexBBox bounds;
|
||||
kexVec3 splitNormal;
|
||||
float dist;
|
||||
vertexBatch_t *frontPoints;
|
||||
vertexBatch_t *backPoints;
|
||||
|
||||
// get bounds from current set of points
|
||||
for(unsigned int i = 0; i < surfPoints.Length(); ++i)
|
||||
{
|
||||
bounds.AddPoint(surfPoints[i]);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 3; ++i)
|
||||
{
|
||||
// check if its large enough to be divided
|
||||
if((bounds.max[i] - bounds.min[i]) > divide)
|
||||
{
|
||||
splitNormal.Clear();
|
||||
splitNormal[i] = 1;
|
||||
|
||||
dist = (bounds.max[i] + bounds.min[i]) * 0.5f;
|
||||
|
||||
frontPoints = new vertexBatch_t;
|
||||
backPoints = new vertexBatch_t;
|
||||
|
||||
// start clipping
|
||||
Clip(surfPoints, splitNormal, dist, frontPoints, backPoints);
|
||||
|
||||
if(!SubdivideRecursion(*frontPoints, divide, points))
|
||||
{
|
||||
points.Push(frontPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete frontPoints;
|
||||
}
|
||||
|
||||
if(!SubdivideRecursion(*backPoints, divide, points))
|
||||
{
|
||||
points.Push(backPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete backPoints;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexLightSurface::Subdivide
|
||||
//
|
||||
|
||||
void kexLightSurface::Subdivide(const float divide)
|
||||
{
|
||||
kexArray<vertexBatch_t*> points;
|
||||
vertexBatch_t surfPoints;
|
||||
|
||||
for(int i = 0; i < surface->numVerts; ++i)
|
||||
{
|
||||
surfPoints.Push(surface->verts[i]);
|
||||
}
|
||||
|
||||
SubdivideRecursion(surfPoints, divide, points);
|
||||
|
||||
// from each group of vertices caused by the split, begin
|
||||
// creating a origin point based on the center of that group
|
||||
for(unsigned int i = 0; i < points.Length(); ++i)
|
||||
{
|
||||
vertexBatch_t *vb = points[i];
|
||||
kexVec3 center;
|
||||
|
||||
for(unsigned int j = 0; j < vb->Length(); ++j)
|
||||
{
|
||||
center += (*vb)[j];
|
||||
}
|
||||
|
||||
origins.Push(center / (float)vb->Length());
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < points.Length(); ++i)
|
||||
{
|
||||
vertexBatch_t *vb = points[i];
|
||||
|
||||
vb->Empty();
|
||||
delete vb;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexLightSurface::TraceSurface
|
||||
//
|
||||
|
||||
bool kexLightSurface::TraceSurface(kexDoomMap *doomMap, kexTrace &trace, const surface_t *surf,
|
||||
const kexVec3 &origin, float *dist)
|
||||
{
|
||||
kexVec3 normal;
|
||||
kexVec3 lnormal;
|
||||
kexVec3 center;
|
||||
bool bInside;
|
||||
float angle;
|
||||
float curDist;
|
||||
|
||||
*dist = -M_INFINITY;
|
||||
|
||||
// light surface will always be fullbright
|
||||
if(surf == surface)
|
||||
{
|
||||
*dist = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bInside = false;
|
||||
|
||||
// nudge the origin around to see if it's actually in the subsector
|
||||
float nudges[4] = { -2, 2, -4, 4 };
|
||||
|
||||
for(int x = 0; x < 4; x++)
|
||||
{
|
||||
for(int y = 0; y < 4; y++)
|
||||
{
|
||||
if(doomMap->PointInsideSubSector(origin.x + nudges[x],
|
||||
origin.y + nudges[y], surface->subSector))
|
||||
{
|
||||
bInside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bInside)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lnormal = surface->plane.Normal();
|
||||
|
||||
if(surf)
|
||||
{
|
||||
normal = surf->plane.Normal();
|
||||
|
||||
if(normal.Dot(lnormal) > 0)
|
||||
{
|
||||
// not facing the light surface
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normal = kexVec3::vecUp;
|
||||
}
|
||||
|
||||
// we need to pick the closest sample point on the light surface. what really sucks is
|
||||
// that we have to trace each one... which could really blow up the compile time
|
||||
for(unsigned int i = 0; i < origins.Length(); ++i)
|
||||
{
|
||||
center = origins[i];
|
||||
|
||||
if(!bWall && origin.z > center.z)
|
||||
{
|
||||
// origin is not going to seen or traced by the light surface
|
||||
// so don't even bother. this also fixes some bizzare light
|
||||
// bleeding issues
|
||||
continue;
|
||||
}
|
||||
|
||||
if(bWall)
|
||||
{
|
||||
angle = (origin - center).ToVec2().Normalize().Dot(lnormal.ToVec2());
|
||||
}
|
||||
else
|
||||
{
|
||||
kexVec3 dir = (origin - center).Normalize();
|
||||
|
||||
if(surf)
|
||||
{
|
||||
if(normal.Dot(dir) >= 0)
|
||||
{
|
||||
// not even facing the light surface
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
angle = dir.Dot(lnormal);
|
||||
|
||||
if(angle > innerCone)
|
||||
{
|
||||
angle = innerCone;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bInside && angle < outerCone)
|
||||
{
|
||||
// out of the cone range
|
||||
continue;
|
||||
}
|
||||
|
||||
if(bWall)
|
||||
{
|
||||
if(origin.z >= surface->verts[0].z && origin.z <= surface->verts[2].z)
|
||||
{
|
||||
// since walls are always vertically straight, we can cheat a little by adjusting
|
||||
// the sampling point height. this also allows us to do accurate light emitting
|
||||
// while just using one sample point
|
||||
center.z = origin.z;
|
||||
}
|
||||
}
|
||||
|
||||
// trace the origin to the center of the light surface. nudge by the normals in
|
||||
// case the start/end points are directly on or inside the surface
|
||||
trace.Trace(center + lnormal, origin + normal);
|
||||
|
||||
if(trace.fraction != 1)
|
||||
{
|
||||
// something is obstructing it
|
||||
continue;
|
||||
}
|
||||
|
||||
float d = origin.Distance(center);
|
||||
|
||||
if(d <= 0)
|
||||
{
|
||||
// this origin point must be right on the light surface so just mark it as
|
||||
// full bright if that's the case
|
||||
curDist = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
curDist = distance / d;
|
||||
}
|
||||
|
||||
if(curDist >= 1)
|
||||
{
|
||||
curDist = 1;
|
||||
|
||||
// might get large unlit gaps near the surface. this looks a lot worse for
|
||||
// non-wall light surfaces so just clamp to full bright and exit out.
|
||||
if(!bWall)
|
||||
{
|
||||
*dist = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// determine how much to fade out
|
||||
if(angle < innerCone)
|
||||
{
|
||||
float div = (innerCone - outerCone);
|
||||
|
||||
if(div != 0)
|
||||
{
|
||||
curDist *= ((angle - outerCone) / div);
|
||||
}
|
||||
else
|
||||
{
|
||||
curDist *= angle;
|
||||
}
|
||||
}
|
||||
|
||||
if(curDist > *dist)
|
||||
{
|
||||
*dist = curDist;
|
||||
}
|
||||
}
|
||||
|
||||
return *dist > 0;
|
||||
}
|
92
src/lightmap/lightsurface.h
Normal file
92
src/lightmap/lightsurface.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __LIGHT_SURFACE_H__
|
||||
#define __LIGHT_SURFACE_H__
|
||||
|
||||
#include "surfaces.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int tag;
|
||||
float outerCone;
|
||||
float innerCone;
|
||||
float falloff;
|
||||
float distance;
|
||||
float intensity;
|
||||
bool bIgnoreFloor;
|
||||
bool bIgnoreCeiling;
|
||||
bool bNoCenterPoint;
|
||||
kexVec3 rgb;
|
||||
} surfaceLightDef_t;
|
||||
|
||||
class kexDoomMap;
|
||||
class kexTrace;
|
||||
|
||||
class kexLightSurface
|
||||
{
|
||||
public:
|
||||
kexLightSurface(void);
|
||||
~kexLightSurface(void);
|
||||
|
||||
void Init(const surfaceLightDef_t &lightSurfaceDef, surface_t *surface,
|
||||
const bool bWall, const bool bNoCenterPoint);
|
||||
void Subdivide(const float divide);
|
||||
void CreateCenterOrigin(void);
|
||||
bool TraceSurface(kexDoomMap *doomMap, kexTrace &trace, const surface_t *surface,
|
||||
const kexVec3 &origin, float *dist);
|
||||
|
||||
const float OuterCone(void) const { return outerCone; }
|
||||
const float InnerCone(void) const { return innerCone; }
|
||||
const float FallOff(void) const { return falloff; }
|
||||
const float Distance(void) const { return distance; }
|
||||
const float Intensity(void) const { return intensity; }
|
||||
const kexVec3 GetRGB(void) const { return rgb; }
|
||||
const bool IsAWall(void) const { return bWall; }
|
||||
const bool NoCenterPoint(void) const { return bNoCenterPoint; }
|
||||
const surface_t *Surface(void) const { return surface; }
|
||||
const vertexBatch_t Origins(void) const { return origins; }
|
||||
|
||||
private:
|
||||
bool SubdivideRecursion(vertexBatch_t &surfPoints, float divide,
|
||||
kexArray<vertexBatch_t*> &points);
|
||||
void Clip(vertexBatch_t &points, const kexVec3 &normal, float dist,
|
||||
vertexBatch_t *frontPoints, vertexBatch_t *backPoints);
|
||||
|
||||
float outerCone;
|
||||
float innerCone;
|
||||
float falloff;
|
||||
float distance;
|
||||
float intensity;
|
||||
kexVec3 rgb;
|
||||
bool bWall;
|
||||
bool bNoCenterPoint;
|
||||
vertexBatch_t origins;
|
||||
surface_t *surface;
|
||||
};
|
||||
|
||||
#endif
|
957
src/lightmap/mapdata.cpp
Normal file
957
src/lightmap/mapdata.cpp
Normal file
|
@ -0,0 +1,957 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: General doom map utilities and data preperation
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "common.h"
|
||||
#include "wad.h"
|
||||
#include "kexlib/parser.h"
|
||||
#include "mapData.h"
|
||||
#include "lightSurface.h"
|
||||
|
||||
const kexVec3 kexDoomMap::defaultSunColor(1, 1, 1);
|
||||
const kexVec3 kexDoomMap::defaultSunDirection(0.45f, 0.3f, 0.9f);
|
||||
|
||||
//
|
||||
// kexDoomMap::kexDoomMap
|
||||
//
|
||||
|
||||
kexDoomMap::kexDoomMap(void)
|
||||
{
|
||||
this->mapLines = NULL;
|
||||
this->mapVerts = NULL;
|
||||
this->mapSides = NULL;
|
||||
this->mapSectors = NULL;
|
||||
this->mapSegs = NULL;
|
||||
this->mapSSects = NULL;
|
||||
this->nodes = NULL;
|
||||
this->leafs = NULL;
|
||||
this->segLeafLookup = NULL;
|
||||
this->ssLeafLookup = NULL;
|
||||
this->ssLeafCount = NULL;
|
||||
this->segSurfaces[0] = NULL;
|
||||
this->segSurfaces[1] = NULL;
|
||||
this->segSurfaces[2] = NULL;
|
||||
this->leafSurfaces[0] = NULL;
|
||||
this->leafSurfaces[1] = NULL;
|
||||
this->vertexes = NULL;
|
||||
this->mapPVS = NULL;
|
||||
this->mapDef = NULL;
|
||||
|
||||
this->numLeafs = 0;
|
||||
this->numLines = 0;
|
||||
this->numVerts = 0;
|
||||
this->numSides = 0;
|
||||
this->numSectors = 0;
|
||||
this->numSegs = 0;
|
||||
this->numSSects = 0;
|
||||
this->numNodes = 0;
|
||||
this->numVertexes = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::~kexDoomMap
|
||||
//
|
||||
|
||||
kexDoomMap::~kexDoomMap(void)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::BuildMapFromWad
|
||||
//
|
||||
|
||||
void kexDoomMap::BuildMapFromWad(kexWadFile &wadFile)
|
||||
{
|
||||
wadFile.GetMapLump<mapThing_t>(ML_THINGS, &mapThings, &numThings);
|
||||
wadFile.GetMapLump<mapVertex_t>(ML_VERTEXES, &mapVerts, &numVerts);
|
||||
wadFile.GetMapLump<mapLineDef_t>(ML_LINEDEFS, &mapLines, &numLines);
|
||||
wadFile.GetMapLump<mapSideDef_t>(ML_SIDEDEFS, &mapSides, &numSides);
|
||||
wadFile.GetMapLump<mapSector_t>(ML_SECTORS, &mapSectors, &numSectors);
|
||||
|
||||
wadFile.GetGLMapLump<glSeg_t>(ML_GL_SEGS, &mapSegs, &numSegs);
|
||||
wadFile.GetGLMapLump<mapSubSector_t>(ML_GL_SSECT, &mapSSects, &numSSects);
|
||||
wadFile.GetGLMapLump<mapNode_t>(ML_GL_NODES, &nodes, &numNodes);
|
||||
wadFile.GetGLMapLump<byte>(ML_GL_PVS, &mapPVS, 0);
|
||||
|
||||
if(mapSegs == NULL)
|
||||
{
|
||||
Error("kexDoomMap::BuildMapFromWad: SEGS lump not found\n");
|
||||
return;
|
||||
}
|
||||
if(mapSSects == NULL)
|
||||
{
|
||||
Error("kexDoomMap::BuildMapFromWad: SSECTORS lump not found\n");
|
||||
return;
|
||||
}
|
||||
if(nodes == NULL)
|
||||
{
|
||||
Error("kexDoomMap::BuildMapFromWad: NODES lump not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < mapDefs.Length(); ++i)
|
||||
{
|
||||
if(mapDefs[i].map == wadFile.currentmap)
|
||||
{
|
||||
mapDef = &mapDefs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("------------- Level Info -------------\n");
|
||||
printf("Vertices: %i\n", numVerts);
|
||||
printf("Segments: %i\n", numSegs);
|
||||
printf("Subsectors: %i\n", numSSects);
|
||||
|
||||
BuildVertexes(wadFile);
|
||||
BuildNodeBounds();
|
||||
BuildLeafs();
|
||||
BuildPVS();
|
||||
CheckSkySectors();
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::CheckSkySectors
|
||||
//
|
||||
|
||||
void kexDoomMap::CheckSkySectors(void)
|
||||
{
|
||||
char name[9];
|
||||
|
||||
bSkySectors = (bool*)Mem_Calloc(sizeof(bool) * numSectors, hb_static);
|
||||
bSSectsVisibleToSky = (bool*)Mem_Calloc(sizeof(bool) * numSSects, hb_static);
|
||||
|
||||
for(int i = 0; i < numSectors; ++i)
|
||||
{
|
||||
if(mapDef->sunIgnoreTag != 0 && mapSectors[i].tag == mapDef->sunIgnoreTag)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
strncpy(name, mapSectors[i].ceilingpic, 8);
|
||||
name[8] = 0;
|
||||
|
||||
if(!strncmp(name, "F_SKY001", 8))
|
||||
{
|
||||
bSkySectors[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// try to early out by quickly checking which subsector can potentially
|
||||
// see a sky sector
|
||||
for(int i = 0; i < numSSects; ++i)
|
||||
{
|
||||
for(int j = 0; j < numSSects; ++j)
|
||||
{
|
||||
mapSector_t *sec = GetSectorFromSubSector(&mapSSects[j]);
|
||||
|
||||
if(bSkySectors[sec - mapSectors] == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(CheckPVS(&mapSSects[i], &mapSSects[j]))
|
||||
{
|
||||
bSSectsVisibleToSky[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::BuildPVS
|
||||
//
|
||||
|
||||
void kexDoomMap::BuildPVS(void)
|
||||
{
|
||||
// don't do anything if already loaded
|
||||
if(mapPVS != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int len = ((numSSects + 7) / 8) * numSSects;
|
||||
mapPVS = (byte*)Mem_Malloc(len, hb_static);
|
||||
memset(mapPVS, 0xff, len);
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::CheckPVS
|
||||
//
|
||||
|
||||
bool kexDoomMap::CheckPVS(mapSubSector_t *s1, mapSubSector_t *s2)
|
||||
{
|
||||
byte *vis;
|
||||
int n1, n2;
|
||||
|
||||
n1 = s1 - mapSSects;
|
||||
n2 = s2 - mapSSects;
|
||||
|
||||
vis = &mapPVS[(((numSSects + 7) / 8) * n1)];
|
||||
|
||||
return ((vis[n2 >> 3] & (1 << (n2 & 7))) != 0);
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::BuildVertexes
|
||||
//
|
||||
|
||||
void kexDoomMap::BuildVertexes(kexWadFile &wadFile)
|
||||
{
|
||||
byte *data;
|
||||
int count;
|
||||
glVert_t *verts;
|
||||
lump_t *lump;
|
||||
|
||||
if(!(lump = wadFile.GetGLMapLump(static_cast<glMapLumps_t>(ML_GL_VERTS))))
|
||||
{
|
||||
Error("kexDoomMap::BuildVertexes: GL_VERTS lump not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
data = wadFile.GetLumpData(lump);
|
||||
|
||||
if(*((int*)data) != gNd2)
|
||||
{
|
||||
Error("kexDoomMap::BuildVertexes: GL_VERTS must be version 2 only");
|
||||
return;
|
||||
}
|
||||
|
||||
verts = (glVert_t*)(data + GL_VERT_OFFSET);
|
||||
count = (lump->size - GL_VERT_OFFSET) / sizeof(glVert_t);
|
||||
|
||||
numVertexes = numVerts + count;
|
||||
vertexes = (vertex_t*)Mem_Calloc(sizeof(vertex_t) * numVertexes, hb_static);
|
||||
|
||||
for(int i = 0; i < numVerts; i++)
|
||||
{
|
||||
vertexes[i].x = F(mapVerts[i].x << 16);
|
||||
vertexes[i].y = F(mapVerts[i].y << 16);
|
||||
}
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
vertexes[numVerts + i].x = F(verts[i].x);
|
||||
vertexes[numVerts + i].y = F(verts[i].y);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::BuildNodeBounds
|
||||
//
|
||||
|
||||
void kexDoomMap::BuildNodeBounds(void)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
kexVec3 point;
|
||||
float high = -M_INFINITY;
|
||||
float low = M_INFINITY;
|
||||
|
||||
nodeBounds = (kexBBox*)Mem_Calloc(sizeof(kexBBox) * numNodes, hb_static);
|
||||
|
||||
for(i = 0; i < numSectors; ++i)
|
||||
{
|
||||
if(mapSectors[i].ceilingheight > high)
|
||||
{
|
||||
high = mapSectors[i].ceilingheight;
|
||||
}
|
||||
if(mapSectors[i].floorheight < low)
|
||||
{
|
||||
low = mapSectors[i].floorheight;
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < numNodes; ++i)
|
||||
{
|
||||
nodeBounds[i].Clear();
|
||||
|
||||
for(j = 0; j < 2; ++j)
|
||||
{
|
||||
point.Set(nodes[i].bbox[j][BOXLEFT], nodes[i].bbox[j][BOXBOTTOM], low);
|
||||
nodeBounds[i].AddPoint(point);
|
||||
point.Set(nodes[i].bbox[j][BOXRIGHT], nodes[i].bbox[j][BOXTOP], high);
|
||||
nodeBounds[i].AddPoint(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::BuildLeafs
|
||||
//
|
||||
|
||||
void kexDoomMap::BuildLeafs(void)
|
||||
{
|
||||
mapSubSector_t *ss;
|
||||
leaf_t *lf;
|
||||
int i;
|
||||
int j;
|
||||
kexVec3 point;
|
||||
mapSector_t *sector;
|
||||
int count;
|
||||
|
||||
leafs = (leaf_t*)Mem_Calloc(sizeof(leaf_t*) * numSegs * 2, hb_static);
|
||||
numLeafs = numSSects;
|
||||
|
||||
ss = mapSSects;
|
||||
|
||||
segLeafLookup = (int*)Mem_Calloc(sizeof(int) * numSegs, hb_static);
|
||||
ssLeafLookup = (int*)Mem_Calloc(sizeof(int) * numSSects, hb_static);
|
||||
ssLeafCount = (int*)Mem_Calloc(sizeof(int) * numSSects, hb_static);
|
||||
ssLeafBounds = (kexBBox*)Mem_Calloc(sizeof(kexBBox) * numSSects, hb_static);
|
||||
|
||||
count = 0;
|
||||
|
||||
for(i = 0; i < numSSects; ++i, ++ss)
|
||||
{
|
||||
ssLeafCount[i] = ss->numsegs;
|
||||
ssLeafLookup[i] = ss->firstseg;
|
||||
|
||||
ssLeafBounds[i].Clear();
|
||||
sector = GetSectorFromSubSector(ss);
|
||||
|
||||
if(ss->numsegs)
|
||||
{
|
||||
for(j = 0; j < ss->numsegs; ++j)
|
||||
{
|
||||
glSeg_t *seg = &mapSegs[ss->firstseg + j];
|
||||
lf = &leafs[count++];
|
||||
|
||||
segLeafLookup[ss->firstseg + j] = i;
|
||||
|
||||
lf->vertex = GetSegVertex(seg->v1);
|
||||
lf->seg = seg;
|
||||
|
||||
point.Set(lf->vertex->x, lf->vertex->y, sector->floorheight);
|
||||
ssLeafBounds[i].AddPoint(point);
|
||||
|
||||
point.z = sector->ceilingheight;
|
||||
ssLeafBounds[i].AddPoint(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::GetSegVertex
|
||||
//
|
||||
|
||||
vertex_t *kexDoomMap::GetSegVertex(int index)
|
||||
{
|
||||
if(index & 0x8000)
|
||||
{
|
||||
index = (index & 0x7FFF) + numVerts;
|
||||
}
|
||||
|
||||
return &vertexes[index];
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::GetSideDef
|
||||
//
|
||||
|
||||
mapSideDef_t *kexDoomMap::GetSideDef(const glSeg_t *seg)
|
||||
{
|
||||
mapLineDef_t *line;
|
||||
|
||||
if(seg->linedef == NO_LINE_INDEX)
|
||||
{
|
||||
// skip minisegs
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = &mapLines[seg->linedef];
|
||||
return &mapSides[line->sidenum[seg->side]];
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::GetFrontSector
|
||||
//
|
||||
|
||||
mapSector_t *kexDoomMap::GetFrontSector(const glSeg_t *seg)
|
||||
{
|
||||
mapSideDef_t *side = GetSideDef(seg);
|
||||
|
||||
if(side == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &mapSectors[side->sector];
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::GetBackSector
|
||||
//
|
||||
|
||||
mapSector_t *kexDoomMap::GetBackSector(const glSeg_t *seg)
|
||||
{
|
||||
mapLineDef_t *line;
|
||||
|
||||
if(seg->linedef == NO_LINE_INDEX)
|
||||
{
|
||||
// skip minisegs
|
||||
return NULL;
|
||||
}
|
||||
|
||||
line = &mapLines[seg->linedef];
|
||||
|
||||
if(line->flags & ML_TWOSIDED)
|
||||
{
|
||||
mapSideDef_t *backSide = &mapSides[line->sidenum[seg->side^1]];
|
||||
return &mapSectors[backSide->sector];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::GetSectorFromSubSector
|
||||
//
|
||||
|
||||
mapSector_t *kexDoomMap::GetSectorFromSubSector(const mapSubSector_t *sub)
|
||||
{
|
||||
mapSector_t *sector = NULL;
|
||||
|
||||
// try to find a sector that the subsector belongs to
|
||||
for(int i = 0; i < sub->numsegs; i++)
|
||||
{
|
||||
glSeg_t *seg = &mapSegs[sub->firstseg + i];
|
||||
if(seg->side != NO_SIDE_INDEX)
|
||||
{
|
||||
sector = GetFrontSector(seg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::PointInSubSector
|
||||
//
|
||||
|
||||
mapSubSector_t *kexDoomMap::PointInSubSector(const int x, const int y)
|
||||
{
|
||||
mapNode_t *node;
|
||||
int side;
|
||||
int nodenum;
|
||||
kexVec3 dp1;
|
||||
kexVec3 dp2;
|
||||
float d;
|
||||
|
||||
// single subsector is a special case
|
||||
if(!numNodes)
|
||||
{
|
||||
return &mapSSects[0];
|
||||
}
|
||||
|
||||
nodenum = numNodes - 1;
|
||||
|
||||
while(!(nodenum & NF_SUBSECTOR) )
|
||||
{
|
||||
node = &nodes[nodenum];
|
||||
|
||||
kexVec3 pt1(F(node->x << 16), F(node->y << 16), 0);
|
||||
kexVec3 pt2(F(node->dx << 16), F(node->dy << 16), 0);
|
||||
kexVec3 pos(F(x << 16), F(y << 16), 0);
|
||||
|
||||
dp1 = pt1 - pos;
|
||||
dp2 = (pt2 + pt1) - pos;
|
||||
d = dp1.Cross(dp2).z;
|
||||
|
||||
side = FLOATSIGNBIT(d);
|
||||
|
||||
nodenum = node->children[side ^ 1];
|
||||
}
|
||||
|
||||
return &mapSSects[nodenum & ~NF_SUBSECTOR];
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::PointInsideSubSector
|
||||
//
|
||||
|
||||
bool kexDoomMap::PointInsideSubSector(const float x, const float y, const mapSubSector_t *sub)
|
||||
{
|
||||
surface_t *surf;
|
||||
int i;
|
||||
kexVec2 p(x, y);
|
||||
kexVec2 dp1, dp2;
|
||||
kexVec2 pt1, pt2;
|
||||
|
||||
surf = leafSurfaces[0][sub - mapSSects];
|
||||
|
||||
// check to see if the point is inside the subsector leaf
|
||||
for(i = 0; i < surf->numVerts; i++)
|
||||
{
|
||||
pt1 = surf->verts[i].ToVec2();
|
||||
pt2 = surf->verts[(i+1)%surf->numVerts].ToVec2();
|
||||
|
||||
dp1 = pt1 - p;
|
||||
dp2 = pt2 - p;
|
||||
|
||||
if(dp1.CrossScalar(dp2) < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// this point is outside the subsector leaf
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::LineIntersectSubSector
|
||||
//
|
||||
|
||||
bool kexDoomMap::LineIntersectSubSector(const kexVec3 &start, const kexVec3 &end,
|
||||
const mapSubSector_t *sub, kexVec2 &out)
|
||||
{
|
||||
surface_t *surf;
|
||||
kexVec2 p1, p2;
|
||||
kexVec2 s1, s2;
|
||||
kexVec2 pt;
|
||||
kexVec2 v;
|
||||
float d, u;
|
||||
float newX;
|
||||
float ab;
|
||||
int i;
|
||||
|
||||
surf = leafSurfaces[0][sub - mapSSects];
|
||||
p1 = start.ToVec2();
|
||||
p2 = end.ToVec2();
|
||||
|
||||
for(i = 0; i < surf->numVerts; i++)
|
||||
{
|
||||
s1 = surf->verts[i].ToVec2();
|
||||
s2 = surf->verts[(i+1)%surf->numVerts].ToVec2();
|
||||
|
||||
if((p1 == p2) || (s1 == s2))
|
||||
{
|
||||
// zero length
|
||||
continue;
|
||||
}
|
||||
|
||||
if((p1 == s1) || (p2 == s1) || (p1 == s2) || (p2 == s2))
|
||||
{
|
||||
// shares end point
|
||||
continue;
|
||||
}
|
||||
|
||||
// translate to origin
|
||||
pt = p2 - p1;
|
||||
s1 -= p1;
|
||||
s2 -= p1;
|
||||
|
||||
// normalize
|
||||
u = pt.UnitSq();
|
||||
d = kexMath::InvSqrt(u);
|
||||
v = (pt * d);
|
||||
|
||||
// rotate points s1 and s2 so they're on the positive x axis
|
||||
newX = s1.Dot(v);
|
||||
s1.y = s1.CrossScalar(v);
|
||||
s1.x = newX;
|
||||
|
||||
newX = s2.Dot(v);
|
||||
s2.y = s2.CrossScalar(v);
|
||||
s2.x = newX;
|
||||
|
||||
if((s1.y < 0 && s2.y < 0) || (s1.y >= 0 && s2.y >= 0))
|
||||
{
|
||||
// s1 and s2 didn't cross
|
||||
continue;
|
||||
}
|
||||
|
||||
ab = s2.x + (s1.x - s2.x) * s2.y / (s2.y - s1.y);
|
||||
|
||||
if(ab < 0 || ab > (u * d))
|
||||
{
|
||||
// s1 and s2 crosses but outside of points p1 and p2
|
||||
continue;
|
||||
}
|
||||
|
||||
// intersected
|
||||
out = p1 + (v * ab);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::GetSunColor
|
||||
//
|
||||
|
||||
const kexVec3 &kexDoomMap::GetSunColor(void) const
|
||||
{
|
||||
if(mapDef != NULL)
|
||||
{
|
||||
return mapDef->sunColor;
|
||||
}
|
||||
|
||||
return defaultSunColor;
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::GetSunDirection
|
||||
//
|
||||
|
||||
const kexVec3 &kexDoomMap::GetSunDirection(void) const
|
||||
{
|
||||
if(mapDef != NULL)
|
||||
{
|
||||
return mapDef->sunDir;
|
||||
}
|
||||
|
||||
return defaultSunDirection;
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::ParseConfigFile
|
||||
//
|
||||
|
||||
void kexDoomMap::ParseConfigFile(const char *file)
|
||||
{
|
||||
kexLexer *lexer;
|
||||
|
||||
if(!(lexer = parser->Open(file)))
|
||||
{
|
||||
Error("kexDoomMap::ParseConfigFile: %s not found\n", file);
|
||||
return;
|
||||
}
|
||||
|
||||
while(lexer->CheckState())
|
||||
{
|
||||
lexer->Find();
|
||||
|
||||
// check for mapdef block
|
||||
if(lexer->Matches("mapdef"))
|
||||
{
|
||||
mapDef_t mapDef;
|
||||
|
||||
mapDef.map = -1;
|
||||
mapDef.sunIgnoreTag = 0;
|
||||
|
||||
lexer->ExpectNextToken(TK_LBRACK);
|
||||
lexer->Find();
|
||||
|
||||
while(lexer->TokenType() != TK_RBRACK)
|
||||
{
|
||||
if(lexer->Matches("map"))
|
||||
{
|
||||
mapDef.map = lexer->GetNumber();
|
||||
}
|
||||
else if(lexer->Matches("sun_ignore_tag"))
|
||||
{
|
||||
mapDef.sunIgnoreTag = lexer->GetNumber();
|
||||
}
|
||||
else if(lexer->Matches("sun_direction"))
|
||||
{
|
||||
mapDef.sunDir = lexer->GetVectorString3();
|
||||
}
|
||||
else if(lexer->Matches("sun_color"))
|
||||
{
|
||||
mapDef.sunColor = lexer->GetVectorString3();
|
||||
mapDef.sunColor /= 255.0f;
|
||||
}
|
||||
|
||||
lexer->Find();
|
||||
}
|
||||
|
||||
mapDefs.Push(mapDef);
|
||||
}
|
||||
|
||||
// check for lightdef block
|
||||
if(lexer->Matches("lightdef"))
|
||||
{
|
||||
lightDef_t lightDef;
|
||||
|
||||
lightDef.doomednum = -1;
|
||||
lightDef.height = 0;
|
||||
lightDef.intensity = 2;
|
||||
lightDef.falloff = 1;
|
||||
lightDef.bCeiling = false;
|
||||
|
||||
lexer->ExpectNextToken(TK_LBRACK);
|
||||
lexer->Find();
|
||||
|
||||
while(lexer->TokenType() != TK_RBRACK)
|
||||
{
|
||||
if(lexer->Matches("doomednum"))
|
||||
{
|
||||
lightDef.doomednum = lexer->GetNumber();
|
||||
}
|
||||
else if(lexer->Matches("rgb"))
|
||||
{
|
||||
lightDef.rgb = lexer->GetVectorString3();
|
||||
lightDef.rgb /= 255.0f;
|
||||
}
|
||||
else if(lexer->Matches("height"))
|
||||
{
|
||||
lightDef.height = (float)lexer->GetFloat();
|
||||
}
|
||||
else if(lexer->Matches("radius"))
|
||||
{
|
||||
lightDef.radius = (float)lexer->GetFloat();
|
||||
}
|
||||
else if(lexer->Matches("intensity"))
|
||||
{
|
||||
lightDef.intensity = (float)lexer->GetFloat();
|
||||
}
|
||||
else if(lexer->Matches("falloff"))
|
||||
{
|
||||
lightDef.falloff = (float)lexer->GetFloat();
|
||||
}
|
||||
else if(lexer->Matches("ceiling"))
|
||||
{
|
||||
lightDef.bCeiling = true;
|
||||
}
|
||||
|
||||
lexer->Find();
|
||||
}
|
||||
|
||||
lightDefs.Push(lightDef);
|
||||
}
|
||||
|
||||
if(lexer->Matches("surfaceLight"))
|
||||
{
|
||||
surfaceLightDef_t surfaceLight;
|
||||
|
||||
surfaceLight.tag = 0;
|
||||
surfaceLight.outerCone = 1.0f;
|
||||
surfaceLight.innerCone = 0;
|
||||
surfaceLight.falloff = 1.0f;
|
||||
surfaceLight.intensity = 1.0f;
|
||||
surfaceLight.distance = 32.0f;
|
||||
surfaceLight.bIgnoreCeiling = false;
|
||||
surfaceLight.bIgnoreFloor = false;
|
||||
surfaceLight.bNoCenterPoint = false;
|
||||
|
||||
lexer->ExpectNextToken(TK_LBRACK);
|
||||
lexer->Find();
|
||||
|
||||
while(lexer->TokenType() != TK_RBRACK)
|
||||
{
|
||||
if(lexer->Matches("tag"))
|
||||
{
|
||||
surfaceLight.tag = lexer->GetNumber();
|
||||
}
|
||||
else if(lexer->Matches("rgb"))
|
||||
{
|
||||
surfaceLight.rgb = lexer->GetVectorString3();
|
||||
surfaceLight.rgb /= 255.0f;
|
||||
}
|
||||
else if(lexer->Matches("cone_outer"))
|
||||
{
|
||||
surfaceLight.outerCone = (float)lexer->GetFloat() / 180.0f;
|
||||
}
|
||||
else if(lexer->Matches("cone_inner"))
|
||||
{
|
||||
surfaceLight.innerCone = (float)lexer->GetFloat() / 180.0f;
|
||||
}
|
||||
else if(lexer->Matches("falloff"))
|
||||
{
|
||||
surfaceLight.falloff = (float)lexer->GetFloat();
|
||||
}
|
||||
else if(lexer->Matches("intensity"))
|
||||
{
|
||||
surfaceLight.intensity = (float)lexer->GetFloat();
|
||||
}
|
||||
else if(lexer->Matches("distance"))
|
||||
{
|
||||
surfaceLight.distance = (float)lexer->GetFloat();
|
||||
}
|
||||
else if(lexer->Matches("bIgnoreCeiling"))
|
||||
{
|
||||
surfaceLight.bIgnoreCeiling = true;
|
||||
}
|
||||
else if(lexer->Matches("bIgnoreFloor"))
|
||||
{
|
||||
surfaceLight.bIgnoreFloor = true;
|
||||
}
|
||||
else if(lexer->Matches("bNoCenterPoint"))
|
||||
{
|
||||
surfaceLight.bNoCenterPoint = true;
|
||||
}
|
||||
|
||||
lexer->Find();
|
||||
}
|
||||
|
||||
surfaceLightDefs.Push(surfaceLight);
|
||||
}
|
||||
}
|
||||
|
||||
// we're done with the file
|
||||
parser->Close();
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::CreateLights
|
||||
//
|
||||
|
||||
void kexDoomMap::CreateLights(void)
|
||||
{
|
||||
mapThing_t *thing;
|
||||
thingLight_t *thingLight;
|
||||
unsigned int j;
|
||||
int numSurfLights;
|
||||
kexVec2 pt;
|
||||
|
||||
//
|
||||
// add lights from thing sources
|
||||
//
|
||||
for(int i = 0; i < numThings; ++i)
|
||||
{
|
||||
lightDef_t *lightDef = NULL;
|
||||
|
||||
thing = &mapThings[i];
|
||||
|
||||
for(j = 0; j < lightDefs.Length(); ++j)
|
||||
{
|
||||
if(thing->type == lightDefs[j].doomednum)
|
||||
{
|
||||
lightDef = &lightDefs[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!lightDef)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(lightDef->radius >= 0)
|
||||
{
|
||||
// ignore if all skills aren't set
|
||||
if(!(thing->options & 7))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
thingLight = new thingLight_t;
|
||||
|
||||
thingLight->mapThing = thing;
|
||||
thingLight->rgb = lightDef->rgb;
|
||||
thingLight->intensity = lightDef->intensity;
|
||||
thingLight->falloff = lightDef->falloff;
|
||||
thingLight->radius = lightDef->radius >= 0 ? lightDef->radius : thing->angle;
|
||||
thingLight->height = lightDef->height;
|
||||
thingLight->bCeiling = lightDef->bCeiling;
|
||||
thingLight->ssect = PointInSubSector(thing->x, thing->y);
|
||||
thingLight->sector = GetSectorFromSubSector(thingLight->ssect);
|
||||
|
||||
thingLight->origin.Set(thing->x, thing->y);
|
||||
thingLights.Push(thingLight);
|
||||
}
|
||||
|
||||
printf("Thing lights: %i\n", thingLights.Length());
|
||||
|
||||
numSurfLights = 0;
|
||||
|
||||
//
|
||||
// add surface lights
|
||||
//
|
||||
for(j = 0; j < surfaces.Length(); ++j)
|
||||
{
|
||||
surface_t *surface = surfaces[j];
|
||||
|
||||
for(unsigned int k = 0; k < surfaceLightDefs.Length(); ++k)
|
||||
{
|
||||
surfaceLightDef_t *surfaceLightDef = &surfaceLightDefs[k];
|
||||
|
||||
if(surface->type >= ST_MIDDLESEG && surface->type <= ST_LOWERSEG)
|
||||
{
|
||||
glSeg_t *seg = (glSeg_t*)surface->data;
|
||||
|
||||
if(mapLines[seg->linedef].tag == surfaceLightDef->tag)
|
||||
{
|
||||
kexLightSurface *lightSurface = new kexLightSurface;
|
||||
|
||||
lightSurface->Init(*surfaceLightDef, surface, true, false);
|
||||
lightSurface->CreateCenterOrigin();
|
||||
lightSurfaces.Push(lightSurface);
|
||||
numSurfLights++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mapSubSector_t *sub = surface->subSector;
|
||||
mapSector_t *sector = GetSectorFromSubSector(sub);
|
||||
|
||||
if(!sector || surface->numVerts <= 0)
|
||||
{
|
||||
// eh....
|
||||
continue;
|
||||
}
|
||||
|
||||
if(surface->type == ST_CEILING && surfaceLightDef->bIgnoreCeiling)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(surface->type == ST_FLOOR && surfaceLightDef->bIgnoreFloor)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(sector->tag == surfaceLightDef->tag)
|
||||
{
|
||||
kexLightSurface *lightSurface = new kexLightSurface;
|
||||
|
||||
lightSurface->Init(*surfaceLightDef, surface, false, surfaceLightDef->bNoCenterPoint);
|
||||
lightSurface->Subdivide(16);
|
||||
lightSurfaces.Push(lightSurface);
|
||||
numSurfLights++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Surface lights: %i\n", numSurfLights);
|
||||
}
|
||||
|
||||
//
|
||||
// kexDoomMap::CleanupThingLights
|
||||
//
|
||||
|
||||
void kexDoomMap::CleanupThingLights(void)
|
||||
{
|
||||
for(unsigned int i = 0; i < thingLights.Length(); i++)
|
||||
{
|
||||
delete thingLights[i];
|
||||
}
|
||||
}
|
276
src/lightmap/mapdata.h
Normal file
276
src/lightmap/mapdata.h
Normal file
|
@ -0,0 +1,276 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __MAPDATA_H__
|
||||
#define __MAPDATA_H__
|
||||
|
||||
#include "wad.h"
|
||||
#include "surfaces.h"
|
||||
#include "lightSurface.h"
|
||||
|
||||
#define NO_SIDE_INDEX -1
|
||||
#define NO_LINE_INDEX 0xFFFF
|
||||
#define NF_SUBSECTOR 0x8000
|
||||
|
||||
enum
|
||||
{
|
||||
BOXTOP,
|
||||
BOXBOTTOM,
|
||||
BOXLEFT,
|
||||
BOXRIGHT
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ML_BLOCKING = 1, // Solid, is an obstacle.
|
||||
ML_BLOCKMONSTERS = 2, // Blocks monsters only.
|
||||
ML_TWOSIDED = 4, // Backside will not be present at all if not two sided.
|
||||
ML_TRANSPARENT1 = 2048, // 25% or 75% transcluency?
|
||||
ML_TRANSPARENT2 = 4096 // 25% or 75% transcluency?
|
||||
} mapFlags_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
} mapVertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short textureoffset;
|
||||
short rowoffset;
|
||||
char toptexture[8];
|
||||
char bottomtexture[8];
|
||||
char midtexture[8];
|
||||
short sector;
|
||||
} mapSideDef_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short v1;
|
||||
short v2;
|
||||
short flags;
|
||||
short special;
|
||||
short tag;
|
||||
short sidenum[2]; // sidenum[1] will be -1 if one sided
|
||||
} mapLineDef_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short floorheight;
|
||||
short ceilingheight;
|
||||
char floorpic[8];
|
||||
char ceilingpic[8];
|
||||
short lightlevel;
|
||||
short special;
|
||||
short tag;
|
||||
} mapSector_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Partition line from (x,y) to x+dx,y+dy)
|
||||
short x;
|
||||
short y;
|
||||
short dx;
|
||||
short dy;
|
||||
|
||||
// Bounding box for each child,
|
||||
// clip against view frustum.
|
||||
short bbox[2][4];
|
||||
|
||||
// If NF_SUBSECTOR its a subsector,
|
||||
// else it's a node of another subtree.
|
||||
word children[2];
|
||||
} mapNode_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
word v1;
|
||||
word v2;
|
||||
short angle;
|
||||
word linedef;
|
||||
short side;
|
||||
short offset;
|
||||
} mapSeg_t;
|
||||
|
||||
typedef struct mapSubSector_s
|
||||
{
|
||||
word numsegs;
|
||||
word firstseg;
|
||||
} mapSubSector_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
short angle;
|
||||
short type;
|
||||
short options;
|
||||
} mapThing_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
} glVert_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
word v1;
|
||||
word v2;
|
||||
word linedef;
|
||||
int16_t side;
|
||||
word partner;
|
||||
} glSeg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
} vertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vertex_t *vertex;
|
||||
glSeg_t *seg;
|
||||
} leaf_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int doomednum;
|
||||
float height;
|
||||
float radius;
|
||||
float intensity;
|
||||
float falloff;
|
||||
bool bCeiling;
|
||||
kexVec3 rgb;
|
||||
} lightDef_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int map;
|
||||
int sunIgnoreTag;
|
||||
kexVec3 sunDir;
|
||||
kexVec3 sunColor;
|
||||
} mapDef_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mapThing_t *mapThing;
|
||||
kexVec2 origin;
|
||||
kexVec3 rgb;
|
||||
float intensity;
|
||||
float falloff;
|
||||
float height;
|
||||
float radius;
|
||||
bool bCeiling;
|
||||
mapSector_t *sector;
|
||||
mapSubSector_t *ssect;
|
||||
} thingLight_t;
|
||||
|
||||
class kexDoomMap
|
||||
{
|
||||
public:
|
||||
kexDoomMap(void);
|
||||
~kexDoomMap(void);
|
||||
|
||||
void BuildMapFromWad(kexWadFile &wadFile);
|
||||
mapSideDef_t *GetSideDef(const glSeg_t *seg);
|
||||
mapSector_t *GetFrontSector(const glSeg_t *seg);
|
||||
mapSector_t *GetBackSector(const glSeg_t *seg);
|
||||
mapSector_t *GetSectorFromSubSector(const mapSubSector_t *sub);
|
||||
mapSubSector_t *PointInSubSector(const int x, const int y);
|
||||
bool PointInsideSubSector(const float x, const float y, const mapSubSector_t *sub);
|
||||
bool LineIntersectSubSector(const kexVec3 &start, const kexVec3 &end,
|
||||
const mapSubSector_t *sub, kexVec2 &out);
|
||||
vertex_t *GetSegVertex(int index);
|
||||
bool CheckPVS(mapSubSector_t *s1, mapSubSector_t *s2);
|
||||
|
||||
void ParseConfigFile(const char *file);
|
||||
void CreateLights(void);
|
||||
void CleanupThingLights(void);
|
||||
|
||||
const kexVec3 &GetSunColor(void) const;
|
||||
const kexVec3 &GetSunDirection(void) const;
|
||||
|
||||
mapThing_t *mapThings;
|
||||
mapLineDef_t *mapLines;
|
||||
mapVertex_t *mapVerts;
|
||||
mapSideDef_t *mapSides;
|
||||
mapSector_t *mapSectors;
|
||||
glSeg_t *mapSegs;
|
||||
mapSubSector_t *mapSSects;
|
||||
mapNode_t *nodes;
|
||||
leaf_t *leafs;
|
||||
vertex_t *vertexes;
|
||||
byte *mapPVS;
|
||||
|
||||
bool *bSkySectors;
|
||||
bool *bSSectsVisibleToSky;
|
||||
|
||||
int numThings;
|
||||
int numLines;
|
||||
int numVerts;
|
||||
int numSides;
|
||||
int numSectors;
|
||||
int numSegs;
|
||||
int numSSects;
|
||||
int numNodes;
|
||||
int numLeafs;
|
||||
int numVertexes;
|
||||
|
||||
int *segLeafLookup;
|
||||
int *ssLeafLookup;
|
||||
int *ssLeafCount;
|
||||
kexBBox *ssLeafBounds;
|
||||
|
||||
kexBBox *nodeBounds;
|
||||
|
||||
surface_t **segSurfaces[3];
|
||||
surface_t **leafSurfaces[2];
|
||||
|
||||
kexArray<thingLight_t*> thingLights;
|
||||
kexArray<kexLightSurface*> lightSurfaces;
|
||||
|
||||
private:
|
||||
void BuildLeafs(void);
|
||||
void BuildNodeBounds(void);
|
||||
void CheckSkySectors(void);
|
||||
void BuildVertexes(kexWadFile &wadFile);
|
||||
void BuildPVS(void);
|
||||
|
||||
kexArray<lightDef_t> lightDefs;
|
||||
kexArray<surfaceLightDef_t> surfaceLightDefs;
|
||||
kexArray<mapDef_t> mapDefs;
|
||||
|
||||
mapDef_t *mapDef;
|
||||
|
||||
static const kexVec3 defaultSunColor;
|
||||
static const kexVec3 defaultSunDirection;
|
||||
};
|
||||
|
||||
#endif
|
364
src/lightmap/surfaces.cpp
Normal file
364
src/lightmap/surfaces.cpp
Normal file
|
@ -0,0 +1,364 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Prepares geometry from map structures
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "common.h"
|
||||
#include "surfaces.h"
|
||||
#include "mapData.h"
|
||||
|
||||
//#define EXPORT_OBJ
|
||||
|
||||
kexArray<surface_t*> surfaces;
|
||||
|
||||
//
|
||||
// Surface_AllocateFromSeg
|
||||
//
|
||||
|
||||
static void Surface_AllocateFromSeg(kexDoomMap &doomMap, glSeg_t *seg)
|
||||
{
|
||||
mapSideDef_t *side;
|
||||
surface_t *surf;
|
||||
float top, bTop;
|
||||
float bottom, bBottom;
|
||||
mapSector_t *front;
|
||||
mapSector_t *back;
|
||||
vertex_t *v1;
|
||||
vertex_t *v2;
|
||||
|
||||
if(seg->linedef == NO_LINE_INDEX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
side = doomMap.GetSideDef(seg);
|
||||
front = doomMap.GetFrontSector(seg);
|
||||
back = doomMap.GetBackSector(seg);
|
||||
|
||||
top = front->ceilingheight;
|
||||
bottom = front->floorheight;
|
||||
|
||||
v1 = doomMap.GetSegVertex(seg->v1);
|
||||
v2 = doomMap.GetSegVertex(seg->v2);
|
||||
|
||||
if(back)
|
||||
{
|
||||
bTop = back->ceilingheight;
|
||||
bBottom = back->floorheight;
|
||||
|
||||
if(bTop == top && bBottom == bottom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// bottom seg
|
||||
if(bottom < bBottom)
|
||||
{
|
||||
if(side->bottomtexture[0] != '-')
|
||||
{
|
||||
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
|
||||
surf->numVerts = 4;
|
||||
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * 4, hb_static);
|
||||
|
||||
surf->verts[0].x = surf->verts[2].x = v1->x;
|
||||
surf->verts[0].y = surf->verts[2].y = v1->y;
|
||||
surf->verts[1].x = surf->verts[3].x = v2->x;
|
||||
surf->verts[1].y = surf->verts[3].y = v2->y;
|
||||
surf->verts[0].z = surf->verts[1].z = bottom;
|
||||
surf->verts[2].z = surf->verts[3].z = bBottom;
|
||||
|
||||
surf->plane.SetNormal(surf->verts[0], surf->verts[1], surf->verts[2]);
|
||||
surf->plane.SetDistance(surf->verts[0]);
|
||||
surf->type = ST_LOWERSEG;
|
||||
surf->typeIndex = seg - doomMap.mapSegs;
|
||||
surf->subSector = &doomMap.mapSSects[doomMap.segLeafLookup[seg - doomMap.mapSegs]];
|
||||
|
||||
doomMap.segSurfaces[1][surf->typeIndex] = surf;
|
||||
surf->data = (glSeg_t*)seg;
|
||||
|
||||
surfaces.Push(surf);
|
||||
}
|
||||
|
||||
bottom = bBottom;
|
||||
}
|
||||
|
||||
// top seg
|
||||
if(top > bTop)
|
||||
{
|
||||
bool bSky = false;
|
||||
int frontidx = front-doomMap.mapSectors;
|
||||
int backidx = back-doomMap.mapSectors;
|
||||
|
||||
if(doomMap.bSkySectors[frontidx] && doomMap.bSkySectors[backidx])
|
||||
{
|
||||
if(front->ceilingheight != back->ceilingheight && side->toptexture[0] == '-')
|
||||
{
|
||||
bSky = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(side->toptexture[0] != '-' || bSky)
|
||||
{
|
||||
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
|
||||
surf->numVerts = 4;
|
||||
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * 4, hb_static);
|
||||
|
||||
surf->verts[0].x = surf->verts[2].x = v1->x;
|
||||
surf->verts[0].y = surf->verts[2].y = v1->y;
|
||||
surf->verts[1].x = surf->verts[3].x = v2->x;
|
||||
surf->verts[1].y = surf->verts[3].y = v2->y;
|
||||
surf->verts[0].z = surf->verts[1].z = bTop;
|
||||
surf->verts[2].z = surf->verts[3].z = top;
|
||||
|
||||
surf->plane.SetNormal(surf->verts[0], surf->verts[1], surf->verts[2]);
|
||||
surf->plane.SetDistance(surf->verts[0]);
|
||||
surf->type = ST_UPPERSEG;
|
||||
surf->typeIndex = seg - doomMap.mapSegs;
|
||||
surf->bSky = bSky;
|
||||
surf->subSector = &doomMap.mapSSects[doomMap.segLeafLookup[seg - doomMap.mapSegs]];
|
||||
|
||||
doomMap.segSurfaces[2][surf->typeIndex] = surf;
|
||||
surf->data = (glSeg_t*)seg;
|
||||
|
||||
surfaces.Push(surf);
|
||||
}
|
||||
|
||||
top = bTop;
|
||||
}
|
||||
}
|
||||
|
||||
// middle seg
|
||||
if(back == NULL)
|
||||
{
|
||||
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
|
||||
surf->numVerts = 4;
|
||||
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * 4, hb_static);
|
||||
|
||||
surf->verts[0].x = surf->verts[2].x = v1->x;
|
||||
surf->verts[0].y = surf->verts[2].y = v1->y;
|
||||
surf->verts[1].x = surf->verts[3].x = v2->x;
|
||||
surf->verts[1].y = surf->verts[3].y = v2->y;
|
||||
surf->verts[0].z = surf->verts[1].z = bottom;
|
||||
surf->verts[2].z = surf->verts[3].z = top;
|
||||
|
||||
surf->plane.SetNormal(surf->verts[0], surf->verts[1], surf->verts[2]);
|
||||
surf->plane.SetDistance(surf->verts[0]);
|
||||
surf->type = ST_MIDDLESEG;
|
||||
surf->typeIndex = seg - doomMap.mapSegs;
|
||||
surf->subSector = &doomMap.mapSSects[doomMap.segLeafLookup[seg - doomMap.mapSegs]];
|
||||
|
||||
doomMap.segSurfaces[0][surf->typeIndex] = surf;
|
||||
surf->data = (glSeg_t*)seg;
|
||||
|
||||
surfaces.Push(surf);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Surface_AllocateFromLeaf
|
||||
//
|
||||
// Plane normals should almost always be known
|
||||
// unless slopes are involved....
|
||||
//
|
||||
|
||||
static void Surface_AllocateFromLeaf(kexDoomMap &doomMap)
|
||||
{
|
||||
surface_t *surf;
|
||||
leaf_t *leaf;
|
||||
mapSector_t *sector = NULL;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
printf("------------- Building leaf surfaces -------------\n");
|
||||
|
||||
doomMap.leafSurfaces[0] = (surface_t**)Mem_Calloc(sizeof(surface_t*) *
|
||||
doomMap.numSSects, hb_static);
|
||||
doomMap.leafSurfaces[1] = (surface_t**)Mem_Calloc(sizeof(surface_t*) *
|
||||
doomMap.numSSects, hb_static);
|
||||
|
||||
for(i = 0; i < doomMap.numSSects; i++)
|
||||
{
|
||||
printf("subsectors: %i / %i\r", i+1, doomMap.numSSects);
|
||||
|
||||
if(doomMap.ssLeafCount[i] < 3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sector = doomMap.GetSectorFromSubSector(&doomMap.mapSSects[i]);
|
||||
|
||||
// I will be NOT surprised if some users tries to do something stupid with
|
||||
// sector hacks
|
||||
if(sector == NULL)
|
||||
{
|
||||
Error("Surface_AllocateFromLeaf: subsector %i has no sector\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
|
||||
surf->numVerts = doomMap.ssLeafCount[i];
|
||||
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * surf->numVerts, hb_static);
|
||||
surf->subSector = &doomMap.mapSSects[i];
|
||||
|
||||
// floor verts
|
||||
for(j = 0; j < surf->numVerts; j++)
|
||||
{
|
||||
leaf = &doomMap.leafs[doomMap.ssLeafLookup[i] + (surf->numVerts - 1) - j];
|
||||
|
||||
surf->verts[j].x = leaf->vertex->x;
|
||||
surf->verts[j].y = leaf->vertex->y;
|
||||
surf->verts[j].z = sector->floorheight;
|
||||
}
|
||||
|
||||
surf->plane.SetNormal(kexVec3(0, 0, 1));
|
||||
surf->plane.SetDistance(surf->verts[0]);
|
||||
surf->type = ST_FLOOR;
|
||||
surf->typeIndex = i;
|
||||
|
||||
doomMap.leafSurfaces[0][i] = surf;
|
||||
surf->data = (mapSector_t*)sector;
|
||||
|
||||
surfaces.Push(surf);
|
||||
|
||||
surf = (surface_t*)Mem_Calloc(sizeof(surface_t), hb_static);
|
||||
surf->numVerts = doomMap.ssLeafCount[i];
|
||||
surf->verts = (kexVec3*)Mem_Calloc(sizeof(kexVec3) * surf->numVerts, hb_static);
|
||||
surf->subSector = &doomMap.mapSSects[i];
|
||||
|
||||
if(doomMap.bSkySectors[sector-doomMap.mapSectors])
|
||||
{
|
||||
surf->bSky = true;
|
||||
}
|
||||
|
||||
// ceiling verts
|
||||
for(j = 0; j < surf->numVerts; j++)
|
||||
{
|
||||
leaf = &doomMap.leafs[doomMap.ssLeafLookup[i] + j];
|
||||
|
||||
surf->verts[j].x = leaf->vertex->x;
|
||||
surf->verts[j].y = leaf->vertex->y;
|
||||
surf->verts[j].z = sector->ceilingheight;
|
||||
}
|
||||
|
||||
surf->plane.SetNormal(kexVec3(0, 0, -1));
|
||||
surf->plane.SetDistance(surf->verts[0]);
|
||||
surf->type = ST_CEILING;
|
||||
surf->typeIndex = i;
|
||||
|
||||
doomMap.leafSurfaces[1][i] = surf;
|
||||
surf->data = (mapSector_t*)sector;
|
||||
|
||||
surfaces.Push(surf);
|
||||
}
|
||||
|
||||
printf("\nLeaf surfaces: %i\n", surfaces.Length() - doomMap.numSSects);
|
||||
}
|
||||
|
||||
//
|
||||
// Surface_AllocateFromMap
|
||||
//
|
||||
|
||||
void Surface_AllocateFromMap(kexDoomMap &doomMap)
|
||||
{
|
||||
doomMap.segSurfaces[0] = (surface_t**)Mem_Calloc(sizeof(surface_t*) *
|
||||
doomMap.numSegs, hb_static);
|
||||
doomMap.segSurfaces[1] = (surface_t**)Mem_Calloc(sizeof(surface_t*) *
|
||||
doomMap.numSegs, hb_static);
|
||||
doomMap.segSurfaces[2] = (surface_t**)Mem_Calloc(sizeof(surface_t*) *
|
||||
doomMap.numSegs, hb_static);
|
||||
|
||||
printf("------------- Building seg surfaces -------------\n");
|
||||
|
||||
for(int i = 0; i < doomMap.numSegs; i++)
|
||||
{
|
||||
Surface_AllocateFromSeg(doomMap, &doomMap.mapSegs[i]);
|
||||
printf("segs: %i / %i\r", i+1, doomMap.numSegs);
|
||||
}
|
||||
|
||||
printf("\nSeg surfaces: %i\n", surfaces.Length());
|
||||
|
||||
#ifdef EXPORT_OBJ
|
||||
FILE *f = fopen("level.obj", "w");
|
||||
int curLen = surfaces.Length();
|
||||
for(unsigned int i = 0; i < surfaces.Length(); i++)
|
||||
{
|
||||
for(int j = 0; j < surfaces[i]->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "v %f %f %f\n",
|
||||
-surfaces[i]->verts[j].y / 256.0f,
|
||||
surfaces[i]->verts[j].z / 256.0f,
|
||||
-surfaces[i]->verts[j].x / 256.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int tri;
|
||||
|
||||
for(unsigned int i = 0; i < surfaces.Length(); i++)
|
||||
{
|
||||
fprintf(f, "o surf%i_seg%i\n", i, i);
|
||||
fprintf(f, "f %i %i %i\n", 0+(i*4)+1, 1+(i*4)+1, 2+(i*4)+1);
|
||||
fprintf(f, "f %i %i %i\n", 1+(i*4)+1, 3+(i*4)+1, 2+(i*4)+1);
|
||||
|
||||
tri = 3+(i*4)+1;
|
||||
}
|
||||
|
||||
tri++;
|
||||
#endif
|
||||
|
||||
Surface_AllocateFromLeaf(doomMap);
|
||||
|
||||
printf("Surfaces total: %i\n\n", surfaces.Length());
|
||||
|
||||
#ifdef EXPORT_OBJ
|
||||
for(unsigned int i = curLen; i < surfaces.Length(); i++)
|
||||
{
|
||||
for(int j = 0; j < surfaces[i]->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "v %f %f %f\n",
|
||||
-surfaces[i]->verts[j].y / 256.0f,
|
||||
surfaces[i]->verts[j].z / 256.0f,
|
||||
-surfaces[i]->verts[j].x / 256.0f);
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int i = curLen; i < surfaces.Length(); i++)
|
||||
{
|
||||
fprintf(f, "o surf%i_ssect%i\n", i, i - curLen);
|
||||
fprintf(f, "f ");
|
||||
for(int j = 0; j < surfaces[i]->numVerts; j++)
|
||||
{
|
||||
fprintf(f, "%i ", tri++);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
#endif
|
||||
}
|
73
src/lightmap/surfaces.h
Normal file
73
src/lightmap/surfaces.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __SURFACES_H__
|
||||
#define __SURFACES_H__
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ST_UNKNOWN = 0,
|
||||
ST_MIDDLESEG,
|
||||
ST_UPPERSEG,
|
||||
ST_LOWERSEG,
|
||||
ST_CEILING,
|
||||
ST_FLOOR
|
||||
} surfaceType_t;
|
||||
|
||||
typedef kexArray<kexVec3> vertexBatch_t;
|
||||
|
||||
// convert from fixed point(FRACUNIT) to floating point
|
||||
#define F(x) (((float)(x))/65536.0f)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
kexPlane plane;
|
||||
int lightmapNum;
|
||||
int lightmapOffs[2];
|
||||
int lightmapDims[2];
|
||||
kexVec3 lightmapOrigin;
|
||||
kexVec3 lightmapSteps[2];
|
||||
kexVec3 textureCoords[2];
|
||||
kexBBox bounds;
|
||||
int numVerts;
|
||||
kexVec3 *verts;
|
||||
float *lightmapCoords;
|
||||
surfaceType_t type;
|
||||
int typeIndex;
|
||||
void *data;
|
||||
bool bSky;
|
||||
struct mapSubSector_s *subSector;
|
||||
} surface_t;
|
||||
|
||||
extern kexArray<surface_t*> surfaces;
|
||||
|
||||
class kexDoomMap;
|
||||
class kexWadFile;
|
||||
|
||||
void Surface_AllocateFromMap(kexDoomMap &doomMap);
|
||||
|
||||
#endif
|
285
src/lightmap/trace.cpp
Normal file
285
src/lightmap/trace.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: General class module for handling ray tracing of the
|
||||
// world geometry. Ideally, all of this needs to be revisited...
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "common.h"
|
||||
#include "mapData.h"
|
||||
#include "trace.h"
|
||||
|
||||
//
|
||||
// kexTrace::kexTrace
|
||||
//
|
||||
|
||||
kexTrace::kexTrace(void)
|
||||
{
|
||||
this->map = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// kexTrace::~kexTrace
|
||||
//
|
||||
|
||||
kexTrace::~kexTrace(void)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexTrace::Init
|
||||
//
|
||||
|
||||
void kexTrace::Init(kexDoomMap &doomMap)
|
||||
{
|
||||
map = &doomMap;
|
||||
}
|
||||
|
||||
//
|
||||
// kexTrace::Trace
|
||||
//
|
||||
|
||||
void kexTrace::Trace(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||
{
|
||||
start = startVec;
|
||||
end = endVec;
|
||||
dir = (end - start).Normalize();
|
||||
hitNormal.Clear();
|
||||
hitVector.Clear();
|
||||
hitSurface = NULL;
|
||||
fraction = 1;
|
||||
|
||||
if(map == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TraceBSPNode(map->numNodes - 1);
|
||||
}
|
||||
|
||||
//
|
||||
// kexTrace::TraceSurface
|
||||
//
|
||||
|
||||
void kexTrace::TraceSurface(surface_t *surface)
|
||||
{
|
||||
kexPlane *plane;
|
||||
kexVec3 hit;
|
||||
kexVec3 edge1;
|
||||
kexVec3 edge2;
|
||||
kexVec3 normal;
|
||||
float d1;
|
||||
float d2;
|
||||
float d;
|
||||
float frac;
|
||||
int i;
|
||||
kexPluecker r;
|
||||
|
||||
if(surface == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
plane = &surface->plane;
|
||||
|
||||
d1 = plane->Distance(start) - plane->d;
|
||||
d2 = plane->Distance(end) - plane->d;
|
||||
|
||||
if(d1 <= d2 || d1 < 0 || d2 > 0)
|
||||
{
|
||||
// trace is either completely in front or behind the plane
|
||||
return;
|
||||
}
|
||||
|
||||
frac = (d1 / (d1 - d2));
|
||||
|
||||
if(frac > 1 || frac < 0)
|
||||
{
|
||||
// not a valid contact
|
||||
return;
|
||||
}
|
||||
|
||||
if(frac >= fraction)
|
||||
{
|
||||
// farther than the current contact
|
||||
return;
|
||||
}
|
||||
|
||||
hit = start.Lerp(end, frac);
|
||||
normal = plane->Normal();
|
||||
|
||||
r.SetRay(start, dir);
|
||||
|
||||
// segs are always made up of 4 vertices, so its safe to assume 4 edges here
|
||||
if(surface->type >= ST_MIDDLESEG && surface->type <= ST_LOWERSEG)
|
||||
{
|
||||
kexPluecker p1;
|
||||
kexPluecker p2;
|
||||
kexPluecker p3;
|
||||
kexPluecker p4;
|
||||
byte sideBits = 0;
|
||||
|
||||
p1.SetLine(surface->verts[2], surface->verts[3]); // top edge
|
||||
p2.SetLine(surface->verts[1], surface->verts[0]); // bottom edge
|
||||
p3.SetLine(surface->verts[3], surface->verts[1]); // right edge
|
||||
p4.SetLine(surface->verts[0], surface->verts[2]); // left edge
|
||||
|
||||
// this sucks so much..... I am surprised this even works at all
|
||||
d = r.InnerProduct(p1)-0.001f;
|
||||
sideBits |= (FLOATSIGNBIT(d) << 0);
|
||||
d = r.InnerProduct(p2)-0.001f;
|
||||
sideBits |= (FLOATSIGNBIT(d) << 1);
|
||||
d = r.InnerProduct(p3)-0.001f;
|
||||
sideBits |= (FLOATSIGNBIT(d) << 2);
|
||||
d = r.InnerProduct(p4)-0.001f;
|
||||
sideBits |= (FLOATSIGNBIT(d) << 3);
|
||||
|
||||
if(sideBits != 0xF)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(surface->type == ST_FLOOR || surface->type == ST_CEILING)
|
||||
{
|
||||
kexPluecker p;
|
||||
kexVec3 v1;
|
||||
kexVec3 v2;
|
||||
|
||||
for(i = 0; i < surface->numVerts; i++)
|
||||
{
|
||||
v1 = surface->verts[i];
|
||||
v2 = surface->verts[(i+1)%surface->numVerts];
|
||||
|
||||
p.SetLine(v2, v1);
|
||||
|
||||
if(r.InnerProduct(p) > 0.01f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hitNormal = normal;
|
||||
hitVector = hit;
|
||||
hitSurface = surface;
|
||||
fraction = frac;
|
||||
}
|
||||
|
||||
//
|
||||
// kexTrace::TraceSubSector
|
||||
//
|
||||
|
||||
void kexTrace::TraceSubSector(int num)
|
||||
{
|
||||
mapSubSector_t *sub;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sub = &map->mapSSects[num];
|
||||
|
||||
if(!map->ssLeafBounds[num].LineIntersect(start, end))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// test line segments
|
||||
for(i = 0; i < sub->numsegs; i++)
|
||||
{
|
||||
int segnum = sub->firstseg + i;
|
||||
|
||||
for(j = 0; j < 3; j++)
|
||||
{
|
||||
if(j == 0)
|
||||
{
|
||||
int linenum = map->mapSegs[segnum].linedef;
|
||||
|
||||
if(linenum != NO_LINE_INDEX && map->mapLines[linenum].flags &
|
||||
(ML_TWOSIDED|ML_TRANSPARENT1|ML_TRANSPARENT2))
|
||||
{
|
||||
// don't trace transparent 2-sided lines
|
||||
continue;
|
||||
}
|
||||
}
|
||||
TraceSurface(map->segSurfaces[j][segnum]);
|
||||
}
|
||||
}
|
||||
|
||||
// test subsector leafs
|
||||
for(j = 0; j < 2; j++)
|
||||
{
|
||||
TraceSurface(map->leafSurfaces[j][num]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexTrace::TraceBSPNode
|
||||
//
|
||||
|
||||
void kexTrace::TraceBSPNode(int num)
|
||||
{
|
||||
mapNode_t *node;
|
||||
kexVec3 dp1;
|
||||
kexVec3 dp2;
|
||||
float d;
|
||||
byte side;
|
||||
|
||||
if(num & NF_SUBSECTOR)
|
||||
{
|
||||
TraceSubSector(num & (~NF_SUBSECTOR));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!map->nodeBounds[num & (~NF_SUBSECTOR)].LineIntersect(start, end))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
node = &map->nodes[num];
|
||||
|
||||
kexVec3 pt1(F(node->x << 16), F(node->y << 16), 0);
|
||||
kexVec3 pt2(F(node->dx << 16), F(node->dy << 16), 0);
|
||||
|
||||
dp1 = pt1 - start;
|
||||
dp2 = (pt2 + pt1) - start;
|
||||
d = dp1.Cross(dp2).z;
|
||||
|
||||
side = FLOATSIGNBIT(d);
|
||||
|
||||
TraceBSPNode(node->children[side ^ 1]);
|
||||
|
||||
dp1 = pt1 - end;
|
||||
dp2 = (pt2 + pt1) - end;
|
||||
d = dp1.Cross(dp2).z;
|
||||
|
||||
// don't trace if both ends of the ray are on the same side
|
||||
if(side != FLOATSIGNBIT(d))
|
||||
{
|
||||
TraceBSPNode(node->children[side]);
|
||||
}
|
||||
}
|
59
src/lightmap/trace.h
Normal file
59
src/lightmap/trace.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __TRACE_H__
|
||||
#define __TRACE_H__
|
||||
|
||||
class kexDoomMap;
|
||||
|
||||
class kexTrace
|
||||
{
|
||||
public:
|
||||
kexTrace(void);
|
||||
~kexTrace(void);
|
||||
|
||||
void Init(kexDoomMap &doomMap);
|
||||
void Trace(const kexVec3 &startVec, const kexVec3 &endVec);
|
||||
|
||||
kexVec3 start;
|
||||
kexVec3 end;
|
||||
kexVec3 dir;
|
||||
kexVec3 hitNormal;
|
||||
kexVec3 hitVector;
|
||||
surface_t *hitSurface;
|
||||
float fraction;
|
||||
|
||||
private:
|
||||
void TraceBSPNode(int num);
|
||||
void TraceSubSector(int num);
|
||||
void TraceSurface(surface_t *surface);
|
||||
|
||||
kexDoomMap *map;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
326
src/lightmap/wad.cpp
Normal file
326
src/lightmap/wad.cpp
Normal file
|
@ -0,0 +1,326 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: General wad loading mechanics
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "common.h"
|
||||
#include "wad.h"
|
||||
|
||||
//
|
||||
// kexWadFile::~kexWadFile
|
||||
//
|
||||
|
||||
kexWadFile::~kexWadFile(void)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::Open
|
||||
//
|
||||
|
||||
bool kexWadFile::Open(const char *fileName)
|
||||
{
|
||||
if(!file.Open(fileName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(&header, file.Buffer(), sizeof(wadHeader_t));
|
||||
lumps = (lump_t*)file.GetOffset(2);
|
||||
wadName = fileName;
|
||||
bWriting = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::Write
|
||||
//
|
||||
|
||||
void kexWadFile::Write(const char *fileName)
|
||||
{
|
||||
assert(bWriting == true);
|
||||
|
||||
file.Create(fileName);
|
||||
file.Write8(header.id[0]);
|
||||
file.Write8(header.id[1]);
|
||||
file.Write8(header.id[2]);
|
||||
file.Write8(header.id[3]);
|
||||
file.Write32(header.lmpcount);
|
||||
file.Write32(header.lmpdirpos);
|
||||
|
||||
for(unsigned int i = 0; i < writeLumpList.Length(); i++)
|
||||
{
|
||||
byte *data = writeDataList[i];
|
||||
|
||||
if(!data)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int j = 0; j < writeLumpList[i].size; j++)
|
||||
{
|
||||
file.Write8(data[j]);
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < writeLumpList.Length(); i++)
|
||||
{
|
||||
file.Write32(writeLumpList[i].filepos);
|
||||
file.Write32(writeLumpList[i].size);
|
||||
for(int j = 0; j < 8; j++)
|
||||
{
|
||||
file.Write8(writeLumpList[i].name[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::Close
|
||||
//
|
||||
|
||||
void kexWadFile::Close(void)
|
||||
{
|
||||
if(file.Opened())
|
||||
{
|
||||
file.Close();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::GetLumpFromName
|
||||
//
|
||||
|
||||
lump_t *kexWadFile::GetLumpFromName(const char *name)
|
||||
{
|
||||
char n[9];
|
||||
|
||||
for(int i = 0; i < header.lmpcount; i++)
|
||||
{
|
||||
// could be optimized here but I really don't feel like
|
||||
// wasting time on this
|
||||
strncpy(n, lumps[i].name, 8);
|
||||
n[8] = 0;
|
||||
|
||||
if(!strncmp(n, name, 8))
|
||||
{
|
||||
return &lumps[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::GetLumpData
|
||||
//
|
||||
|
||||
byte *kexWadFile::GetLumpData(const lump_t *lump)
|
||||
{
|
||||
file.SetOffset(lump->filepos);
|
||||
return &file.Buffer()[lump->filepos];
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::GetLumpData
|
||||
//
|
||||
|
||||
byte *kexWadFile::GetLumpData(const char *name)
|
||||
{
|
||||
lump_t *lump = GetLumpFromName(name);
|
||||
|
||||
if(!lump)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.SetOffset(lump->filepos);
|
||||
return &file.Buffer()[lump->filepos];
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::SetCurrentMap
|
||||
//
|
||||
|
||||
void kexWadFile::SetCurrentMap(const int map)
|
||||
{
|
||||
lump_t *lump = GetLumpFromName(Va("MAP%02d", map));
|
||||
|
||||
if(lump == NULL)
|
||||
{
|
||||
Error("kexWadFile::SetCurrentMap: MAP%02d not found\n", map);
|
||||
return;
|
||||
}
|
||||
|
||||
mapLumpID = lump - lumps;
|
||||
|
||||
lump = GetLumpFromName(Va("GL_MAP%02d", map));
|
||||
|
||||
if(lump == NULL)
|
||||
{
|
||||
Error("kexWadFile::SetCurrentMap: GL_MAP%02d not found\n", map);
|
||||
return;
|
||||
}
|
||||
|
||||
glMapLumpID = lump - lumps;
|
||||
currentmap = map;
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::GetMapLump
|
||||
//
|
||||
|
||||
lump_t *kexWadFile::GetMapLump(mapLumps_t lumpID)
|
||||
{
|
||||
if(mapLumpID + lumpID >= header.lmpcount)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &lumps[mapLumpID + lumpID];
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::GetGLMapLump
|
||||
//
|
||||
|
||||
lump_t *kexWadFile::GetGLMapLump(glMapLumps_t lumpID)
|
||||
{
|
||||
if(glMapLumpID + lumpID >= header.lmpcount)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &lumps[glMapLumpID + lumpID];
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::InitForWrite
|
||||
//
|
||||
|
||||
void kexWadFile::InitForWrite(void)
|
||||
{
|
||||
header.id[0] = 'P';
|
||||
header.id[1] = 'W';
|
||||
header.id[2] = 'A';
|
||||
header.id[3] = 'D';
|
||||
|
||||
writePos = sizeof(wadHeader_t);
|
||||
bWriting = true;
|
||||
|
||||
header.lmpcount = 0;
|
||||
header.lmpdirpos = writePos;
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::CopyLumpsFromWadFile
|
||||
//
|
||||
|
||||
void kexWadFile::CopyLumpsFromWadFile(kexWadFile &wadFile)
|
||||
{
|
||||
lump_t lump;
|
||||
|
||||
assert(bWriting == true);
|
||||
|
||||
for(int i = 0; i < wadFile.header.lmpcount; ++i)
|
||||
{
|
||||
lump = wadFile.lumps[i];
|
||||
AddLump(wadFile.lumps[i].name, lump.size, &wadFile.file.Buffer()[lump.filepos]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::CopyLumpsFromWadFile
|
||||
//
|
||||
|
||||
void kexWadFile::CopyLumpsFromWadFile(kexWadFile &wadFile, kexArray<int> &lumpIgnoreList)
|
||||
{
|
||||
lump_t lump;
|
||||
unsigned int j;
|
||||
bool bSkip;
|
||||
|
||||
assert(bWriting == true);
|
||||
|
||||
for(int i = 0; i < wadFile.header.lmpcount; ++i)
|
||||
{
|
||||
lump = wadFile.lumps[i];
|
||||
bSkip = false;
|
||||
|
||||
for(j = 0; j < lumpIgnoreList.Length(); ++j)
|
||||
{
|
||||
if(lumpIgnoreList[j] == i)
|
||||
{
|
||||
bSkip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(bSkip)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AddLump(wadFile.lumps[i].name, lump.size, &wadFile.file.Buffer()[lump.filepos]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::AddLump
|
||||
//
|
||||
|
||||
void kexWadFile::AddLump(const char *name, const int size, byte *data)
|
||||
{
|
||||
lump_t lump;
|
||||
|
||||
assert(bWriting == true);
|
||||
|
||||
lump.filepos = writePos;
|
||||
lump.size = size;
|
||||
strncpy(lump.name, name, 8);
|
||||
|
||||
writeLumpList.Push(lump);
|
||||
writeDataList.Push(data);
|
||||
|
||||
header.lmpcount++;
|
||||
header.lmpdirpos += lump.size;
|
||||
writePos += lump.size;
|
||||
}
|
||||
|
||||
//
|
||||
// kexWadFile::CreateBackup
|
||||
//
|
||||
|
||||
void kexWadFile::CreateBackup(void)
|
||||
{
|
||||
kexStr backupName = wadName;
|
||||
|
||||
backupName.StripExtension();
|
||||
file.Duplicate(backupName + ".wad.bak");
|
||||
}
|
164
src/lightmap/wad.h
Normal file
164
src/lightmap/wad.h
Normal file
|
@ -0,0 +1,164 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __WAD_H__
|
||||
#define __WAD_H__
|
||||
|
||||
#include "kexlib/binFile.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ML_HEADER = 0,
|
||||
ML_THINGS,
|
||||
ML_LINEDEFS,
|
||||
ML_SIDEDEFS,
|
||||
ML_VERTEXES,
|
||||
ML_SEGS,
|
||||
ML_SUBSECTORS,
|
||||
ML_NODES,
|
||||
ML_SECTORS,
|
||||
ML_REJECT,
|
||||
ML_BLOCKMAP,
|
||||
ML_LIGHTMAP,
|
||||
ML_NUMLUMPS
|
||||
} mapLumps_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ML_GL_LABEL = 0, // A separator name, GL_ExMx or GL_MAPxx
|
||||
ML_GL_VERTS, // Extra Vertices
|
||||
ML_GL_SEGS, // Segs, from linedefs & minisegs
|
||||
ML_GL_SSECT, // SubSectors, list of segs
|
||||
ML_GL_NODES, // GL BSP nodes
|
||||
ML_GL_PVS // PVS portals
|
||||
} glMapLumps_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ML_LM_LABEL = 0,
|
||||
ML_LM_CELLS,
|
||||
ML_LM_SUN,
|
||||
ML_LM_SURFS,
|
||||
ML_LM_TXCRD,
|
||||
ML_LM_LMAPS
|
||||
} lmMapLumps_t;
|
||||
|
||||
#define gNd2 0x32644E67
|
||||
|
||||
#define GL_VERT_OFFSET 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char id[4];
|
||||
int lmpcount;
|
||||
int lmpdirpos;
|
||||
} wadHeader_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int filepos;
|
||||
int size;
|
||||
char name[8];
|
||||
} lump_t;
|
||||
|
||||
class kexWadFile
|
||||
{
|
||||
public:
|
||||
~kexWadFile(void);
|
||||
|
||||
wadHeader_t header;
|
||||
lump_t *lumps;
|
||||
unsigned int size;
|
||||
int mapLumpID;
|
||||
int glMapLumpID;
|
||||
kexStr wadName;
|
||||
int currentmap;
|
||||
|
||||
lump_t *GetLumpFromName(const char *name);
|
||||
lump_t *GetMapLump(mapLumps_t lumpID);
|
||||
lump_t *GetGLMapLump(glMapLumps_t lumpID);
|
||||
byte *GetLumpData(const lump_t *lump);
|
||||
byte *GetLumpData(const char *name);
|
||||
void SetCurrentMap(const int map);
|
||||
bool Open(const char *fileName);
|
||||
void Write(const char *fileName);
|
||||
void Close(void);
|
||||
void CreateBackup(void);
|
||||
void InitForWrite(void);
|
||||
void CopyLumpsFromWadFile(kexWadFile &wadFile);
|
||||
void CopyLumpsFromWadFile(kexWadFile &wadFile, kexArray<int> &lumpIgnoreList);
|
||||
void AddLump(const char *name, const int size, byte *data);
|
||||
|
||||
template<typename type>
|
||||
void GetMapLump(mapLumps_t lumpID, type **ptr, int *count)
|
||||
{
|
||||
if(mapLumpID + lumpID >= header.lmpcount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lump_t *lump = GetMapLump(lumpID);
|
||||
if(lump == NULL || lump->size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*ptr = (type*)GetLumpData(lump);
|
||||
|
||||
if(count)
|
||||
{
|
||||
*count = lump->size / sizeof(type);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename type>
|
||||
void GetGLMapLump(glMapLumps_t lumpID, type **ptr, int *count)
|
||||
{
|
||||
if(glMapLumpID + lumpID >= header.lmpcount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lump_t *lump = GetGLMapLump(lumpID);
|
||||
if(lump == NULL || lump->size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*ptr = (type*)GetLumpData(lump);
|
||||
|
||||
if(count)
|
||||
{
|
||||
*count = lump->size / sizeof(type);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
kexBinFile file;
|
||||
bool bWriting;
|
||||
int writePos;
|
||||
kexArray<lump_t> writeLumpList;
|
||||
kexArray<byte*> writeDataList;
|
||||
};
|
||||
|
||||
#endif
|
418
src/lightmap/worker.cpp
Normal file
418
src/lightmap/worker.cpp
Normal file
|
@ -0,0 +1,418 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// DESCRIPTION: Worker Threads
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "common.h"
|
||||
#include "worker.h"
|
||||
|
||||
int kexWorker::maxWorkThreads = MAX_THREADS;
|
||||
|
||||
//
|
||||
// WorkThread
|
||||
//
|
||||
|
||||
void *WorkThread(void *p)
|
||||
{
|
||||
jobFuncArgs_t *args = (jobFuncArgs_t*)p;
|
||||
kexWorker *worker = args->worker;
|
||||
|
||||
while(1)
|
||||
{
|
||||
int jobid;
|
||||
|
||||
worker->LockMutex();
|
||||
|
||||
if(worker->FinishedAllJobs())
|
||||
{
|
||||
worker->UnlockMutex();
|
||||
break;
|
||||
}
|
||||
|
||||
jobid = worker->DispatchJob();
|
||||
worker->UnlockMutex();
|
||||
|
||||
worker->RunJob(args->data, jobid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// kexWorker::kexWorker
|
||||
//
|
||||
|
||||
kexWorker::kexWorker(void)
|
||||
{
|
||||
this->numWorkLoad = 0;
|
||||
this->jobsWorked = 0;
|
||||
this->job = NULL;
|
||||
|
||||
memset(this->jobArgs, 0, sizeof(this->jobArgs));
|
||||
}
|
||||
|
||||
//
|
||||
// kexWorker::~kexWorker
|
||||
//
|
||||
|
||||
kexWorker::~kexWorker(void)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexWorker::LockMutex
|
||||
//
|
||||
|
||||
void kexWorker::LockMutex(void)
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
//
|
||||
// kexWorker::UnlockMutex
|
||||
//
|
||||
|
||||
void kexWorker::UnlockMutex(void)
|
||||
{
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
//
|
||||
// kexWorker::Destroy
|
||||
//
|
||||
|
||||
void kexWorker::Destroy(void)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// kexWorker::RunThreads
|
||||
//
|
||||
|
||||
void kexWorker::RunThreads(const int count, void *data, jobFunc_t jobFunc)
|
||||
{
|
||||
job = jobFunc;
|
||||
numWorkLoad = count;
|
||||
jobsWorked = 0;
|
||||
|
||||
for(int i = 0; i < kexWorker::maxWorkThreads; ++i)
|
||||
{
|
||||
jobArgs[i].worker = this;
|
||||
jobArgs[i].jobID = i;
|
||||
jobArgs[i].data = data;
|
||||
|
||||
threads[i] = std::thread([=]() { WorkThread(&jobArgs[i]); });
|
||||
}
|
||||
|
||||
for(int i = 0; i < kexWorker::maxWorkThreads; ++i)
|
||||
{
|
||||
threads[i].join();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Stuff from old main.cpp
|
||||
|
||||
static kexStr basePath;
|
||||
|
||||
void Error(const char *error, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
||||
va_start(argptr, error);
|
||||
vprintf(error, argptr);
|
||||
va_end(argptr);
|
||||
printf("\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *Va(const char *str, ...)
|
||||
{
|
||||
va_list v;
|
||||
static char vastr[1024];
|
||||
|
||||
va_start(v, str);
|
||||
vsprintf(vastr, str, v);
|
||||
va_end(v);
|
||||
|
||||
return vastr;
|
||||
}
|
||||
|
||||
void Delay(int ms)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||
}
|
||||
|
||||
//
|
||||
// GetSeconds
|
||||
//
|
||||
|
||||
const int64_t GetSeconds(void)
|
||||
{
|
||||
return time(0);
|
||||
}
|
||||
|
||||
//
|
||||
// FilePath
|
||||
//
|
||||
|
||||
const kexStr &FilePath(void)
|
||||
{
|
||||
return basePath;
|
||||
}
|
||||
|
||||
//
|
||||
// Main
|
||||
//
|
||||
|
||||
#if 0
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
kexWadFile wadFile;
|
||||
kexWadFile outWadFile;
|
||||
kexDoomMap doomMap;
|
||||
lump_t *lmLump;
|
||||
kexArray<int> ignoreLumps;
|
||||
kexLightmapBuilder builder;
|
||||
kexStr configFile("strife_sve.cfg");
|
||||
bool bWriteTGA;
|
||||
int map = 1;
|
||||
int arg = 1;
|
||||
|
||||
printf("DLight (c) 2013-2014 Samuel Villarreal\n\n");
|
||||
|
||||
if (argc < 1 || argv[1] == NULL)
|
||||
{
|
||||
printf("Usage: dlight [options] [wadfile]\n");
|
||||
printf("Use -help for list of options\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
basePath = argv[0];
|
||||
basePath.StripFile();
|
||||
|
||||
bWriteTGA = false;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!strcmp(argv[arg], "-help"))
|
||||
{
|
||||
printf("Options:\n");
|
||||
printf("-help: displays all known options\n");
|
||||
printf("-map: process lightmap for MAP##\n");
|
||||
printf("-samples: set texel sampling size (lowest = higher quaility but\n");
|
||||
printf(" slow compile time) must be in powers of two\n");
|
||||
printf("-ambience: set global ambience value for lightmaps (0.0 - 1.0)\n");
|
||||
printf("-size: lightmap texture dimentions for width and height\n");
|
||||
printf(" must be in powers of two (1, 2, 4, 8, 16, etc)\n");
|
||||
printf("-threads: set total number of threads (1 min, 128 max)\n");
|
||||
printf("-config: specify a config file to parse (default: strife_sve.cfg)\n");
|
||||
printf("-writetga: dumps lightmaps to targa (.TGA) files\n");
|
||||
arg++;
|
||||
return 0;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-map"))
|
||||
{
|
||||
if (argv[arg + 1] == NULL)
|
||||
{
|
||||
Error("Specify map number for -map\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
map = atoi(argv[++arg]);
|
||||
arg++;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-samples"))
|
||||
{
|
||||
if (argv[arg + 1] == NULL)
|
||||
{
|
||||
Error("Specify value for -samples\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
builder.samples = atoi(argv[++arg]);
|
||||
if (builder.samples <= 0)
|
||||
{
|
||||
builder.samples = 1;
|
||||
}
|
||||
if (builder.samples > 128)
|
||||
{
|
||||
builder.samples = 128;
|
||||
}
|
||||
|
||||
builder.samples = kexMath::RoundPowerOfTwo(builder.samples);
|
||||
arg++;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-ambience"))
|
||||
{
|
||||
if (argv[arg + 1] == NULL)
|
||||
{
|
||||
Error("Specify value for -ambience\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
builder.ambience = (float)atof(argv[++arg]);
|
||||
if (builder.ambience < 0)
|
||||
{
|
||||
builder.ambience = 0;
|
||||
}
|
||||
if (builder.ambience > 1)
|
||||
{
|
||||
builder.ambience = 1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-size"))
|
||||
{
|
||||
int lmDims;
|
||||
|
||||
if (argv[arg + 1] == NULL)
|
||||
{
|
||||
Error("Specify value for -size\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
lmDims = atoi(argv[++arg]);
|
||||
if (lmDims <= 0)
|
||||
{
|
||||
lmDims = 1;
|
||||
}
|
||||
if (lmDims > LIGHTMAP_MAX_SIZE)
|
||||
{
|
||||
lmDims = LIGHTMAP_MAX_SIZE;
|
||||
}
|
||||
|
||||
lmDims = kexMath::RoundPowerOfTwo(lmDims);
|
||||
|
||||
builder.textureWidth = lmDims;
|
||||
builder.textureHeight = lmDims;
|
||||
arg++;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-threads"))
|
||||
{
|
||||
kexWorker::maxWorkThreads = atoi(argv[++arg]);
|
||||
kexMath::Clamp(kexWorker::maxWorkThreads, 1, MAX_THREADS);
|
||||
arg++;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-config"))
|
||||
{
|
||||
configFile = argv[++arg];
|
||||
arg++;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "-writetga"))
|
||||
{
|
||||
bWriteTGA = true;
|
||||
arg++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argv[arg] == NULL)
|
||||
{
|
||||
printf("Usage: dlight [options] [wadfile]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!wadFile.Open(argv[arg]))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// concat the base path to light def file if there is none
|
||||
if (configFile.IndexOf("\\") == -1 && configFile.IndexOf("/") == -1)
|
||||
{
|
||||
configFile = basePath + configFile;
|
||||
}
|
||||
|
||||
int starttime = (int)GetSeconds();
|
||||
|
||||
printf("---------------- Parsing config file ----------------\n\n");
|
||||
doomMap.ParseConfigFile(configFile.c_str());
|
||||
|
||||
printf("------------- Building level structures -------------\n\n");
|
||||
wadFile.SetCurrentMap(map);
|
||||
doomMap.BuildMapFromWad(wadFile);
|
||||
|
||||
printf("----------- Allocating surfaces from level ----------\n\n");
|
||||
Surface_AllocateFromMap(doomMap);
|
||||
|
||||
printf("---------------- Allocating lights ----------------\n\n");
|
||||
doomMap.CreateLights();
|
||||
|
||||
printf("---------------- Creating lightmaps ---------------\n\n");
|
||||
builder.CreateLightmaps(doomMap);
|
||||
doomMap.CleanupThingLights();
|
||||
|
||||
if (bWriteTGA)
|
||||
{
|
||||
builder.WriteTexturesToTGA();
|
||||
}
|
||||
|
||||
printf("------------------ Rebuilding wad ----------------\n\n");
|
||||
wadFile.CreateBackup();
|
||||
|
||||
lmLump = wadFile.GetLumpFromName(Va("LM_MAP%02d", wadFile.currentmap));
|
||||
|
||||
if (lmLump)
|
||||
{
|
||||
int lumpnum = lmLump - wadFile.lumps;
|
||||
|
||||
ignoreLumps.Push(lumpnum + ML_LM_LABEL);
|
||||
ignoreLumps.Push(lumpnum + ML_LM_CELLS);
|
||||
ignoreLumps.Push(lumpnum + ML_LM_SUN);
|
||||
ignoreLumps.Push(lumpnum + ML_LM_SURFS);
|
||||
ignoreLumps.Push(lumpnum + ML_LM_TXCRD);
|
||||
ignoreLumps.Push(lumpnum + ML_LM_LMAPS);
|
||||
}
|
||||
|
||||
outWadFile.InitForWrite();
|
||||
outWadFile.CopyLumpsFromWadFile(wadFile, ignoreLumps);
|
||||
outWadFile.AddLump(Va("LM_MAP%02d", wadFile.currentmap), 0, NULL);
|
||||
|
||||
builder.AddLightGridLump(outWadFile);
|
||||
builder.AddLightmapLumps(outWadFile);
|
||||
|
||||
printf("------------- Writing %s -------------\n\n", wadFile.wadName.c_str());
|
||||
outWadFile.Write(wadFile.wadName);
|
||||
outWadFile.Close();
|
||||
wadFile.Close();
|
||||
|
||||
printf("----------------- Shutting down -----------------\n\n");
|
||||
Mem_Purge(hb_static);
|
||||
|
||||
int proctime = (int)GetSeconds() - starttime;
|
||||
printf("\nBuild time: %d:%02d:%02d\n",
|
||||
proctime / 3600, (proctime / 60) % 60, proctime % 60);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
76
src/lightmap/worker.h
Normal file
76
src/lightmap/worker.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Note: this is a modified version of dlight. It is not the original software.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2013-2014 Samuel Villarreal
|
||||
// svkaiser@gmail.com
|
||||
//
|
||||
// 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 __WORKER_H__
|
||||
#define __WORKER_H__
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#define MAX_THREADS 128
|
||||
|
||||
class kexWorker;
|
||||
|
||||
typedef void(*jobFunc_t)(void*, int);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
kexWorker *worker;
|
||||
void *data;
|
||||
int jobID;
|
||||
} jobFuncArgs_t;
|
||||
|
||||
class kexWorker
|
||||
{
|
||||
public:
|
||||
kexWorker(void);
|
||||
~kexWorker(void);
|
||||
|
||||
void RunThreads(const int count, void *data, jobFunc_t jobFunc);
|
||||
void LockMutex(void);
|
||||
void UnlockMutex(void);
|
||||
void Destroy(void);
|
||||
|
||||
bool FinishedAllJobs(void) { return jobsWorked == numWorkLoad; }
|
||||
int DispatchJob(void) { int j = jobsWorked; jobsWorked++; return j; }
|
||||
void RunJob(void *data, const int jobID) { job(data, jobID); }
|
||||
|
||||
jobFuncArgs_t *Args(const int id) { return &jobArgs[id]; }
|
||||
const int JobsWorked(void) const { return jobsWorked; }
|
||||
|
||||
static int maxWorkThreads;
|
||||
|
||||
private:
|
||||
std::thread threads[MAX_THREADS];
|
||||
jobFuncArgs_t jobArgs[MAX_THREADS];
|
||||
std::mutex mutex;
|
||||
jobFunc_t job;
|
||||
int jobsWorked;
|
||||
int numWorkLoad;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue