diff options
author | click <none@none> | 2010-06-05 00:59:25 +0200 |
---|---|---|
committer | click <none@none> | 2010-06-05 00:59:25 +0200 |
commit | e77716188861d4aa83b227a90e04a66b63baeb1f (patch) | |
tree | ce72764181a760314ec851f7535052dcf75649db /dep/src/g3dlite/PrecomputedRandom.cpp | |
parent | 1426c2970f42a2d065198806f750bf5dd28d580b (diff) |
HIGHLY EXPERIMENTAL - USE AT YOUR OWN RISK
Implement the use of the new vmap3-format by Lynx3d (mad props to you for this, and thanks for the talks earlier)
+ reduced Vmap size to less than one third, and improve precision
+ indoor/outdoor check which allows automatic unmounting of players
+ additional area information from WMOAreaTable.dbc, removed existing "hacks"
+ WMO liquid information for swimming and fishing correctly in buildings/cities/caves/instances (lava and slime WILL hurt from now on!)
- buildfiles for windows are not properly done, and will need to be sorted out
NOTE: Do NOT annoy Lynx3d about this, any issues with this "port" is entirely our fault !
THIS REVISION IS CONSIDERED UNSTABLE AND CONTAINS WORK IN PROGRESS - USE AT YOUR OWN RISK!
--HG--
branch : trunk
Diffstat (limited to 'dep/src/g3dlite/PrecomputedRandom.cpp')
-rw-r--r-- | dep/src/g3dlite/PrecomputedRandom.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/dep/src/g3dlite/PrecomputedRandom.cpp b/dep/src/g3dlite/PrecomputedRandom.cpp new file mode 100644 index 00000000000..387ded35195 --- /dev/null +++ b/dep/src/g3dlite/PrecomputedRandom.cpp @@ -0,0 +1,125 @@ +/** + @file PrecomputedRandom.cpp + + @maintainer Morgan McGuire, http://graphics.cs.williams.edu + + @created 2009-03-31 + @edited 2009-07-01 + + Copyright 2000-2009, Morgan McGuire. + All rights reserved. + */ + +#include "G3D/PrecomputedRandom.h" +#include "G3D/System.h" + +namespace G3D { + +PrecomputedRandom::PrecomputedRandom(int dataSize, uint32 seed) : + Random((void*)NULL), + m_hemiUniform(NULL), + m_sphereBits(NULL), + m_modMask(dataSize - 1), + m_freeData(true) { + + alwaysAssertM(isPow2(dataSize), "dataSize must be a power of 2"); + m_index = seed & m_modMask; + + HemiUniformData* h; + SphereBitsData* s; + m_hemiUniform = h = (HemiUniformData*) System::malloc(sizeof(HemiUniformData) * dataSize); + m_sphereBits = s = (SphereBitsData*) System::malloc(sizeof(SphereBitsData) * dataSize); + + Random r; + + for (int i = 0; i < dataSize; ++i) { + h[i].uniform = r.uniform(); + r.cosHemi(h[i].cosHemiX, h[i].cosHemiY, h[i].cosHemiZ); + + s[i].bits = r.bits(); + r.sphere(s[i].sphereX, s[i].sphereY, s[i].sphereZ); + } + +} + + +PrecomputedRandom::PrecomputedRandom(const HemiUniformData* data1, const SphereBitsData* data2, int dataSize, uint32 seed) : + Random((void*)NULL), + m_hemiUniform(data1), + m_sphereBits(data2), + m_modMask(dataSize - 1), + m_freeData(false) { + + m_index = seed & m_modMask; + alwaysAssertM(isPow2(dataSize), "dataSize must be a power of 2"); +} + + +PrecomputedRandom::~PrecomputedRandom() { + if (m_freeData) { + System::free(const_cast<HemiUniformData*>(m_hemiUniform)); + System::free(const_cast<SphereBitsData*>(m_sphereBits)); + } +} + +float PrecomputedRandom::uniform(float low, float high) { + m_index = (m_index + 1) & m_modMask; + return low + m_hemiUniform[m_index].uniform * (high - low); +} + + +float PrecomputedRandom::uniform() { + m_index = (m_index + 1) & m_modMask; + return m_hemiUniform[m_index].uniform; +} + + +void PrecomputedRandom::cosHemi(float& x, float& y, float& z) { + m_index = (m_index + 1) & m_modMask; + x = m_hemiUniform[m_index].cosHemiX; + y = m_hemiUniform[m_index].cosHemiY; + z = m_hemiUniform[m_index].cosHemiZ; +} + +void PrecomputedRandom::cosPowHemi(const float k, float& x, float& y, float& z) { + // Computing a cosPowHemi costs 4 slow functions (pow, sqrt, sin, + // cos). We can do it with two, given a cosHemi sample, basically + // saving the cost of sin and cos and making a single 128-byte + // memory read (for a vector) instead of two (for adjacent uniform + // floats). + + // cos^1 distribution sample + float cos1; + cosHemi(x, y, cos1); + + // Fix the distribution by adjusting the cosine: + // rnd(cos^k t) = (rnd(cos(t))^2)^(1/k) + + // produces cos^k distribution sample + z = pow(cos1, 2.0f / (1.0f + k)); + + // Rescale x and y by sqrt(1.0f - square(z)) / sqrt(x*x + y*y). + // Add a very tiny offset to handle the (almost impossibly unlikely) case where + // z = 1 and x^2+y^2 = 0. + static const float eps = 0.000001f; + const float s = sqrt((1.0f + eps - square(z)) / (square(x) + square(y) + eps)); + + x *= s; + y *= s; +} + + +uint32 PrecomputedRandom::bits() { + m_index = (m_index + 1) & m_modMask; + return m_sphereBits[m_index].bits; +} + + +void PrecomputedRandom::sphere(float& x, float& y, float& z) { + m_index = (m_index + 1) & m_modMask; + x = m_sphereBits[m_index].sphereX; + y = m_sphereBits[m_index].sphereY; + z = m_sphereBits[m_index].sphereZ; +} + +} |