Add dlight codebase to zdray

This commit is contained in:
Magnus Norddahl 2018-10-26 09:15:14 +02:00
parent b4f22e7959
commit 405bb743a0
35 changed files with 13189 additions and 1 deletions

View file

@ -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
View 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
View 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

View 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;
}

View 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

View 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());
}

View 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

View 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];
}

View 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];
}

View 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];
}

View 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

View 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;
}

View 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();
}

View 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];
}

View 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);
}

View 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;
}

File diff suppressed because it is too large Load diff

View 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;
}

View 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

File diff suppressed because it is too large Load diff

View 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

File diff suppressed because it is too large Load diff

93
src/lightmap/lightmap.h Normal file
View 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

View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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