From ef8694dd609878abb3546c405e1ff6ff8e09152b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 24 Mar 2013 10:06:43 -0700 Subject: [PATCH] 1) Added createSphere() to VoxelSystem to create a sphere 2) Added pointToVoxel() to SharedUtils, this will give you a voxel code given x,y,z,s,r,g,b 3) Added '.' keyboard interface to create a random sphere in the local voxel system --- interface/src/VoxelSystem.cpp | 83 +++++++++++++++++ interface/src/VoxelSystem.h | 2 +- interface/src/main.cpp | 46 ++++++++++ shared/src/SharedUtil.cpp | 163 ++++++++++++++++++++++++++++++++++ shared/src/SharedUtil.h | 4 + 5 files changed, 297 insertions(+), 1 deletion(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 4aaee09ed7..3b5f6a267b 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -98,6 +98,88 @@ void VoxelSystem::loadVoxelsFile(char* fileName) { voxelsToRender = (voxelsRendered > 0); } +////////////////////////////////////////////////////////////////////////////////////////// +// Method: VoxelSystem::createSphere() +// Description: Creates a sphere of voxels in the local system at a given location/radius +// To Do: Move this function someplace better? I put it here because we need a +// mechanism to tell the system to redraw it's arrays after voxels are done +// being added. This is a concept mostly only understood by VoxelSystem. +// Complaints: Brad :) +void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid) +{ + // Psuedocode for creating a sphere: + // + // for (theta from 0 to 2pi): + // for (phi from 0 to pi): + // x = xc+r*cos(theta)*sin(phi) + // y = yc+r*sin(theta)*sin(phi) + // z = zc+r*cos(phi) + + int t=0; // total points + + // We want to make sure that as we "sweep" through our angles + // we use a delta angle that's small enough to not skip any voxels + // we can calculate theta from our desired arc length + // + // lenArc = ndeg/360deg * 2pi*R + // lenArc = theta/2pi * 2pi*R + // lenArc = theta*R + // theta = lenArc/R + // theta = g/r + float angleDelta = (s/r); + + // assume solid for now + float ri = 0.0; + if (!solid) + { + ri=r; // just the outer surface + } + // If you also iterate form the interior of the sphere to the radius, makeing + // larger and larger sphere's you'd end up with a solid sphere. And lots of voxels! + for (; ri <= r; ri+=s) + { + for (float theta=0.0; theta <= 2*M_PI; theta += angleDelta) + { + for (float phi=0.0; phi <= M_PI; phi += angleDelta) + { + t++; // total voxels + float x = xc+r*cos(theta)*sin(phi); + float y = yc+r*sin(theta)*sin(phi); + float z = zc+r*cos(phi); + /* + std::cout << " r=" << r; + std::cout << " theta=" << theta; + std::cout << " phi=" << phi; + std::cout << " x=" << x; + std::cout << " y=" << y; + std::cout << " z=" << z; + std::cout << " t=" << t; + std::cout << std::endl; + */ + + // random color data + unsigned char red = randomColorValue(65); + unsigned char green = randomColorValue(65); + unsigned char blue = randomColorValue(65); + + unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); + tree->readCodeColorBufferToTree(voxelData); + delete voxelData; + + } + } + } + + // reset the verticesEndPointer so we're writing to the beginning of the array + verticesEndPointer = verticesArray; + // call recursive function to populate in memory arrays + // it will return the number of voxels added + voxelsRendered = treeToArrays(tree->rootNode); + // set the boolean if there are any voxels to be rendered so we re-fill the VBOs + voxelsToRender = (voxelsRendered > 0); +} + + void VoxelSystem::parseData(void *data, int size) { // output the bits received from the voxel server unsigned char *voxelData = (unsigned char *) data + 1; @@ -243,3 +325,4 @@ void VoxelSystem::simulate(float deltaTime) { } + diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index adb73808de..6755886225 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -34,7 +34,7 @@ public: void setVoxelsRendered(int v) {voxelsRendered = v;}; int getVoxelsRendered() {return voxelsRendered;}; void loadVoxelsFile(char* fileName); - + void createSphere(float r,float xc, float yc, float zc, float s, bool solid); private: int voxelsRendered; VoxelTree *tree; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index e933169e1d..e572942823 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -692,6 +692,45 @@ void display(void) framecount++; } +void testPointToVoxel() +{ + float y=0; + float z=0; + float s=0.1; + for (float x=0; x<=1; x+= 0.05) + { + std::cout << " x=" << x << " "; + + unsigned char red = 200; //randomColorValue(65); + unsigned char green = 200; //randomColorValue(65); + unsigned char blue = 200; //randomColorValue(65); + + unsigned char* voxelCode = pointToVoxel(x, y, z, s,red,green,blue); + printVoxelCode(voxelCode); + delete voxelCode; + std::cout << std::endl; + } +} + +void addRandomSphere() +{ + float r = randFloatInRange(0.05,0.1); + float xc = randFloatInRange(r,(1-r)); + float yc = randFloatInRange(r,(1-r)); + float zc = randFloatInRange(r,(1-r)); + float s = 0.002; // size of voxels to make up surface of sphere + bool solid = false; + + printf("random sphere\n"); + printf("radius=%f\n",r); + printf("xc=%f\n",xc); + printf("yc=%f\n",yc); + printf("zc=%f\n",zc); + + voxels.createSphere(r,xc,yc,zc,s,solid); +} + + const float KEYBOARD_YAW_RATE = 0.8; const float KEYBOARD_STRAFE_RATE = 0.03; const float KEYBOARD_FLY_RATE = 0.08; @@ -766,6 +805,13 @@ void key(unsigned char k, int x, int y) { myHead.SetNewHeadTarget((randFloat()-0.5)*20.0, (randFloat()-0.5)*20.0); } + + // press the . key to get a new random sphere of voxels added + if (k == '.') + { + addRandomSphere(); + //testPointToVoxel(); + } } // diff --git a/shared/src/SharedUtil.cpp b/shared/src/SharedUtil.cpp index 3340241fdd..3e9e75e2bb 100644 --- a/shared/src/SharedUtil.cpp +++ b/shared/src/SharedUtil.cpp @@ -28,6 +28,10 @@ float randFloat () { return (rand() % 10000)/10000.f; } +float randFloatInRange (float min,float max) { + return min + ((rand() % 10000)/10000.f * (max-min)); +} + unsigned char randomColorValue(int miniumum) { return miniumum + (rand() % (255 - miniumum)); } @@ -104,3 +108,162 @@ bool cmdOptionExists(char** begin, char** end, const std::string& option) { return std::find(begin, end, option) != end; } + +////////////////////////////////////////////////////////////////////////////////////////// +// Function: pointToVoxel() +// Description: Given a universal point with location x,y,z this will return the voxel +// voxel code corresponding to the closest voxel which encloses a cube with +// lower corners at x,y,z, having side of length S. +// The input values x,y,z range 0.0 <= v < 1.0 +// TO DO: This code is not very DRY. It should be cleaned up to be DRYer. +// IMPORTANT: The voxel is returned to you a buffer which you MUST delete when you are +// done with it. +// Usage: +// unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue); +// tree->readCodeColorBufferToTree(voxelData); +// delete voxelData; +// +// Complaints: Brad :) +unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, unsigned char g, unsigned char b ) { + + float xTest, yTest, zTest, sTest; + xTest = yTest = zTest = sTest = 0.5; + + // First determine the voxelSize that will properly encode a + // voxel of size S. + int voxelSizeInBits = 0; + while (sTest > s) { + sTest /= 2.0; + voxelSizeInBits+=3; + } + + unsigned int voxelSizeInBytes = (voxelSizeInBits/8)+1; + unsigned int voxelSizeInOctets = (voxelSizeInBits/3); + unsigned int voxelBufferSize = voxelSizeInBytes+1+3; // 1 for size, 3 for color + + // allocate our resulting buffer + unsigned char* voxelOut = new unsigned char[voxelBufferSize]; + + // first byte of buffer is always our size in octets + voxelOut[0]=voxelSizeInOctets; + + sTest = 0.5; // reset sTest so we can do this again. + + unsigned char byte = 0; // we will be adding coding bits here + int bitInByteNDX = 0; // keep track of where we are in byte as we go + int byteNDX = 1; // keep track of where we are in buffer of bytes as we go + int octetsDone = 0; + + // Now we actually fill out the voxel code + while (octetsDone < voxelSizeInOctets) { + + if (x > xTest) { + // + byte = (byte << 1) | true; + xTest += sTest/2.0; + } + else { + // + byte = (byte << 1) | false; + xTest -= sTest/2.0; + } + bitInByteNDX++; + // If we've reached the last bit of the byte, then we want to copy this byte + // into our buffer. And get ready to start on a new byte + if (bitInByteNDX > 7) + { + voxelOut[byteNDX]=byte; + byteNDX++; + bitInByteNDX=0; + byte=0; + } + + if (y > yTest) { + // + byte = (byte << 1) | true; + yTest += sTest/2.0; + } + else { + // + byte = (byte << 1) | false; + yTest -= sTest/2.0; + } + bitInByteNDX++; + // If we've reached the last bit of the byte, then we want to copy this byte + // into our buffer. And get ready to start on a new byte + if (bitInByteNDX > 7) + { + voxelOut[byteNDX]=byte; + byteNDX++; + bitInByteNDX=0; + byte=0; + } + + if (z > zTest) { + // + byte = (byte << 1) | true; + zTest += sTest/2.0; + } + else { + // + byte = (byte << 1) | false; + zTest -= sTest/2.0; + } + bitInByteNDX++; + // If we've reached the last bit of the byte, then we want to copy this byte + // into our buffer. And get ready to start on a new byte + if (bitInByteNDX > 7) + { + voxelOut[byteNDX]=byte; + byteNDX++; + bitInByteNDX=0; + byte=0; + } + + octetsDone++; + sTest /= 2.0; + } + + // If we've got here, and we didn't fill the last byte, we need to zero pad this + // byte before we copy it into our buffer. + if (bitInByteNDX > 0 && bitInByteNDX < 7) + { + // Pad the last byte + while (bitInByteNDX <= 7) + { + byte = (byte << 1) | false; + bitInByteNDX++; + } + + // Copy it into our output buffer + voxelOut[byteNDX]=byte; + byteNDX++; + } + // copy color data + voxelOut[byteNDX]=r; + voxelOut[byteNDX+1]=g; + voxelOut[byteNDX+2]=b; + + return voxelOut; +} + +void printVoxelCode(unsigned char* voxelCode) +{ + unsigned char octets = voxelCode[0]; + unsigned int voxelSizeInBits = octets*3; + unsigned int voxelSizeInBytes = (voxelSizeInBits/8)+1; + unsigned int voxelSizeInOctets = (voxelSizeInBits/3); + unsigned int voxelBufferSize = voxelSizeInBytes+1+3; // 1 for size, 3 for color + + printf("octets=%d\n",octets); + printf("voxelSizeInBits=%d\n",voxelSizeInBits); + printf("voxelSizeInBytes=%d\n",voxelSizeInBytes); + printf("voxelSizeInOctets=%d\n",voxelSizeInOctets); + printf("voxelBufferSize=%d\n",voxelBufferSize); + + for(int i=0;i