Commit for 2018.05.24.7z
This commit is contained in:
parent
c9d201745e
commit
e9d10b530f
@ -264,6 +264,7 @@ int main(int argc, char** argv){
|
||||
client::render();
|
||||
ext::render();
|
||||
}
|
||||
|
||||
if ( !client::terminated ) {
|
||||
uf::iostream << "Natural termination!" << "\n";
|
||||
client::terminate();
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <uf/ext/ext.h>
|
||||
#include <uf/utils/window/window.h>
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
|
||||
namespace client {
|
||||
extern bool ready;
|
||||
|
@ -22,7 +22,7 @@ namespace uf {
|
||||
namespace physics {
|
||||
namespace time {
|
||||
UF_API uf::Timer<> timer;
|
||||
UF_API double current, previous, delta;
|
||||
UF_API double current, previous, delta, clamp;
|
||||
}
|
||||
void UF_API tick();
|
||||
template<typename T> pod::Transform<T>& update( pod::Transform<T>& transform, pod::Physics& physics );
|
||||
|
114
engine/inc/uf/utils/thread/thread.h
Normal file
114
engine/inc/uf/utils/thread/thread.h
Normal file
@ -0,0 +1,114 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/config.h>
|
||||
#include <uf/utils/time/time.h>
|
||||
#include <uf/utils/math/math.h>
|
||||
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace pod {
|
||||
struct UF_API Thread {
|
||||
typedef std::function<int()> function_t;
|
||||
typedef std::queue<pod::Thread::function_t> queue_t;
|
||||
typedef std::vector<pod::Thread::function_t> container_t;
|
||||
|
||||
uint uid;
|
||||
double limiter;
|
||||
std::string name;
|
||||
bool running, terminates;
|
||||
|
||||
std::mutex* mutex;
|
||||
std::thread thread;
|
||||
|
||||
pod::Thread::queue_t temps;
|
||||
pod::Thread::container_t consts;
|
||||
};
|
||||
}
|
||||
|
||||
namespace uf {
|
||||
namespace thread {
|
||||
/* Acts on thread */
|
||||
void UF_API start( pod::Thread& );
|
||||
void UF_API quit( pod::Thread& );
|
||||
|
||||
void UF_API tick( pod::Thread& );
|
||||
// void UF_API tick( pod::Thread&, const std::function<void()>& = NULL );
|
||||
|
||||
void UF_API add( pod::Thread&, const pod::Thread::function_t&, bool = false );
|
||||
void UF_API process( pod::Thread& );
|
||||
|
||||
void UF_API wait( pod::Thread& );
|
||||
|
||||
const std::string& UF_API name( const pod::Thread& );
|
||||
uint UF_API uid( const pod::Thread& );
|
||||
bool UF_API running( const pod::Thread& );
|
||||
/* Acts on global threads */
|
||||
typedef std::vector<pod::Thread*> container_t;
|
||||
extern UF_API uf::thread::container_t threads;
|
||||
|
||||
void UF_API terminate();
|
||||
|
||||
pod::Thread& UF_API create( const std::string& = "", bool = true, bool = true );
|
||||
void UF_API destroy( pod::Thread& );
|
||||
bool UF_API has( uint );
|
||||
bool UF_API has( const std::string& );
|
||||
pod::Thread& UF_API get( uint );
|
||||
pod::Thread& UF_API get( const std::string& );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
namespace uf {
|
||||
class UF_API Thread {
|
||||
public:
|
||||
typedef std::function<int()> function_t;
|
||||
typedef std::queue<uf::Thread::function_t> queue_t;
|
||||
typedef std::vector<uf::Thread::function_t> container_t;
|
||||
|
||||
enum {
|
||||
TEMP = 0,
|
||||
CONSTANT = 1,
|
||||
};
|
||||
protected:
|
||||
uint m_uid;
|
||||
uint m_mode;
|
||||
bool m_running;
|
||||
bool m_shouldLock;
|
||||
bool m_terminateOnEmpty;
|
||||
std::mutex m_mutex;
|
||||
std::string m_name;
|
||||
std::thread m_thread;
|
||||
uf::Thread::queue_t m_temps;
|
||||
uf::Thread::container_t m_consts;
|
||||
public:
|
||||
static uint fps;
|
||||
static uint thread_count;
|
||||
Thread( const std::string& = "", bool = true, uint = 0 );
|
||||
virtual ~Thread();
|
||||
|
||||
void start();
|
||||
virtual void tick(const std::function<void()>& = NULL);
|
||||
void add( const uf::Thread::function_t&, uint = 0 );
|
||||
void process();
|
||||
void quit();
|
||||
|
||||
std::string toString() const;
|
||||
const std::string& getName() const;
|
||||
uint getUid() const;
|
||||
const bool& isRunning() const;
|
||||
};
|
||||
namespace thread {
|
||||
typedef std::unordered_map<std::string, uf::Thread*> container_t;
|
||||
extern UF_API uf::thread::container_t threads;
|
||||
|
||||
void UF_API add( uf::Thread* );
|
||||
uf::Thread& UF_API get( const std::string& );
|
||||
bool UF_API add( const std::string&, const uf::Thread::function_t&, uint = 0 );
|
||||
bool UF_API quit( const std::string& );
|
||||
};
|
||||
}
|
||||
*/
|
@ -201,7 +201,7 @@ uf::Collider::Manifold UF_API uf::AABBox::intersects( const uf::AABBox& b ) cons
|
||||
manifold.depth = 9E9;
|
||||
auto test = [&]( const pod::Vector3& axis, float minA, float maxA, float minB, float maxB )->bool{
|
||||
float axisLSqr = uf::vector::dot(axis, axis);
|
||||
if ( axisLSqr < 1E-8f ) return false;
|
||||
if ( axisLSqr < 1E-8f ) return true;
|
||||
|
||||
float d0 = maxB - minA;
|
||||
float d1 = maxA - minB;
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include <uf/utils/math/physics.h>
|
||||
|
||||
void UF_API uf::physics::tick() {
|
||||
static float clamp = 1 / 15.0; if ( uf::physics::time::clamp != clamp ) uf::physics::time::clamp = clamp;
|
||||
uf::physics::time::previous = uf::physics::time::current;
|
||||
uf::physics::time::current = uf::physics::time::timer.elapsed().asDouble();
|
||||
uf::physics::time::delta = uf::physics::time::current - uf::physics::time::previous;
|
||||
if ( uf::physics::time::delta > uf::physics::time::clamp ) uf::physics::time::delta = uf::physics::time::clamp;
|
||||
}
|
300
engine/src/utils/thread/thread.cpp
Normal file
300
engine/src/utils/thread/thread.cpp
Normal file
@ -0,0 +1,300 @@
|
||||
#include <uf/utils/thread/thread.h>
|
||||
#include <iostream>
|
||||
|
||||
uf::thread::container_t uf::thread::threads;
|
||||
|
||||
void UF_API uf::thread::start( pod::Thread& thread ) { if ( thread.running ) return;
|
||||
thread.thread = std::thread( uf::thread::tick, std::ref(thread) );
|
||||
thread.running = true;
|
||||
}
|
||||
void UF_API uf::thread::quit( pod::Thread& thread ) { // if ( !thread.running ) return;
|
||||
thread.running = false;
|
||||
|
||||
if ( thread.mutex != NULL ) thread.mutex->lock();
|
||||
if ( thread.thread.joinable() ) thread.thread.join();
|
||||
if ( thread.mutex != NULL ) thread.mutex->unlock();
|
||||
|
||||
}
|
||||
void UF_API uf::thread::tick( pod::Thread& thread ) {
|
||||
while ( thread.running ) {
|
||||
uf::thread::process( thread );
|
||||
if ( thread.terminates && thread.temps.empty() && thread.consts.empty() ) uf::thread::quit( thread );
|
||||
}
|
||||
}
|
||||
/*
|
||||
void UF_API uf::thread::tick( pod::Thread& thread, const std::function<void()>& callback ) {
|
||||
while ( thread.running ) {
|
||||
uf::thread::process( thread );
|
||||
if ( callback ) callback();
|
||||
if ( thread.terminates && thread.temps.empty() && thread.consts.empty() ) uf::thread::quit( thread );
|
||||
}
|
||||
}
|
||||
*/
|
||||
void UF_API uf::thread::add( pod::Thread& thread, const pod::Thread::function_t& function, bool temporary ) {
|
||||
if ( thread.mutex != NULL ) thread.mutex->lock();
|
||||
temporary ? thread.temps.push( function ) : thread.consts.push_back( function );
|
||||
if ( thread.mutex != NULL ) thread.mutex->unlock();
|
||||
}
|
||||
void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(uf::thread::uid(thread)) ) { std::cout << "Bad Thread: " << thread.uid << " " << thread.name << std::endl; return; } //ops
|
||||
std::function<int()> temps = [&] {
|
||||
int i = 0;
|
||||
while ( !thread.temps.empty() ) {
|
||||
auto& function = thread.temps.front();
|
||||
if ( function ) function();
|
||||
thread.temps.pop();
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
};
|
||||
std::function<int()> consts = [&] {
|
||||
int i = 0;
|
||||
for ( auto function : thread.consts ) {
|
||||
function();
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
if ( thread.mutex != NULL ) thread.mutex->lock();
|
||||
temps();
|
||||
consts();
|
||||
if ( thread.mutex != NULL ) thread.mutex->unlock();
|
||||
}
|
||||
void UF_API uf::thread::wait( pod::Thread& thread ) {
|
||||
if ( thread.mutex != NULL ) {
|
||||
thread.mutex->lock();
|
||||
thread.mutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& UF_API uf::thread::name( const pod::Thread& thread ) {
|
||||
return thread.name;
|
||||
}
|
||||
uint UF_API uf::thread::uid( const pod::Thread& thread ) {
|
||||
return thread.uid;
|
||||
}
|
||||
bool UF_API uf::thread::running( const pod::Thread& thread ) {
|
||||
return thread.running;
|
||||
}
|
||||
|
||||
void UF_API uf::thread::terminate() {
|
||||
while ( !uf::thread::threads.empty() ) {
|
||||
pod::Thread& thread = **uf::thread::threads.begin();
|
||||
uf::thread::destroy( thread );
|
||||
}
|
||||
}
|
||||
pod::Thread& UF_API uf::thread::create( const std::string& name, bool start, bool locks ) {
|
||||
pod::Thread* pointer = NULL;
|
||||
uf::thread::threads.emplace_back(pointer = new pod::Thread);
|
||||
pod::Thread& thread = *pointer;
|
||||
|
||||
static uint uids = 0;
|
||||
thread.name = name;
|
||||
thread.uid = uids++;
|
||||
thread.terminates = false;
|
||||
thread.running = false;
|
||||
thread.mutex = NULL;
|
||||
thread.mutex = locks ? new std::mutex() : NULL;
|
||||
|
||||
std::cout << "Creating Thread #" << thread.uid << " (" << name << ") " << &thread << std::endl;
|
||||
|
||||
if ( start ) uf::thread::start( thread );
|
||||
|
||||
return thread;
|
||||
}
|
||||
void UF_API uf::thread::destroy( pod::Thread& thread ) {
|
||||
if ( !uf::thread::has( uf::thread::uid(thread) ) ) return; // oops
|
||||
|
||||
uf::thread::quit( thread );
|
||||
std::cout << "Quitted Thread #" << thread.uid << " (" << thread.name << ")" << std::endl;
|
||||
|
||||
if ( thread.mutex != NULL ) delete thread.mutex;
|
||||
|
||||
for ( auto it = uf::thread::threads.begin(); it != uf::thread::threads.end(); ++it )
|
||||
if ( uf::thread::uid( **it ) == uf::thread::uid(thread) ) {
|
||||
delete *it;
|
||||
uf::thread::threads.erase( it );
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool UF_API uf::thread::has( uint uid ) {
|
||||
for ( const pod::Thread* thread : uf::thread::threads ) if ( uf::thread::uid(*thread) == uid ) return true;
|
||||
return false;
|
||||
}
|
||||
bool UF_API uf::thread::has( const std::string& name ) {
|
||||
for ( const pod::Thread* thread : uf::thread::threads ) if ( uf::thread::name(*thread) == name ) return true;
|
||||
return false;
|
||||
}
|
||||
pod::Thread& UF_API uf::thread::get( uint uid ) {
|
||||
static pod::Thread null;
|
||||
for ( pod::Thread* thread : uf::thread::threads ) if ( uf::thread::uid(*thread) == uid ) return *thread;
|
||||
return null;
|
||||
}
|
||||
pod::Thread& UF_API uf::thread::get( const std::string& name ) {
|
||||
static pod::Thread null;
|
||||
for ( pod::Thread* thread : uf::thread::threads ) if ( uf::thread::name(*thread) == name ) return *thread;
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
#include <sstream>
|
||||
|
||||
uint uf::Thread::fps = 60;
|
||||
uint uf::Thread::threads = 0;
|
||||
|
||||
UF_API_CALL uf::Thread::Thread( const std::string& name, bool start, uint mode ) {
|
||||
static int uid = 0;
|
||||
this->m_mode = mode;
|
||||
this->m_name = name;
|
||||
this->m_running = false;
|
||||
this->m_shouldLock = false;
|
||||
this->m_terminateOnEmpty = false;
|
||||
this->m_uid = start ? ++uid : 0;
|
||||
|
||||
if ( uf::Thread::threads != 0 && this->m_uid > uf::Thread::threads ) start = false;
|
||||
if ( start ) this->start();
|
||||
}
|
||||
UF_API_CALL uf::Thread::~Thread() {
|
||||
this->m_quit();
|
||||
}
|
||||
|
||||
void UF_API_CALL uf::Thread::start() {
|
||||
if ( this->m_running ) return;
|
||||
|
||||
this->m_running = true;
|
||||
this->m_thread = std::thread( [&]{ this->tick(); } );
|
||||
}
|
||||
|
||||
void UF_API_CALL uf::Thread::tick( const std::function<void()>& callback ) {
|
||||
double curTime = uf::time::curTime;
|
||||
double prevTime = uf::time::prevTime;
|
||||
double deltaTime = curTime - prevTime;
|
||||
double tempTime = 0;
|
||||
double totalTime = 0;
|
||||
double framerate = 1 / uf::Thread::fps;
|
||||
|
||||
bool should_call = (bool) callback;
|
||||
while ( this->m_running ) {
|
||||
prevTime = curTime;
|
||||
curTime = uf::time::curTime;
|
||||
deltaTime = curTime - prevTime;
|
||||
tempTime += deltaTime;
|
||||
totalTime += deltaTime;
|
||||
|
||||
if ( tempTime > framerate ) {
|
||||
this->process();
|
||||
tempTime = 0.0;
|
||||
if ( should_call ) callback();
|
||||
if ( this->m_terminateOnEmpty && this->m_temps.empty() && this->m_consts.empty() ) {
|
||||
this->m_running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UF_API_CALL uf::Thread::add( const uf::Thread::function_t& function, uint mode ) {
|
||||
if ( this->m_shouldLock ) this->m_mutex.lock();
|
||||
switch ( mode ) {
|
||||
case uf::Thread::TEMP: this->m_temps.push(function); break;
|
||||
case uf::Thread::CONSTANT: this->m_consts.push_back(function); break;
|
||||
}
|
||||
if ( this->m_shouldLock ) this->m_mutex.unlock();
|
||||
}
|
||||
|
||||
void UF_API_CALL uf::Thread::process() {
|
||||
std::function<int()> temps = [&] {
|
||||
int i = 0;
|
||||
while ( !this->m_temps.empty() ) {
|
||||
uf::Thread::function_t& function = this->m_temps.front();
|
||||
if ( function() != -1 ) this->m_temps.pop();
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
};
|
||||
std::function<int()> consts = [&] {
|
||||
int i = 0;
|
||||
for ( uf::Thread::container_t::iterator it = this->m_consts.begin(); it != this->m_consts.end(); ++it ) {
|
||||
uf::Thread::function_t& function = *it;
|
||||
function();
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
if ( this->m_shouldLock ) this->m_mutex.lock();
|
||||
try {
|
||||
switch ( this->m_mode ) {
|
||||
case 0:
|
||||
temps();
|
||||
consts();
|
||||
break;
|
||||
case 1:
|
||||
consts();
|
||||
temps();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch ( ... ) {
|
||||
// std::cout << "error" << std::endl;
|
||||
// uf::iostream << "error" << "\n";
|
||||
}
|
||||
if ( this->m_shouldLock ) this->m_mutex.unlock();
|
||||
}
|
||||
|
||||
void UF_API_CALL uf::Thread::quit() {
|
||||
this->m_running = false;
|
||||
this->m_thread.join();
|
||||
|
||||
// uf::log << uf::Log::Entree( { "basic", { this->m_toString() + " killed", __LINE__ - 1, __FILE__, __FUNCTION__, 0 } } );
|
||||
}
|
||||
|
||||
std::string UF_API_CALL uf::Thread::toString() const {
|
||||
// std::stringstream str;
|
||||
// str << "Thread(Name: " << this->m_name << ")";
|
||||
// return str.str();
|
||||
return "Thread";
|
||||
}
|
||||
const std::string& UF_API_CALL uf::Thread::getName() const {
|
||||
return this->m_name;
|
||||
}
|
||||
uint UF_API_CALL uf::Thread::getUid() const {
|
||||
return this->m_uid;
|
||||
}
|
||||
const bool& UF_API_CALL uf::Thread::isRunning() const {
|
||||
return this->m_running;
|
||||
}
|
||||
//
|
||||
uf::thread::container_t uf::thread::threads;
|
||||
|
||||
void UF_API_CALL uf::thread::add( uf::Thread* thread ) {
|
||||
std::string name = thread->getName();
|
||||
uf::thread::threads[name] = thread;
|
||||
}
|
||||
uf::Thread& UF_API_CALL uf::thread::get( const std::string& name ) {
|
||||
static uf::Thread null( "NULL", false );
|
||||
try {
|
||||
return *uf::thread::threads.at(name);
|
||||
} catch ( std::out_of_range oor ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
bool UF_API_CALL uf::thread::add( const std::string& name, const uf::Thread::function_t& function, uint mode ) {
|
||||
uf::Thread& thread = uf::thread::get(name);
|
||||
if ( thread.getName() == "NULL" || ( uf::Thread::threads != 0 && thread.getUid() > uf::Thread::threads ) ) {
|
||||
switch ( mode ) {
|
||||
case uf::Thread::TEMP: function(); break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
thread.add( function, mode );
|
||||
|
||||
return true;
|
||||
}
|
||||
bool UF_API_CALL uf::thread::quit( const std::string& name ) {
|
||||
uf::Thread& thread = uf::thread::get(name);
|
||||
if ( thread.getName() == "NULL" ) return false;
|
||||
|
||||
thread.quit();
|
||||
return true;
|
||||
}
|
||||
*/
|
31
ext/main.cpp
31
ext/main.cpp
@ -17,6 +17,7 @@
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
#include <uf/utils/userdata/userdata.h>
|
||||
#include <uf/utils/image/image.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
|
||||
#include <uf/gl/shader/shader.h>
|
||||
#include <uf/gl/mesh/mesh.h>
|
||||
@ -108,6 +109,12 @@ void EXT_API ext::initialize() {
|
||||
::world.master.initialize();
|
||||
}
|
||||
|
||||
/* */ {
|
||||
pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, false );
|
||||
pod::Thread& threadAux = uf::thread::has("Aux") ? uf::thread::get("Aux") : uf::thread::create( "Aux", true, false );
|
||||
pod::Thread& threadPhysics = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false );
|
||||
}
|
||||
|
||||
ext::ready = true;
|
||||
uf::iostream << "EXT took " << times.sys.elapsed().asDouble() << " seconds to initialize!" << "\n";
|
||||
}
|
||||
@ -123,22 +130,30 @@ void EXT_API ext::tick() {
|
||||
/* Update entities */ {
|
||||
::world.master.tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Tick Main Thread Queue */ {
|
||||
pod::Thread& thread = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, false );
|
||||
uf::thread::process( thread );
|
||||
}
|
||||
}
|
||||
void EXT_API ext::render() {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
/* Draw geometry */ {
|
||||
::world.master.render();
|
||||
}
|
||||
}
|
||||
void EXT_API ext::terminate() {
|
||||
// curTime = spec::time.getTime();
|
||||
io.output << io.input << std::endl;
|
||||
for ( const auto& str : uf::iostream.getHistory() )
|
||||
io.output << str << std::endl;
|
||||
io.output << "\nTerminated after " << times.sys.elapsed().asDouble() << " seconds" << std::endl;
|
||||
io.output.close();
|
||||
/* Flush input buffer */ {
|
||||
io.output << io.input << std::endl;
|
||||
for ( const auto& str : uf::iostream.getHistory() ) io.output << str << std::endl;
|
||||
io.output << "\nTerminated after " << times.sys.elapsed().asDouble() << " seconds" << std::endl;
|
||||
io.output.close();
|
||||
}
|
||||
|
||||
/* Close Threads */ {
|
||||
uf::thread::terminate();
|
||||
}
|
||||
|
||||
/* Write persistent data */ {
|
||||
struct {
|
||||
|
@ -49,6 +49,8 @@ void ext::Craeture::initialize() {
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
}
|
||||
}
|
||||
|
||||
#include <uf/utils/thread/thread.h>
|
||||
void ext::Craeture::tick() {
|
||||
ext::Object::tick();
|
||||
|
||||
@ -59,45 +61,52 @@ void ext::Craeture::tick() {
|
||||
}
|
||||
this->animate();
|
||||
|
||||
/* Collision */ if ( this->m_parent && serializer["collision"]["should"].asBool() ) {
|
||||
uf::Entity& parent = this->getParent();
|
||||
if ( this->hasComponent<uf::CollisionBody>() && parent.hasComponent<uf::CollisionBody>() ) {
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
uf::CollisionBody& pCollider = parent.getComponent<uf::CollisionBody>();
|
||||
/* Threads */ {
|
||||
pod::Thread& thread = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true );
|
||||
auto function = [&]() -> int {
|
||||
/* Collision */ if ( this->m_parent && serializer["collision"]["should"].asBool() ) {
|
||||
uf::Entity& parent = this->getParent();
|
||||
if ( this->hasComponent<uf::CollisionBody>() && parent.hasComponent<uf::CollisionBody>() ) {
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
uf::CollisionBody& pCollider = parent.getComponent<uf::CollisionBody>();
|
||||
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>(); {
|
||||
collider.clear();
|
||||
uf::Collider* box = new uf::AABBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} );
|
||||
collider.add(box);
|
||||
}
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>(); {
|
||||
collider.clear();
|
||||
uf::Collider* box = new uf::AABBox( uf::vector::add({0, 1.5, 0}, transform.position), {0.7, 1.6, 0.7} );
|
||||
collider.add(box);
|
||||
}
|
||||
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
auto result = pCollider.intersects(collider);
|
||||
uf::Collider::Manifold strongest;
|
||||
strongest.depth = 0.001;
|
||||
bool useStrongest = true;
|
||||
for ( auto manifold : result ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
if ( !useStrongest ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(manifold.normal) * -(manifold.depth * manifold.depth * 1.001);
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
auto result = pCollider.intersects(collider);
|
||||
uf::Collider::Manifold strongest;
|
||||
strongest.depth = 0.001;
|
||||
bool useStrongest = true;
|
||||
for ( auto manifold : result ) {
|
||||
if ( manifold.colliding && manifold.depth > 0 ) {
|
||||
if ( strongest.depth < manifold.depth ) strongest = manifold;
|
||||
if ( !useStrongest ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(manifold.normal) * -(manifold.depth * manifold.depth * 1.001);
|
||||
transform.position += correction;
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(strongest.normal) * -(strongest.depth * strongest.depth * 1.001);
|
||||
transform.position += correction;
|
||||
if ( manifold.normal.x == 1 || manifold.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( manifold.normal.y == 1 || manifold.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( manifold.normal.z == 1 || manifold.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
|
||||
// std::cout << "Collision! " << ( strongest.colliding ? "yes" : "no" ) << " " << strongest.normal.x << ", " << strongest.normal.y << ", " << strongest.normal.z << " / " << strongest.depth << std::endl;
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( useStrongest && strongest.colliding ) {
|
||||
pod::Vector3 correction = uf::vector::normalize(strongest.normal) * -(strongest.depth * strongest.depth * 1.001);
|
||||
transform.position += correction;
|
||||
|
||||
// std::cout << "Collision! " << ( strongest.colliding ? "yes" : "no" ) << " " << strongest.normal.x << ", " << strongest.normal.y << ", " << strongest.normal.z << " / " << strongest.depth << std::endl;
|
||||
if ( strongest.normal.x == 1 || strongest.normal.x == -1 ) physics.linear.velocity.x = 0;
|
||||
if ( strongest.normal.y == 1 || strongest.normal.y == -1 ) physics.linear.velocity.y = 0;
|
||||
if ( strongest.normal.z == 1 || strongest.normal.z == -1 ) physics.linear.velocity.z = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
uf::thread::add( thread, function, true );
|
||||
}
|
||||
}
|
||||
void ext::Craeture::render() {
|
||||
|
@ -6,20 +6,11 @@
|
||||
|
||||
void ext::Object::initialize() {
|
||||
uf::Entity::initialize();
|
||||
this->addComponent<pod::Physics>();
|
||||
this->addComponent<pod::Transform<>>();
|
||||
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
physics.linear.velocity = {0,0,0};
|
||||
physics.linear.acceleration = {0,0,0};
|
||||
physics.rotational.velocity = uf::quaternion::axisAngle( {0,1,0}, (pod::Math::num_t) 0 );
|
||||
physics.rotational.acceleration = {0,0,0,0};
|
||||
}
|
||||
void ext::Object::tick() {
|
||||
uf::Entity::tick();
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
// if ( this->m_name == "Cube" ) physics.linear.velocity = {0,1.0125f*cosf(0.125f*uf::physics::time::current),0};
|
||||
transform = uf::physics::update( transform, physics );
|
||||
}
|
||||
void ext::Object::render() {
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <uf/utils/math/transform.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/math/collision.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
|
||||
namespace ext {
|
||||
class EXT_API Object : public uf::Entity {
|
||||
|
@ -110,11 +110,32 @@ void ext::Player::initialize() {
|
||||
uf::Camera& camera = this->getComponent<uf::Camera>();
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
pod::Transform<>& cameraTransform = camera.getTransform();
|
||||
if ( delta.x != 0 ) uf::transform::rotate( transform, transform.up, relta.x ), updateCamera = true;
|
||||
uf::Serializer& serializer = this->getComponent<uf::Serializer>();
|
||||
if ( delta.x != 0 ) {
|
||||
double current, minima, maxima; {
|
||||
current = serializer["camera"]["limit"]["current"][0] != Json::nullValue ? serializer["camera"]["limit"]["current"][0].asDouble() : NAN;
|
||||
minima = serializer["camera"]["limit"]["minima"][0] != Json::nullValue ? serializer["camera"]["limit"]["minima"][0].asDouble() : NAN;
|
||||
maxima = serializer["camera"]["limit"]["maxima"][0] != Json::nullValue ? serializer["camera"]["limit"]["maxima"][0].asDouble() : NAN;
|
||||
}
|
||||
if ( serializer["camera"]["invert"][0].asBool() ) relta.x *= -1;
|
||||
current += relta.x;
|
||||
if ( current != current || ( current < maxima && current > minima ) ) uf::transform::rotate( transform, transform.up, relta.x ), updateCamera = true; else current -= relta.x;
|
||||
if ( serializer["camera"]["limit"]["current"][0] != Json::nullValue ) serializer["camera"]["limit"]["current"][0] = current;
|
||||
}
|
||||
if ( delta.y != 0 ) {
|
||||
static float limit = 0; limit += -relta.y;
|
||||
if ( limit < 1 && limit > -1.2 ) uf::transform::rotate( cameraTransform, cameraTransform.right, relta.y ), updateCamera = true;
|
||||
else limit -= -relta.y;
|
||||
double current, minima, maxima; {
|
||||
current = serializer["camera"]["limit"]["current"][1] != Json::nullValue ? serializer["camera"]["limit"]["current"][1].asDouble() : NAN;
|
||||
minima = serializer["camera"]["limit"]["minima"][1] != Json::nullValue ? serializer["camera"]["limit"]["minima"][1].asDouble() : NAN;
|
||||
maxima = serializer["camera"]["limit"]["maxima"][1] != Json::nullValue ? serializer["camera"]["limit"]["maxima"][1].asDouble() : NAN;
|
||||
}
|
||||
if ( serializer["camera"]["invert"][1].asBool() ) relta.y *= -1;
|
||||
current += relta.y;
|
||||
if ( current != current || ( current < maxima && current > minima ) ) {
|
||||
uf::transform::rotate( cameraTransform, cameraTransform.right, relta.y );
|
||||
uf::transform::rotate( this->m_animation.transforms[serializer["animation"]["names"]["head"].asString()], {0, 0, 1}, -relta.y );
|
||||
updateCamera = true;
|
||||
} else current -= relta.y;
|
||||
if ( serializer["camera"]["limit"]["current"][1] != Json::nullValue ) serializer["camera"]["limit"]["current"][1] = current;
|
||||
}
|
||||
if ( updateCamera ) {
|
||||
camera.updateView();
|
||||
@ -158,11 +179,24 @@ void ext::Player::initialize() {
|
||||
uf::Camera& camera = this->getComponent<uf::Camera>();
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
pod::Transform<>& cameraTransform = camera.getTransform();
|
||||
/*
|
||||
if ( delta.y != 0 ) {
|
||||
double current, minima, maxima; {
|
||||
current = serializer["camera"]["limit"]["current"][1] != Json::nullValue ? serializer["camera"]["limit"]["current"][1].asDouble() : NAN;
|
||||
minima = serializer["camera"]["limit"]["minima"][1] != Json::nullValue ? serializer["camera"]["limit"]["minima"][1].asDouble() : NAN;
|
||||
maxima = serializer["camera"]["limit"]["maxima"][1] != Json::nullValue ? serializer["camera"]["limit"]["maxima"][1].asDouble() : NAN;
|
||||
}
|
||||
if ( serializer["camera"]["invert"][1].asBool() ) relta.y *= -1;
|
||||
current += relta.y;
|
||||
std::cout << "Head: " << current << ", " << minima << ", " << maxima << std::endl;
|
||||
if ( current != current || ( current < maxima && current > minima ) ) uf::transform::rotate( this->m_animation.transforms[serializer["animation"]["names"]["head"].asString()], {0, 0, 1}, relta.y ), updateCamera = true;
|
||||
}
|
||||
if ( false && delta.y != 0 ) {
|
||||
static float limit = 0; limit += -relta.y;
|
||||
if ( limit < 1 && limit > -1 ) uf::transform::rotate( this->m_animation.transforms[serializer["animation"]["names"]["head"].asString()], {0, 0, 1}, -relta.y ), updateCamera = true;
|
||||
else limit -= -relta.y;
|
||||
}
|
||||
*/
|
||||
if ( ::lockMouse ) {
|
||||
uf::hooks.call("window:Mouse.Lock");
|
||||
ignoreNext = true;
|
||||
@ -175,8 +209,8 @@ void ext::Player::tick() {
|
||||
bool deltaCrouch = false;
|
||||
bool walking = false;
|
||||
struct {
|
||||
float move = uf::physics::time::delta * 4;
|
||||
float rotate = uf::physics::time::delta * 4;
|
||||
float move = 4; //uf::physics::time::delta * 4;
|
||||
float rotate = uf::physics::time::delta * 0.75;
|
||||
float limitSquared = 4*4;
|
||||
} speed;
|
||||
|
||||
@ -185,7 +219,7 @@ void ext::Player::tick() {
|
||||
pod::Physics& physics = this->getComponent<pod::Physics>();
|
||||
uf::Serializer& serializer = this->getComponent<uf::Serializer>();
|
||||
|
||||
camera.update(true);
|
||||
// camera.update(true);
|
||||
|
||||
bool floored = physics.linear.velocity.y == 0;
|
||||
if ( ::lockMouse ) {
|
||||
|
@ -72,120 +72,139 @@ void ext::TerrainGenerator::generate(){ if ( this->m_voxels ) return;
|
||||
this->m_voxels = new ext::TerrainVoxel::uid_t**[this->m_size.x];
|
||||
for ( uint x = 0; x < this->m_size.x; ++x ) { this->m_voxels[x] = new ext::TerrainVoxel::uid_t*[this->m_size.y];
|
||||
for ( uint y = 0; y < this->m_size.y; ++y ) { this->m_voxels[x][y] = new ext::TerrainVoxel::uid_t[this->m_size.z];
|
||||
for ( uint z = 0; z < this->m_size.z; ++z ) this->m_voxels[x][y][z] = 0;
|
||||
}
|
||||
}
|
||||
if ( true ) {
|
||||
int rand_roomType = rand() % 6;
|
||||
static bool first = false;
|
||||
if ( !first ) rand_roomType = 0, first = true;
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int z = 0; z < lim_z; z++ ) {
|
||||
if ( this->m_voxels == NULL || this->m_voxels[x] == NULL || this->m_voxels[x][y] == NULL ) break;
|
||||
this->m_voxels[x][y][z] = 0;
|
||||
// Wall
|
||||
/*
|
||||
if ((( x == 0 || x == 1 ) && ( z == lim_z - 1 || z == lim_z - 2 )) ||
|
||||
(( z == 0 || z == 1 ) && ( x == lim_x - 1 || x == lim_x - 2 )))
|
||||
this->m_voxels[x][y][z] = wall;
|
||||
*/
|
||||
// Floor
|
||||
if ( y == 0 ) this->m_voxels[x][y][z] = atlas.floor;
|
||||
// Ceiling
|
||||
if ( y + 1 == lim_y ) this->m_voxels[x][y][z] = rand() % 10 < 8.0f ? 0 : atlas.ceiling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ( rand_roomType ) {
|
||||
// Wall-less room
|
||||
case 0: break;
|
||||
// Typical Room
|
||||
default:
|
||||
// North
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
float randed_wall = rand() % 10;
|
||||
if ( !(y < 5 && x>half_x-3&&x<half_x+3) && randed_wall > 4.0f )
|
||||
this->m_voxels[x][y][lim_z-1] = atlas.wall;
|
||||
else
|
||||
this->m_voxels[x][y][lim_z-1] = 0;
|
||||
}
|
||||
}
|
||||
// South
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
float randed_wall = rand() % 10;
|
||||
if ( !(y < 5 && x>half_x-3&&x<half_x+3) && randed_wall > 4.0f )
|
||||
this->m_voxels[x][y][0] = atlas.wall;
|
||||
else
|
||||
this->m_voxels[x][y][0] = 0;
|
||||
}
|
||||
}
|
||||
// East
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int z = 0; z < lim_x; z++ ) {
|
||||
float randed_wall = rand() % 10;
|
||||
if ( !(y < 5 && z>half_z-3&&z<half_z+3) && randed_wall > 3.0f )
|
||||
this->m_voxels[lim_z-1][y][z] = atlas.wall;
|
||||
else
|
||||
this->m_voxels[lim_z-1][y][z] = 0;
|
||||
}
|
||||
}
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
for ( int z = 0; z < lim_z; z++ ) {
|
||||
this->m_voxels[x][0][z] = atlas.floor;
|
||||
}
|
||||
}
|
||||
// Default Room
|
||||
// Hole room
|
||||
case 2:
|
||||
for ( int x = half_x - (half_x / 2); x < half_x + (half_x / 2) + 1; x++ )
|
||||
for ( int z = half_z - (half_z / 2); z < half_z + (half_z / 2) + 1; z++ )
|
||||
if ( rand() % 10 > 1.25f ) this->m_voxels[x][0][z] = 0;
|
||||
break;
|
||||
// Pillar
|
||||
case 3:
|
||||
for ( int x = half_x - 1; x <= half_x + 1; x++ )
|
||||
for ( int z = half_z - 1; z <= half_z + 1; z++ )
|
||||
for ( int y = 0; y < lim_y; y++ )
|
||||
if ( rand() % 10 > 1.25f ) this->m_voxels[x][y][z] = atlas.pillar;
|
||||
break;
|
||||
// Stair room
|
||||
case -4:
|
||||
int randed_direction = rand() % 2;
|
||||
int start_x = std::max(half_x - 3, 0);
|
||||
int stop_x = std::min(half_x + 5, lim_x);
|
||||
int start_z = -2;
|
||||
int stop_z = 2;
|
||||
int slope_x = lim_y / ( stop_x - start_x );
|
||||
int slope_z = lim_y / ( stop_z - start_z );
|
||||
/*
|
||||
for ( int x = start_x; x <= stop_x; x++ )
|
||||
for ( int z = start_z; z <= stop_z; z++ ) this->m_voxels[x][lim_y - 1][half_z - 1 + z] = 0;
|
||||
*/
|
||||
switch ( randed_direction ) {
|
||||
// Left to Right
|
||||
case 0:
|
||||
for ( int x = start_x; x <= stop_x; x++ ) {
|
||||
int y = (x - start_x) * slope_x + 1;
|
||||
for ( int z = start_z; z <= stop_z && y < lim_y; z++ )
|
||||
for ( int i = y; i >= y - slope_x && i >= 0; i-- )
|
||||
if ( rand() % stop_x > 3 ) this->m_voxels[x][i][half_z - 1 + z] = atlas.stair;
|
||||
}
|
||||
break;
|
||||
// Right to Left
|
||||
case 1:
|
||||
for ( int x = start_x; x <= stop_x; x++ ) {
|
||||
int y = (x - start_x) * slope_x + 3;
|
||||
for ( int z = start_z; z <= stop_z && y < lim_y; z++ )
|
||||
for ( int i = y; i >= y - slope_x && i >= 0; i-- )
|
||||
if ( rand() % stop_x > 3 ) this->m_voxels[x][lim_y - 1 - i][half_z - 1 + z] = atlas.stair;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int rand_roomType = rand() % 6;
|
||||
static bool first = false;
|
||||
if ( !first ) rand_roomType = 0, first = true;
|
||||
|
||||
/*
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int z = 0; z < lim_z; z++ ) {
|
||||
if ( this->m_voxels == NULL || this->m_voxels[x] == NULL || this->m_voxels[x][y] == NULL ) break;
|
||||
this->m_voxels[x][y][z] = 0;
|
||||
// Wall
|
||||
/*
|
||||
if ((( x == 0 || x == 1 ) && ( z == lim_z - 1 || z == lim_z - 2 )) ||
|
||||
(( z == 0 || z == 1 ) && ( x == lim_x - 1 || x == lim_x - 2 )))
|
||||
this->m_voxels[x][y][z] = wall;
|
||||
*/
|
||||
// Floor
|
||||
// if ( y > 3 ) this->m_voxels[x][y][z] = 0;
|
||||
if ( x == 0 ) this->m_voxels[x][y][z] = atlas.floor;
|
||||
if ( y == 0 ) this->m_voxels[x][y][z] = atlas.floor;
|
||||
// Ceiling
|
||||
if ( y + 1 == lim_y ) this->m_voxels[x][y][z] = rand() % 10 < 8.0f ? 0 : atlas.ceiling;
|
||||
if ( z == 0 ) this->m_voxels[x][y][z] = atlas.floor;
|
||||
if ( x == lim_x - 1 ) this->m_voxels[x][y][z] = atlas.floor;
|
||||
if ( y == lim_y - 1 ) this->m_voxels[x][y][z] = atlas.floor;
|
||||
if ( z == lim_z - 1 ) this->m_voxels[x][y][z] = atlas.floor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ( rand_roomType ) {
|
||||
// Wall-less room
|
||||
case 2: break;
|
||||
// Typical Room
|
||||
default:
|
||||
// North
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
float randed_wall = rand() % 10;
|
||||
if ( !(y < 5 && x>half_x-3&&x<half_x+3) && randed_wall > 4.0f )
|
||||
this->m_voxels[x][y][lim_z-1] = atlas.wall;
|
||||
else
|
||||
this->m_voxels[x][y][lim_z-1] = 0;
|
||||
}
|
||||
}
|
||||
// South
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
float randed_wall = rand() % 10;
|
||||
if ( !(y < 5 && x>half_x-3&&x<half_x+3) && randed_wall > 4.0f )
|
||||
this->m_voxels[x][y][0] = atlas.wall;
|
||||
else
|
||||
this->m_voxels[x][y][0] = 0;
|
||||
}
|
||||
}
|
||||
// East
|
||||
for ( int y = 0; y < lim_y; y++ ) {
|
||||
for ( int z = 0; z < lim_x; z++ ) {
|
||||
float randed_wall = rand() % 10;
|
||||
if ( !(y < 5 && z>half_z-3&&z<half_z+3) && randed_wall > 3.0f )
|
||||
this->m_voxels[lim_z-1][y][z] = atlas.wall;
|
||||
else
|
||||
this->m_voxels[lim_z-1][y][z] = 0;
|
||||
}
|
||||
}
|
||||
for ( int x = 0; x < lim_x; x++ ) {
|
||||
for ( int z = 0; z < lim_z; z++ ) {
|
||||
this->m_voxels[x][0][z] = atlas.floor;
|
||||
}
|
||||
}
|
||||
// Default Room
|
||||
// Hole room
|
||||
case 0:
|
||||
for ( int x = half_x - (half_x / 2); x < half_x + (half_x / 2) + 1; x++ )
|
||||
for ( int z = half_z - (half_z / 2); z < half_z + (half_z / 2) + 1; z++ )
|
||||
if ( rand() % 10 > 1.25f ) this->m_voxels[x][0][z] = 0;
|
||||
break;
|
||||
// Pillar
|
||||
case 3:
|
||||
for ( int x = half_x - 1; x <= half_x + 1; x++ )
|
||||
for ( int z = half_z - 1; z <= half_z + 1; z++ )
|
||||
for ( int y = 0; y < lim_y; y++ )
|
||||
if ( rand() % 10 > 1.25f ) this->m_voxels[x][y][z] = atlas.pillar;
|
||||
break;
|
||||
// Stair room
|
||||
case 4:
|
||||
int randed_direction = rand() % 2;
|
||||
int start_x = std::max(half_x - 3, 0);
|
||||
int stop_x = std::min(half_x + 5, lim_x);
|
||||
int start_z = -2;
|
||||
int stop_z = 2;
|
||||
int slope_x = lim_y / ( stop_x - start_x );
|
||||
int slope_z = lim_y / ( stop_z - start_z );
|
||||
|
||||
for ( int x = start_x; x <= stop_x; x++ )
|
||||
for ( int z = start_z; z <= stop_z; z++ )
|
||||
this->m_voxels[x][lim_y - 1][half_z - 1 + z] = 0;
|
||||
switch ( randed_direction ) {
|
||||
// Left to Right
|
||||
case 0:
|
||||
for ( int x = start_x; x <= stop_x; x++ ) {
|
||||
int y = (x - start_x) * slope_x + 1;
|
||||
for ( int z = start_z; z <= stop_z && y < lim_y; z++ )
|
||||
for ( int i = y; i >= y - slope_x && i >= 0; i-- )
|
||||
if ( rand() % stop_x > 3 ) this->m_voxels[x][i][half_z - 1 + z] = atlas.stair;
|
||||
}
|
||||
break;
|
||||
// Right to Left
|
||||
case 1:
|
||||
for ( int x = start_x; x <= stop_x; x++ ) {
|
||||
int y = (x - start_x) * slope_x + 3;
|
||||
for ( int z = start_z; z <= stop_z && y < lim_y; z++ )
|
||||
for ( int i = y; i >= y - slope_x && i >= 0; i-- )
|
||||
if ( rand() % stop_x > 3 ) this->m_voxels[x][lim_y - 1 - i][half_z - 1 + z] = atlas.stair;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
ext::TerrainVoxel::uid_t*** ext::TerrainGenerator::getVoxels() {
|
||||
return this->m_voxels;
|
||||
@ -214,6 +233,137 @@ void ext::TerrainGenerator::rasterize( uf::Mesh& mesh, const ext::Region& region
|
||||
regions.front = terrain.at( { location.x, location.y, location.z + 1 } );
|
||||
regions.back = terrain.at( { location.x, location.y, location.z - 1 } );
|
||||
|
||||
if ( false ) {
|
||||
ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas(ext::TerrainVoxelFloor().uid());
|
||||
const ext::TerrainVoxel::Model& model = voxel.model();
|
||||
|
||||
{
|
||||
for ( uint i = 0; i < model.position.right.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.position.right[i*3+0]; p.y = model.position.right[i*3+1]; p.z = model.position.right[i*3+2];
|
||||
p.x *= this->m_size.x; p.y *= this->m_size.y; p.z *= this->m_size.z;
|
||||
p.x -= this->m_size.x;
|
||||
position.push_back(p.x); position.push_back(p.y); position.push_back(p.z);
|
||||
}
|
||||
for ( uint i = 0; i < model.uv.right.size() / 2; ++i ) {
|
||||
struct { float x, y; } p;
|
||||
p.x = model.uv.right[i*2+0]; p.y = model.uv.right[i*2+1];
|
||||
// p.x *= offset.uv.x; p.y *= offset.uv.y;
|
||||
// p.x += offset.uv.u; p.y += offset.uv.v;
|
||||
uv.push_back(p.x); uv.push_back(p.y);
|
||||
}
|
||||
for ( uint i = 0; i < model.normal.right.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.normal.right[i*3+0]; p.y = model.normal.right[i*3+1]; p.z = model.normal.right[i*3+2];
|
||||
normal.push_back(p.x); normal.push_back(p.y); normal.push_back(p.z);
|
||||
}
|
||||
} {
|
||||
for ( uint i = 0; i < model.position.left.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.position.left[i*3+0]; p.y = model.position.left[i*3+1]; p.z = model.position.left[i*3+2];
|
||||
p.x *= this->m_size.x; p.y *= this->m_size.y; p.z *= this->m_size.z;
|
||||
p.x += this->m_size.x;
|
||||
position.push_back(p.x); position.push_back(p.y); position.push_back(p.z);
|
||||
}
|
||||
for ( uint i = 0; i < model.uv.left.size() / 2; ++i ) {
|
||||
struct { float x, y; } p;
|
||||
p.x = model.uv.left[i*2+0]; p.y = model.uv.left[i*2+1];
|
||||
// p.x *= offset.uv.x; p.y *= offset.uv.y;
|
||||
// p.x += offset.uv.u; p.y += offset.uv.v;
|
||||
uv.push_back(p.x); uv.push_back(p.y);
|
||||
}
|
||||
for ( uint i = 0; i < model.normal.left.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.normal.left[i*3+0]; p.y = model.normal.left[i*3+1]; p.z = model.normal.left[i*3+2];
|
||||
normal.push_back(p.x); normal.push_back(p.y); normal.push_back(p.z);
|
||||
}
|
||||
} {
|
||||
for ( uint i = 0; i < model.position.top.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.position.top[i*3+0]; p.y = model.position.top[i*3+1]; p.z = model.position.top[i*3+2];
|
||||
p.x *= this->m_size.x; p.y *= this->m_size.y; p.z *= this->m_size.z;
|
||||
p.y -= this->m_size.y;
|
||||
position.push_back(p.x); position.push_back(p.y); position.push_back(p.z);
|
||||
}
|
||||
for ( uint i = 0; i < model.uv.top.size() / 2; ++i ) {
|
||||
struct { float x, y; } p;
|
||||
p.x = model.uv.top[i*2+0]; p.y = model.uv.top[i*2+1];
|
||||
// p.x *= offset.uv.x; p.y *= offset.uv.y;
|
||||
// p.x += offset.uv.u; p.y += offset.uv.v;
|
||||
uv.push_back(p.x); uv.push_back(p.y);
|
||||
}
|
||||
for ( uint i = 0; i < model.normal.top.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.normal.top[i*3+0]; p.y = model.normal.top[i*3+1]; p.z = model.normal.top[i*3+2];
|
||||
normal.push_back(p.x); normal.push_back(p.y); normal.push_back(p.z);
|
||||
}
|
||||
} {
|
||||
for ( uint i = 0; i < model.position.bottom.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.position.bottom[i*3+0]; p.y = model.position.bottom[i*3+1]; p.z = model.position.bottom[i*3+2];
|
||||
p.x *= this->m_size.x; p.y *= this->m_size.y; p.z *= this->m_size.z;
|
||||
p.y += this->m_size.y;
|
||||
position.push_back(p.x); position.push_back(p.y); position.push_back(p.z);
|
||||
}
|
||||
for ( uint i = 0; i < model.uv.bottom.size() / 2; ++i ) {
|
||||
struct { float x, y; } p;
|
||||
p.x = model.uv.bottom[i*2+0]; p.y = model.uv.bottom[i*2+1];
|
||||
// p.x *= offset.uv.x; p.y *= offset.uv.y;
|
||||
// p.x += offset.uv.u; p.y += offset.uv.v;
|
||||
uv.push_back(p.x); uv.push_back(p.y);
|
||||
}
|
||||
for ( uint i = 0; i < model.normal.bottom.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.normal.bottom[i*3+0]; p.y = model.normal.bottom[i*3+1]; p.z = model.normal.bottom[i*3+2];
|
||||
normal.push_back(p.x); normal.push_back(p.y); normal.push_back(p.z);
|
||||
}
|
||||
} {
|
||||
for ( uint i = 0; i < model.position.front.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.position.front[i*3+0]; p.y = model.position.front[i*3+1]; p.z = model.position.front[i*3+2];
|
||||
p.x *= this->m_size.x; p.y *= this->m_size.y; p.z *= this->m_size.z;
|
||||
p.z -= this->m_size.z;
|
||||
position.push_back(p.x); position.push_back(p.y); position.push_back(p.z);
|
||||
}
|
||||
for ( uint i = 0; i < model.uv.front.size() / 2; ++i ) {
|
||||
struct { float x, y; } p;
|
||||
p.x = model.uv.front[i*2+0]; p.y = model.uv.front[i*2+1];
|
||||
// p.x *= offset.uv.x; p.y *= offset.uv.y;
|
||||
// p.x += offset.uv.u; p.y += offset.uv.v;
|
||||
uv.push_back(p.x); uv.push_back(p.y);
|
||||
}
|
||||
for ( uint i = 0; i < model.normal.front.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.normal.front[i*3+0]; p.y = model.normal.front[i*3+1]; p.z = model.normal.front[i*3+2];
|
||||
normal.push_back(p.x); normal.push_back(p.y); normal.push_back(p.z);
|
||||
}
|
||||
} {
|
||||
for ( uint i = 0; i < model.position.back.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.position.back[i*3+0]; p.y = model.position.back[i*3+1]; p.z = model.position.back[i*3+2];
|
||||
p.x *= this->m_size.x; p.y *= this->m_size.y; p.z *= this->m_size.z;
|
||||
p.z += this->m_size.z;
|
||||
position.push_back(p.x); position.push_back(p.y); position.push_back(p.z);
|
||||
}
|
||||
for ( uint i = 0; i < model.uv.back.size() / 2; ++i ) {
|
||||
struct { float x, y; } p;
|
||||
p.x = model.uv.back[i*2+0]; p.y = model.uv.back[i*2+1];
|
||||
// p.x *= offset.uv.x; p.y *= offset.uv.y;
|
||||
// p.x += offset.uv.u; p.y += offset.uv.v;
|
||||
uv.push_back(p.x); uv.push_back(p.y);
|
||||
}
|
||||
for ( uint i = 0; i < model.normal.back.size() / 3; ++i ) {
|
||||
struct { float x, y, z; } p;
|
||||
p.x = model.normal.back[i*3+0]; p.y = model.normal.back[i*3+1]; p.z = model.normal.back[i*3+2];
|
||||
normal.push_back(p.x); normal.push_back(p.y); normal.push_back(p.z);
|
||||
}
|
||||
}
|
||||
|
||||
mesh.index();
|
||||
mesh.generate();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for ( uint x = 0; x < this->m_size.x; ++x ) {
|
||||
for ( uint y = 0; y < this->m_size.y; ++y ) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "../light/light.h"
|
||||
|
||||
void ext::Region::initialize() {
|
||||
this->addComponent<pod::Physics>();
|
||||
this->addComponent<pod::Transform<>>();
|
||||
this->addComponent<ext::TerrainGenerator>();
|
||||
|
||||
@ -26,8 +25,6 @@ void ext::Region::load() {
|
||||
size.y = metadata["region"]["size"][1].asUInt();
|
||||
size.z = metadata["region"]["size"][2].asUInt();
|
||||
}
|
||||
generator.initialize(size);
|
||||
generator.generate();
|
||||
|
||||
float r = (rand() % 100) / 100.0;
|
||||
bool addLight = r < metadata["region"]["light"]["random"].asFloat();
|
||||
@ -49,30 +46,13 @@ void ext::Region::load() {
|
||||
if ( addLight ) {
|
||||
// std::cout << metadata["region"]["location"][0] << ", " << metadata["region"]["location"][1] << ", " << metadata["region"]["location"][2] << std::endl;
|
||||
pod::Vector3 color = { 1.0, 1.0, 1.0 }; {
|
||||
float r = (rand() % 256) / 256.0; color.x -= r;
|
||||
float g = (rand() % 256) / 256.0; color.y -= g;
|
||||
float b = (rand() % 256) / 256.0; color.z -= b;
|
||||
// float r = (rand() % 256) / 256.0; color.x -= r;
|
||||
// float g = (rand() % 256) / 256.0; color.y -= g;
|
||||
// float b = (rand() % 256) / 256.0; color.z -= b;
|
||||
|
||||
color = uf::vector::normalize( color );
|
||||
color = uf::vector::normalize( color );
|
||||
}
|
||||
int radius = metadata["region"]["light"]["radius"].asInt();
|
||||
for ( int i = 0; i < radius; ++i ) {
|
||||
uf::Entity* entity = new ext::Light;
|
||||
if ( !((ext::Object*) entity)->load("./light/config.json") ) { uf::iostream << "Error loading `" << "./light/config.json" << "!" << "\n"; delete entity; return; }
|
||||
this->addChild(*entity);
|
||||
entity->initialize();
|
||||
|
||||
pod::Transform<>& parent = this->getComponent<pod::Transform<>>();
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();//entity->getComponent<uf::Camera>().getTransform();
|
||||
entity->getComponent<uf::Camera>().getTransform().reference = &transform;
|
||||
|
||||
transform = uf::transform::initialize( transform );
|
||||
transform.position = parent.position;
|
||||
// transform.position.y += size.y / 2;
|
||||
uf::transform::rotate( transform, transform.up, (360.0 / radius) * (3.1415926/180.0) * i );
|
||||
entity->getComponent<uf::Camera>().update(true);
|
||||
((ext::Light*)entity)->setColor( color );
|
||||
}
|
||||
/* Up */ if ( metadata["region"]["light"]["up"].asBool() ) {
|
||||
uf::Entity* entity = new ext::Light;
|
||||
if ( !((ext::Object*) entity)->load("./light/config.json") ) { uf::iostream << "Error loading `" << "./light/config.json" << "!" << "\n"; delete entity; return; }
|
||||
@ -80,12 +60,11 @@ void ext::Region::load() {
|
||||
entity->initialize();
|
||||
|
||||
pod::Transform<>& parent = this->getComponent<pod::Transform<>>();
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();//entity->getComponent<uf::Camera>().getTransform();
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();
|
||||
entity->getComponent<uf::Camera>().getTransform().reference = &transform;
|
||||
|
||||
transform = uf::transform::initialize( transform );
|
||||
transform.position = parent.position;
|
||||
// transform.position.y += size.y / 2;
|
||||
uf::transform::rotate( transform, transform.right, 1.5708 * 1 );
|
||||
entity->getComponent<uf::Camera>().setFov(120);
|
||||
entity->getComponent<uf::Camera>().update(true);
|
||||
@ -98,19 +77,36 @@ void ext::Region::load() {
|
||||
entity->initialize();
|
||||
|
||||
pod::Transform<>& parent = this->getComponent<pod::Transform<>>();
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();//entity->getComponent<uf::Camera>().getTransform();
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();
|
||||
entity->getComponent<uf::Camera>().getTransform().reference = &transform;
|
||||
|
||||
transform = uf::transform::initialize( transform );
|
||||
transform.position = parent.position;
|
||||
// transform.position.y += size.y / 2;
|
||||
uf::transform::rotate( transform, transform.right, 1.5708 * 3 );
|
||||
entity->getComponent<uf::Camera>().setFov(120);
|
||||
entity->getComponent<uf::Camera>().update(true);
|
||||
((ext::Light*)entity)->setColor( color );
|
||||
}
|
||||
for ( int i = 0; i < radius; ++i ) {
|
||||
uf::Entity* entity = new ext::Light;
|
||||
if ( !((ext::Object*) entity)->load("./light/config.json") ) { uf::iostream << "Error loading `" << "./light/config.json" << "!" << "\n"; delete entity; return; }
|
||||
this->addChild(*entity);
|
||||
entity->initialize();
|
||||
|
||||
pod::Transform<>& parent = this->getComponent<pod::Transform<>>();
|
||||
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();//entity->getComponent<uf::Camera>().getTransform();
|
||||
entity->getComponent<uf::Camera>().getTransform().reference = &transform;
|
||||
|
||||
transform = uf::transform::initialize( transform );
|
||||
transform.position = parent.position;
|
||||
uf::transform::rotate( transform, transform.up, (360.0 / radius) * (3.1415926/180.0) * i );
|
||||
entity->getComponent<uf::Camera>().update(true);
|
||||
((ext::Light*)entity)->setColor( color );
|
||||
}
|
||||
}
|
||||
|
||||
generator.initialize(size);
|
||||
generator.generate();
|
||||
/* Collider */ {
|
||||
pod::Transform<>& transform = this->getComponent<pod::Transform<>>();
|
||||
uf::CollisionBody& collider = this->getComponent<uf::CollisionBody>();
|
||||
@ -138,8 +134,6 @@ void ext::Region::load() {
|
||||
// generator.rasterize(mesh, *this);
|
||||
}
|
||||
void ext::Region::render() {
|
||||
uf::Entity::render();
|
||||
|
||||
if ( !this->m_parent ) return;
|
||||
ext::World& parent = this->getRootParent<ext::World>();
|
||||
|
||||
@ -148,6 +142,30 @@ void ext::Region::render() {
|
||||
uf::Camera& camera = parent.getCamera(); //parent.getPlayer().getComponent<uf::Camera>();
|
||||
uf::Mesh& mesh = this->getComponent<uf::Mesh>();
|
||||
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
const uf::Serializer& pMetadata = parent.getComponent<uf::Serializer>();
|
||||
/*
|
||||
if ( pMetadata["state"].asInt() == 1 && metadata["light"]["rendered"] != Json::nullValue ) {
|
||||
const ext::Player& player = parent.getPlayer();
|
||||
const pod::Transform<>& pTransform = player.getComponent<pod::Transform<>>();
|
||||
pod::Vector3ui size = {
|
||||
metadata["region"]["size"][0].asUInt(),
|
||||
metadata["region"]["size"][1].asUInt(),
|
||||
metadata["region"]["size"][2].asUInt(),
|
||||
};
|
||||
pod::Vector3 pointf = uf::vector::divide(pTransform.position, {size.x, size.y, size.z});
|
||||
pod::Vector3i point = {
|
||||
(int) (pointf.x + (pointf.x > 0 ? 0.5 : -0.5)),
|
||||
(int) (pointf.y + (pointf.y > 0 ? 0.5 : -0.5)),
|
||||
(int) (pointf.z + (pointf.z > 0 ? 0.5 : -0.5)),
|
||||
};
|
||||
if ( point.y != transform.position.y / size.y ) return;
|
||||
}
|
||||
metadata["light"]["rendered"] = true;
|
||||
*/
|
||||
|
||||
uf::Entity::render();
|
||||
|
||||
int slot = 0;
|
||||
if ( this->getParent<ext::Terrain>().hasComponent<uf::Texture>() ) {
|
||||
uf::Texture& texture = this->getParent<ext::Terrain>().getComponent<uf::Texture>();
|
||||
|
@ -9,6 +9,7 @@ void ext::Terrain::initialize() {
|
||||
|
||||
this->generate();
|
||||
}
|
||||
#include <uf/utils/thread/thread.h>
|
||||
void ext::Terrain::tick() {
|
||||
uf::Entity::tick();
|
||||
ext::World& parent = this->getRootParent<ext::World>();
|
||||
@ -21,8 +22,8 @@ void ext::Terrain::tick() {
|
||||
metadata["region"]["size"][2].asUInt(),
|
||||
};
|
||||
if ( this->m_children.empty() ) return;
|
||||
|
||||
for ( uf::Entity* kv : this->m_children ) {
|
||||
|
||||
for ( uf::Entity* kv : this->m_children ) { if ( !kv ) continue;
|
||||
const pod::Transform<>& transform = kv->getComponent<pod::Transform<>>();
|
||||
pod::Vector3i location = {
|
||||
(int) (transform.position.x / size.x),
|
||||
@ -32,10 +33,16 @@ void ext::Terrain::tick() {
|
||||
|
||||
if ( !this->inBounds(location) ) {
|
||||
this->degenerate(location);
|
||||
this->generate();
|
||||
pod::Thread& thread = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", true );
|
||||
auto function = [&]() -> int {
|
||||
this->generate();
|
||||
return 0;
|
||||
};
|
||||
uf::thread::add( thread, function, true );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for ( uf::Entity* kv : this->m_children ) {
|
||||
// Defer generation to make sure all neighbors have their voxels generated
|
||||
std::vector<ext::Region*> queue;
|
||||
@ -54,6 +61,7 @@ void ext::Terrain::tick() {
|
||||
generator.rasterize(mesh, *kv);
|
||||
}
|
||||
}
|
||||
|
||||
this->relocatePlayer();
|
||||
}
|
||||
void ext::Terrain::render() {
|
||||
@ -223,8 +231,6 @@ void ext::Terrain::generate( const pod::Vector3i& position ) {
|
||||
m["region"]["location"][0] = position.x;
|
||||
m["region"]["location"][1] = position.y;
|
||||
m["region"]["location"][2] = position.z;
|
||||
|
||||
// region.initialize();
|
||||
}
|
||||
|
||||
}
|
||||
@ -244,26 +250,9 @@ void ext::Terrain::degenerate( const pod::Vector3i& position ) {
|
||||
(int) (transform.position.z / size.z),
|
||||
};
|
||||
if ( uf::vector::equals( location, position ) ) {
|
||||
for ( uf::Entity* e : kv->getChildren() ) if ( e->getName() == "Player" ) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
for ( uf::Entity* e : kv->getChildren() ) if ( e->getName() == "Player" ) {
|
||||
this->getRootParent<ext::World>().moveChild(*e);
|
||||
std::cout << "Emergency Provisions" << std::endl;
|
||||
std::function<void(const uf::Entity*, int)> recurse = [&]( const uf::Entity* parent, int indent ) {
|
||||
for ( const uf::Entity* entity : parent->getChildren() ) {
|
||||
for ( int i = 0; i < indent; ++i ) std::cout<<"\t";
|
||||
std::cout<<entity->getName()<<std::endl;
|
||||
recurse(entity, indent + 1);
|
||||
}
|
||||
}; recurse(&this->getRootParent<ext::World>(), 0);
|
||||
std::cout << "Emergency Provisions" << std::endl;
|
||||
}
|
||||
*/
|
||||
for ( uf::Entity* e : kv->getChildren() ) if ( e->getName() == "Player" ) return;
|
||||
delete kv; *it = NULL;
|
||||
this->m_children.erase(it);
|
||||
// this->generate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "./gui/gui.h"
|
||||
|
||||
#include <uf/utils/audio/audio.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
|
||||
namespace {
|
||||
uf::Camera* camera;
|
||||
@ -23,13 +24,9 @@ void ext::World::initialize() {
|
||||
}
|
||||
|
||||
void ext::World::tick() {
|
||||
static bool first = true; if ( first ) { first = false;
|
||||
uf::physics::tick();
|
||||
}
|
||||
|
||||
uf::Entity::tick();
|
||||
|
||||
{
|
||||
/* Calibrates Polyfill */ {
|
||||
static float x = 1.07986, y = 24.7805;
|
||||
if ( uf::Window::isKeyPressed("L") ) x += 0.01;
|
||||
if ( uf::Window::isKeyPressed("J") ) x -= 0.01;
|
||||
@ -38,7 +35,7 @@ void ext::World::tick() {
|
||||
if ( uf::Window::isKeyPressed("O") ) std::cout << x << ", " << y << std::endl;
|
||||
glPolygonOffset(x, y);
|
||||
}
|
||||
if (uf::Window::isKeyPressed("U")) {
|
||||
/* Print World Tree */ if (uf::Window::isKeyPressed("U")) {
|
||||
std::function<void(const uf::Entity*, int)> recurse = [&]( const uf::Entity* parent, int indent ) {
|
||||
for ( const uf::Entity* entity : parent->getChildren() ) {
|
||||
for ( int i = 0; i < indent; ++i ) std::cout<<"\t";
|
||||
@ -47,14 +44,14 @@ void ext::World::tick() {
|
||||
}
|
||||
}; recurse(this, 0);
|
||||
}
|
||||
{
|
||||
|
||||
/* Updates Sound Listener */ {
|
||||
ext::Player& player = this->getPlayer();
|
||||
pod::Transform<>& transform = player.getComponent<pod::Transform<>>();
|
||||
|
||||
ext::oal.listener( "POSITION", { transform.position.x, transform.position.y, transform.position.z } );
|
||||
ext::oal.listener( "VELOCITY", { 0, 0, 0 } );
|
||||
ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user