mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
adding some new tools
This commit is contained in:
parent
804943e2fb
commit
17427a9c4d
3 changed files with 967 additions and 0 deletions
39
tools/README.md
Normal file
39
tools/README.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
tools
|
||||
=========
|
||||
|
||||
Various command line tools for interacting with the Voxel Server and Interface.
|
||||
|
||||
objtohio.php :
|
||||
|
||||
USAGE:
|
||||
php objtohio.php -i 'inputFileName' -o 'outputFileName' -m [blocks|wireframe|surface] -s [voxel size]
|
||||
|
||||
DESCRIPTION:
|
||||
Converts a Wavefront OBJ file into a voxel binary file suitable for loading locally into the client or
|
||||
loading on the voxel server or sending to the voxel server using sendvoxels.php
|
||||
|
||||
NOTE:
|
||||
Depending on the size of the model, it might take a lot of memory, so you will likely need to include
|
||||
the -d memory_limit=4096M option
|
||||
|
||||
EXAMPLE:
|
||||
|
||||
php -d memory_limit=4096M objtohio.php -i "Samples/little girl head-obj.obj" -o girl-test.hio -s 0.006
|
||||
|
||||
|
||||
sendvoxels.php :
|
||||
|
||||
USAGE:
|
||||
sendvoxels.php -i 'inputFileName' -s [serverip] -p [port] -c [I|R]
|
||||
|
||||
DESCRIPTION:
|
||||
Sends the contents of a voxel binary file to a voxel server. Can either Insert or Remove voxels. Command defaults
|
||||
to "I" insert.
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
php sendvoxels.php -s 192.168.1.116 -i 'girl-test.hio' -c I
|
||||
php sendvoxels.php -s 192.168.1.116 -i 'girl-test.hio' -c R
|
||||
php sendvoxels.php -s 192.168.1.116 -i 'girl-test.hio'
|
||||
|
||||
|
860
tools/objtohio.php
Normal file
860
tools/objtohio.php
Normal file
|
@ -0,0 +1,860 @@
|
|||
<?php
|
||||
// Parse/Read OBJ file
|
||||
//
|
||||
// USAGE: php objtohio.php -i 'inputFileName' -o 'outputFileName' -m [blocks|wireframe|surface] -s [voxel size]
|
||||
// NOTE: Depending on the size of the model, it might take a lot of memory, so you will likely need to include
|
||||
// the -d memory_limit=4096M option
|
||||
//
|
||||
global $lastmsg;
|
||||
$lastmsg='';
|
||||
|
||||
function echoProgress($msg,$keep=false) {
|
||||
global $lastmsg;
|
||||
for($bs=0;$bs<strlen($lastmsg);$bs++) {
|
||||
echo chr(8);
|
||||
}
|
||||
for($bs=0;$bs<strlen($lastmsg);$bs++) {
|
||||
echo ' ';
|
||||
}
|
||||
for($bs=0;$bs<strlen($lastmsg);$bs++) {
|
||||
echo chr(8);
|
||||
}
|
||||
echo $msg;
|
||||
if (!$keep)
|
||||
$lastmsg=$msg;
|
||||
else
|
||||
$lastmsg='';
|
||||
}
|
||||
|
||||
|
||||
class Vertice
|
||||
{
|
||||
public $x;
|
||||
public $y;
|
||||
public $z;
|
||||
}
|
||||
|
||||
class Voxel
|
||||
{
|
||||
public $material_name;
|
||||
public $x;
|
||||
public $y;
|
||||
public $z;
|
||||
public $s;
|
||||
}
|
||||
|
||||
global $renderMode;
|
||||
$renderMode = 'surface';
|
||||
|
||||
global $minVoxelSize;
|
||||
$minVoxelSize = 0.003; // default
|
||||
|
||||
function findVoxelsOfPolygon($vertices,$s=false,$material='default') {
|
||||
//echo "findVoxelsOfPolygon() vertices=".print_r($vertices,1);
|
||||
|
||||
global $renderMode;
|
||||
switch ($renderMode)
|
||||
{
|
||||
case 'blocks':
|
||||
return polygonAsBlocks($vertices,$s,$material);
|
||||
case 'wireframe':
|
||||
//echo "findVoxelsOfPolygon() calling... polygonAsWireFrame() vertices=".print_r($vertices,1);
|
||||
return polygonAsWireFrame($vertices,$s,$material);
|
||||
default:
|
||||
case 'surface':
|
||||
return polygonAsSurface($vertices,$s,$material);
|
||||
}
|
||||
}
|
||||
|
||||
function polygonAsWireFrame($vertices,$s=false,$material='default')
|
||||
{
|
||||
if ($s === false) {
|
||||
global $minVoxelSize;
|
||||
$s = $minVoxelSize;
|
||||
}
|
||||
//echo "polygonAsWireFrame()\n";
|
||||
//echo "polygonAsWireFrame() vertices=".print_r($vertices,1);
|
||||
|
||||
$maxNdx = count($vertices);
|
||||
//echo "***** polygonAsWireFrame() maxNdx=$maxNdx\n";
|
||||
$voxels = array();
|
||||
for ($ndx = 0; $ndx < $maxNdx; $ndx++)
|
||||
{
|
||||
$v1 = $vertices[$ndx];
|
||||
$v2 = ($ndx < ($maxNdx-1)) ? $vertices[$ndx+1] : $vertices[0];
|
||||
$lineVoxels = voxelLine($v1->x,$v1->y,$v1->z,$v2->x,$v2->y,$v2->z,$s,$material);
|
||||
//echo "polygonAsWireFrame() lineVoxels=".print_r($lineVoxels,1);
|
||||
$voxels = array_merge($voxels,$lineVoxels);
|
||||
}
|
||||
return $voxels;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Find the smallest Voxel of a random polygon.
|
||||
// find minimums of X,Y,Z
|
||||
// find maximums of X,Y,Z
|
||||
// find lengths of max-mins for X,Y,Z
|
||||
// Voxel Point = (minX, minY, minZ,longest side)
|
||||
function polygonAsBlocks($vertices,$s=false,$material='default')
|
||||
{
|
||||
if ($s === false) {
|
||||
global $minVoxelSize;
|
||||
$s = $minVoxelSize;
|
||||
}
|
||||
|
||||
//echo "polygonAsBlocks()\n";
|
||||
$minX = false;
|
||||
$minY = false;
|
||||
$minZ = false;
|
||||
$maxX = false;
|
||||
$maxY = false;
|
||||
$maxZ = false;
|
||||
foreach ($vertices as $vertex)
|
||||
{
|
||||
if ($minX === false || $vertex->x < $minX)
|
||||
$minX = $vertex->x;
|
||||
|
||||
if ($minY === false || $vertex->y < $minY)
|
||||
$minY = $vertex->y;
|
||||
|
||||
if ($minZ === false || $vertex->z < $minZ)
|
||||
$minZ = $vertex->z;
|
||||
|
||||
if ($maxX === false || $vertex->x > $maxX)
|
||||
$maxX = $vertex->x;
|
||||
|
||||
if ($maxY === false || $vertex->y > $maxY)
|
||||
$maxY = $vertex->y;
|
||||
|
||||
if ($maxZ === false || $vertex->z > $maxZ)
|
||||
$maxZ = $vertex->z;
|
||||
}
|
||||
$longestSide = max($maxX-$minX,$maxY-$minY,$maxZ-$minZ);
|
||||
$shortestSide = max(0.0005,min($maxX-$minX,$maxY-$minY,$maxZ-$minZ));
|
||||
|
||||
//printf("findVoxelsOfPolygon() shortestSide=$shortestSide\n");
|
||||
//printf("findVoxelsOfPolygon() minX=$minX, maxX=$maxX\n");
|
||||
//printf("findVoxelsOfPolygon() minY=$minY, maxY=$maxY\n");
|
||||
//printf("findVoxelsOfPolygon() minZ=$minZ, maxZ=$maxZ\n");
|
||||
|
||||
$voxels = array();
|
||||
// Could we???
|
||||
// use the shortest side as our voxel unit, and build up
|
||||
// the partial volume from those blocks....???
|
||||
$x = $minX;
|
||||
while ($x <= $maxX)
|
||||
{
|
||||
//printf("findVoxelsOfPolygon() X loop x=$x, y=$y, z=$z\n");
|
||||
$y = $minY;
|
||||
while($y <= $maxY)
|
||||
{
|
||||
//printf("findVoxelsOfPolygon() x=$x, y=$y, z=$z\n");
|
||||
$z = $minZ;
|
||||
while ($z <= $maxZ)
|
||||
{
|
||||
//printf("findVoxelsOfPolygon() x=$x, y=$y, z=$z, shortestSide=$shortestSide\n");
|
||||
$voxel = new Voxel();
|
||||
$voxel->x = (float)$x;
|
||||
$voxel->y = (float)$y;
|
||||
$voxel->z = (float)$z;
|
||||
$voxel->s = (float)$shortestSide;
|
||||
$voxels[]=$voxel;
|
||||
|
||||
$z+=$shortestSide;
|
||||
}
|
||||
$y+=$shortestSide;
|
||||
}
|
||||
$x+=$shortestSide;
|
||||
}
|
||||
return $voxels;
|
||||
}
|
||||
|
||||
// $scaleU is the scale in universal coordinates that the voxels will
|
||||
// be scaled to fill. we use 1 by default
|
||||
function rescaleVoxels($voxels,$scaleU=1)
|
||||
{
|
||||
echo "rescaleVoxels()...\n";
|
||||
$minX = false;
|
||||
$minY = false;
|
||||
$minZ = false;
|
||||
$maxX = false;
|
||||
$maxY = false;
|
||||
$maxZ = false;
|
||||
|
||||
$vc=0;
|
||||
|
||||
foreach ($voxels as $voxel)
|
||||
{
|
||||
$vc++;
|
||||
echoProgress("searching for bounds voxel:$vc");
|
||||
|
||||
//print_r($voxel);
|
||||
if ($minX === false || $voxel->x < $minX)
|
||||
{
|
||||
//echo "found new minX!\n";
|
||||
$minX = $voxel->x;
|
||||
}
|
||||
|
||||
if ($minY === false || $voxel->y < $minY)
|
||||
{
|
||||
//echo "found new miny!\n";
|
||||
$minY = $voxel->y;
|
||||
}
|
||||
|
||||
if ($minZ === false || $voxel->z < $minZ)
|
||||
{
|
||||
//echo "found new minZ!\n";
|
||||
$minZ = $voxel->z;
|
||||
}
|
||||
|
||||
if ($maxX === false || ($voxel->x+$voxel->s) > $maxX)
|
||||
{
|
||||
$maxX = ($voxel->x+$voxel->s);
|
||||
}
|
||||
|
||||
if ($maxY === false || ($voxel->y+$voxel->s) > $maxY)
|
||||
{
|
||||
//echo "found new maxY!\n";
|
||||
$maxY = ($voxel->y+$voxel->s);
|
||||
}
|
||||
|
||||
if ($maxZ === false || ($voxel->z+$voxel->s) > $maxZ)
|
||||
{
|
||||
//echo "found new maxZ!\n";
|
||||
$maxZ = ($voxel->z+$voxel->s);
|
||||
}
|
||||
}
|
||||
echoProgress("Done searching for bounds...\n",true);
|
||||
|
||||
echo "minX=$minX, minY=$minY, minZ=$minZ\n";
|
||||
echo "maxX=$maxX, maxY=$maxY, maxZ=$maxZ\n";
|
||||
$widthX = $maxX-$minX;
|
||||
$widthY = $maxY-$minY;
|
||||
$widthZ = $maxZ-$minZ;
|
||||
$widthU = max($widthX,$widthY,$widthZ);
|
||||
|
||||
echo "widthX=$widthX, widthY=$widthY, widthZ=$widthZ, widthU=$widthU\n";
|
||||
|
||||
$vc=0;
|
||||
foreach ($voxels as $voxel)
|
||||
{
|
||||
$vc++;
|
||||
echoProgress("Scaling voxel:$vc");
|
||||
|
||||
$voxel->x = $widthX ? (($voxel->x - $minX)/$widthU)*$scaleU : 0;
|
||||
$voxel->y = $widthY ? (($voxel->y - $minY)/$widthU)*$scaleU : 0;
|
||||
$voxel->z = $widthZ ? (($voxel->z - $minZ)/$widthU)*$scaleU : 0;
|
||||
$voxel->s = ($voxel->s/$widthU)*$scaleU;
|
||||
}
|
||||
echoProgress("Done Rescaling Voxels!\n",true);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Function: voxelPolygon()
|
||||
// Description: Given an array of universal points forming a polygon in 3D space, this
|
||||
// will return an array of voxels that fill the interior of this polygon
|
||||
// The voxels will match size s. The input values x,y,z range 0.0 <= v < 1.0
|
||||
// To Do: Currently, this will only work on convex polygons. If the polygon is
|
||||
// concave, we need to partition it into smaller convex polygons.
|
||||
// Complaints: Brad :)
|
||||
function polygonAsSurface($vertices,$s=false,$material='default') {
|
||||
|
||||
if ($s === false) {
|
||||
global $minVoxelSize;
|
||||
$s = $minVoxelSize;
|
||||
}
|
||||
|
||||
//echo "polygonAsSurface()\n";
|
||||
//echoProgress("polygonAsSurface()");
|
||||
|
||||
|
||||
//echo "polygonAsSurface() vertices=".print_r($vertices,1);
|
||||
|
||||
$voxels = array();
|
||||
// starting at v[1]
|
||||
// for each vertice v
|
||||
// for N over v[v+1] to v[v+2]
|
||||
// draw a line from v to v[v+1~v+2:N]
|
||||
// NOTE: this will result in several overlapping/duplicate voxels, so discard extras!!
|
||||
// ALSO NOTE: this will only work on convex polygons.
|
||||
// If the polygon is concave, we need to partition it into smaller convex polygons
|
||||
$count = count($vertices);
|
||||
$vO = $vertices[0];
|
||||
//echo "polygonAsSurface() count=$count\n";
|
||||
//echo "polygonAsSurface() vO=".print_r($vO,1);
|
||||
|
||||
for($n = 1; $n < $count; $n++)
|
||||
{
|
||||
$nP1 = ($n+1)%$count;
|
||||
//echo "polygonAsSurface() n=$n nP1=$nP1\n";
|
||||
|
||||
$vA = $vertices[$n];
|
||||
$vB = $vertices[$nP1];
|
||||
|
||||
//echo "polygonAsSurface() vA=".print_r($vA,1);
|
||||
//echo "polygonAsSurface() vB=".print_r($vB,1);
|
||||
|
||||
//echo "polygonAsSurface() ... voxelLine({$vA->x},{$vA->y},{$vA->z},{$vB->x},{$vB->y},{$vB->z},$s,$material)\n";
|
||||
|
||||
$lAB = voxelLine($vA->x,$vA->y,$vA->z,$vB->x,$vB->y,$vB->z,$s,$material);
|
||||
|
||||
//echo "**** polygonAsSurface() count(lAB)=".count($lAB)."\n";
|
||||
|
||||
$lc=0;
|
||||
foreach($lAB as $vAB)
|
||||
{
|
||||
//echo ">>> polygonAsSurface() vAB=".print_r($vAB,1);
|
||||
//echo ">>> polygonAsSurface() ... voxelLine({$vO->x},{$vO->y},{$vO->z},{$vAB->x},{$vAB->y},{$vAB->z},$s,$material)\n";
|
||||
|
||||
$lOAB = voxelLine($vO->x,$vO->y,$vO->z,$vAB->x,$vAB->y,$vAB->z,$s,$material);
|
||||
$lc++;
|
||||
//echoProgress("polygonAsSurface()... voxelLine() $lc");
|
||||
|
||||
//echo ">>> polygonAsSurface() count(lOAB)=".count($lOAB)."\n";
|
||||
$voxels = array_merge($voxels,$lOAB);
|
||||
}
|
||||
}
|
||||
//echo "polygonAsSurface() count(voxels)=".count($voxels)."\n";
|
||||
//echoProgress("polygonAsSurface() count(voxels)=".count($voxels));
|
||||
return $voxels;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Function: voxelLine()
|
||||
// Description: Given two universal points with location x1,y1,z1 and x2,y2,z2 this will
|
||||
// return an array of voxels that connect these two points with a straight
|
||||
// line. The voxels will match size s.
|
||||
// The input values x,y,z range 0.0 <= v < 1.0
|
||||
// Complaints: Brad :)
|
||||
function voxelLine($x1,$y1,$z1,$x2,$y2,$z2,$s,$material='default')
|
||||
{
|
||||
$voxels = array();
|
||||
$xV = $x2-$x1;
|
||||
$yV = $y2-$y1;
|
||||
$zV = $z2-$z1;
|
||||
$mV = max(abs($xV),abs($yV),abs($zV)); // max vector, which is the one we'll iterate accoss!
|
||||
$its = round($mV/$s);
|
||||
|
||||
/**
|
||||
echo "voxelLine() xV=$xV\n";
|
||||
echo "voxelLine() yV=$yV\n";
|
||||
echo "voxelLine() zV=$zV\n";
|
||||
echo "voxelLine() mV=$mV\n";
|
||||
echo "voxelLine() its=$its\n";
|
||||
**/
|
||||
|
||||
for ($i = 0; $i < $its; $i++)
|
||||
{
|
||||
//echo "voxelLine() loop i=$i\n";
|
||||
$x = $x1+(($xV/$its)*$i);
|
||||
$y = $y1+(($yV/$its)*$i);
|
||||
$z = $z1+(($zV/$its)*$i);
|
||||
$voxel = new Voxel();
|
||||
$voxel->x=$x;
|
||||
$voxel->y=$y;
|
||||
$voxel->z=$z;
|
||||
$voxel->s=$s;
|
||||
$voxel->material_name=$material;
|
||||
$voxels[] = $voxel;
|
||||
}
|
||||
return $voxels;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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 :)
|
||||
global $maxOctet,$minOctet;
|
||||
$maxOctet=0;
|
||||
$minOctet=100;
|
||||
function pointToVoxel($x,$y,$z,$s,$r=false,$g=false,$b=false)
|
||||
{
|
||||
$xTest = $yTest = $zTest = $sTest = 0.5;
|
||||
|
||||
// First determine the voxelSize that will properly encode a
|
||||
// voxel of size S.
|
||||
$voxelSizeInBits = 0;
|
||||
while ($sTest > $s) {
|
||||
$sTest /= 2.0;
|
||||
$voxelSizeInBits+=3;
|
||||
}
|
||||
|
||||
$voxelSizeInBytes = round(($voxelSizeInBits/8)+1);
|
||||
$voxelSizeInOctets = round($voxelSizeInBits/3);
|
||||
$voxelBufferSize = $voxelSizeInBytes+1+3; // 1 for size, 3 for color
|
||||
|
||||
if ($voxelSizeInOctets < 1)
|
||||
{
|
||||
echo "************ WTH!! voxelSizeInOctets=$voxelSizeInOctets s=$s sTest=$sTest ************\n";
|
||||
}
|
||||
|
||||
// for debugging, track our largest octet
|
||||
global $maxOctet,$minOctet;
|
||||
//echo "voxelSizeInOctets=$voxelSizeInOctets\n";
|
||||
$maxOctet = max($maxOctet,$voxelSizeInOctets);
|
||||
$minOctet = min($minOctet,$voxelSizeInOctets);
|
||||
if ($minOctet < 1)
|
||||
{
|
||||
echo "************ WTH!! minOctet=$minOctet\n";
|
||||
}
|
||||
//echo "maxOctet=$maxOctet\n";
|
||||
|
||||
// allocate our resulting buffer
|
||||
$voxelOut = array();
|
||||
|
||||
// first byte of buffer is always our size in octets
|
||||
$voxelOut[0]=$voxelSizeInOctets;
|
||||
|
||||
$sTest = 0.5; // reset sTest so we can do this again.
|
||||
|
||||
$byte = 0; // we will be adding coding bits here
|
||||
$bitInByteNDX = 0; // keep track of where we are in byte as we go
|
||||
$byteNDX = 1; // keep track of where we are in buffer of bytes as we go
|
||||
$octetsDone = 0;
|
||||
|
||||
// Now we actually fill out the voxel code
|
||||
while ($octetsDone < $voxelSizeInOctets) {
|
||||
|
||||
//echo "coding octet: octetsDone=$octetsDone voxelSizeInOctets=$voxelSizeInOctets\n";
|
||||
|
||||
if ($x > $xTest) {
|
||||
//<write 1 bit>
|
||||
$byte = ($byte << 1) | true;
|
||||
$xTest += $sTest/2.0;
|
||||
}
|
||||
else {
|
||||
//<write 0 bit;>
|
||||
$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)
|
||||
{
|
||||
//printf("xTest: got 8 bits, write to array byteNDX=$byteNDX byte=[%08b]\n",$byte);
|
||||
$voxelOut[$byteNDX]=$byte;
|
||||
$byteNDX += 1;
|
||||
$bitInByteNDX=0;
|
||||
$byte=0;
|
||||
}
|
||||
|
||||
if ($y > $yTest) {
|
||||
//<write 1 bit>
|
||||
$byte = ($byte << 1) | true;
|
||||
$yTest += $sTest/2.0;
|
||||
}
|
||||
else {
|
||||
//<write 0 bit;>
|
||||
$byte = ($byte << 1) | false;
|
||||
$yTest -= $sTest/2.0;
|
||||
}
|
||||
$bitInByteNDX++;
|
||||
//echo "coding octet: octetsDone=$octetsDone voxelSizeInOctets=$voxelSizeInOctets bitInByteNDX=$bitInByteNDX\n";
|
||||
|
||||
// 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)
|
||||
{
|
||||
//printf("yTest: got 8 bits, write to array byteNDX=$byteNDX byte=[%08b]\n",$byte);
|
||||
$voxelOut[$byteNDX]=$byte;
|
||||
$byteNDX += 1;
|
||||
$bitInByteNDX=0;
|
||||
$byte=0;
|
||||
}
|
||||
|
||||
if ($z > $zTest) {
|
||||
//<write 1 bit>
|
||||
$byte = ($byte << 1) | true;
|
||||
$zTest += $sTest/2.0;
|
||||
}
|
||||
else {
|
||||
//<write 0 bit;>
|
||||
$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)
|
||||
{
|
||||
//printf("zTest: got 8 bits, write to array byteNDX=$byteNDX byte=[%08b]\n",$byte);
|
||||
$voxelOut[$byteNDX]=$byte;
|
||||
$byteNDX += 1;
|
||||
$bitInByteNDX=0;
|
||||
$byte=0;
|
||||
}
|
||||
|
||||
$octetsDone++;
|
||||
$sTest /= 2.0;
|
||||
}
|
||||
|
||||
//printf("done with bits: byteNDX=$byteNDX bitInByteNDX=$bitInByteNDX\n");
|
||||
|
||||
// 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 < 8)
|
||||
{
|
||||
// Pad the last byte
|
||||
while ($bitInByteNDX <= 7)
|
||||
{
|
||||
$byte = ($byte << 1) | false;
|
||||
$bitInByteNDX++;
|
||||
}
|
||||
|
||||
// Copy it into our output buffer
|
||||
//printf("padding: array byteNDX=$byteNDX byte=[%08b]\n",$byte);
|
||||
$voxelOut[$byteNDX]=$byte;
|
||||
$byteNDX += 1;
|
||||
}
|
||||
// copy color data
|
||||
if ($r !== false)
|
||||
{
|
||||
//printf("color: array byteNDX=$byteNDX red=$r [%08b] green=$g [%08b] blue=$b [%08b]\n",$r,$g,$b);
|
||||
}
|
||||
$voxelOut[$byteNDX]=$r;
|
||||
$voxelOut[$byteNDX+1]=$g;
|
||||
$voxelOut[$byteNDX+2]=$b;
|
||||
|
||||
return $voxelOut;
|
||||
}
|
||||
|
||||
function dumpVoxelCode($voxelCode)
|
||||
{
|
||||
foreach($voxelCode as $byte)
|
||||
{
|
||||
printf("[%08b]",$byte);
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
class Material
|
||||
{
|
||||
public $name;
|
||||
public $red;
|
||||
public $green;
|
||||
public $blue;
|
||||
}
|
||||
|
||||
function randomColorValue($miniumum) {
|
||||
return $miniumum + (rand() % (255 - $miniumum));
|
||||
}
|
||||
|
||||
global $all_voxels;
|
||||
global $all_voxel_codes;
|
||||
|
||||
$all_voxels = array();
|
||||
function add_voxels($voxels)
|
||||
{
|
||||
global $all_voxels;
|
||||
// users can pass an array or a single voxel,
|
||||
// we're rather work on arrays, so conver a single
|
||||
// voxel into an array
|
||||
if (!is_array($voxels))
|
||||
{
|
||||
$voxels = array($voxels);
|
||||
}
|
||||
|
||||
//echo "add_voxels()...".print_r($voxels,1);
|
||||
|
||||
foreach ($voxels as $voxel)
|
||||
{
|
||||
// we ignore color here!
|
||||
$voxelCode = pointToVoxel($voxel->x,$voxel->y,$voxel->z,$voxel->s,false,false,false);
|
||||
$voxelCode = implode(',',$voxelCode);
|
||||
$all_voxels[$voxelCode]=$voxel;
|
||||
}
|
||||
// echo "all_voxels count=".count($all_voxels)."\n";
|
||||
}
|
||||
|
||||
|
||||
function convertObjFile($inputFileName,$outputFileName)
|
||||
{
|
||||
$inputFile = fopen($inputFileName, "rt"); // these are text files
|
||||
|
||||
$fCount=0;
|
||||
|
||||
$default_material = new Material();
|
||||
$default_material->name = 'default';
|
||||
$default_material->red = 240;
|
||||
$default_material->green = 240;
|
||||
$default_material->blue = 240;
|
||||
$current_material = $default_material;
|
||||
$materials = Array('default'=>$default_material);
|
||||
|
||||
$vertices = Array();
|
||||
$voxels = Array();
|
||||
|
||||
// Note: AFAIK we can't be certain that all the vertices are included
|
||||
// at the start of the file before faces. So we need:
|
||||
// 1) scan the entire file, and pull out all the vertices.
|
||||
// 2) Then we can resample that set of vertices to match our coordinate system.
|
||||
// 3) THEN we can process the faces to make voxels
|
||||
$filePasses = array('v','f');
|
||||
$commands = array('v'=>array('v','f','fill_from'),'f'=>array('f','usemtl','material'));
|
||||
foreach ($filePasses as $pass)
|
||||
{
|
||||
fseek($inputFile,0); // always rewind at the start of each pass
|
||||
// Before we do the face pass, resample the vertices
|
||||
if ($pass == 'f')
|
||||
{
|
||||
// now we actually need to rescale our voxels to fit in a 0-1 coordinate space
|
||||
|
||||
echo "vertices PRE-rescale:\n";
|
||||
//print_r($vertices);
|
||||
|
||||
rescaleVoxels($vertices);
|
||||
|
||||
echo "vertices POST-rescale:\n";
|
||||
//print_r($vertices);
|
||||
}
|
||||
|
||||
while (!feof($inputFile) )
|
||||
{
|
||||
$line_of_text = fgets($inputFile);
|
||||
$line_of_text = ereg_replace('[[:blank:]]+', ' ', $line_of_text);
|
||||
$line_of_text = trim(str_replace('\n', '', $line_of_text));
|
||||
|
||||
//echo "$line_of_text";
|
||||
$parts = explode(' ', $line_of_text);
|
||||
$cmd = $parts[0];
|
||||
|
||||
if (in_array($cmd,$commands[$pass]))
|
||||
{
|
||||
switch ($cmd)
|
||||
{
|
||||
// Note: fill from
|
||||
case 'fill_from':
|
||||
// a vertice
|
||||
$ = new Vertice();
|
||||
$v->x = (float)$parts[1];
|
||||
$v->y = (float)$parts[2];
|
||||
$v->z = (float)$parts[3];
|
||||
$vertices[] = $v;
|
||||
//echo "vertice: ".sizeof($vertices)."\n";
|
||||
//echo " vertice:".print_r($v,1)."\n";
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
// a vertice
|
||||
$v = new Vertice();
|
||||
$v->x = (float)$parts[1];
|
||||
$v->y = (float)$parts[2];
|
||||
$v->z = (float)$parts[3];
|
||||
$vertices[] = $v;
|
||||
|
||||
//echo "vertice: ".sizeof($vertices)."\n";
|
||||
|
||||
//echo " vertice:".print_r($v,1)."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'material':
|
||||
// material group...
|
||||
$material_name = trim($parts[1]);
|
||||
$red = $parts[2];
|
||||
$green = $parts[3];
|
||||
$blue = $parts[4];
|
||||
echoProgress("material definition: {$material_name} $red $green $blue\n");
|
||||
|
||||
if (!in_array($material,$materials))
|
||||
{
|
||||
$material = new Material();
|
||||
}
|
||||
else
|
||||
{
|
||||
$material = $materials[$material_name];
|
||||
}
|
||||
|
||||
$material->name = $material_name;
|
||||
$material->red = $red;
|
||||
$material->green = $green;
|
||||
$material->blue = $blue;
|
||||
$materials[$material_name]=$material;
|
||||
break;
|
||||
|
||||
case 'usemtl':
|
||||
// material group...
|
||||
$material = trim($parts[1]);
|
||||
echoProgress("usemtl: {$material}\n");
|
||||
|
||||
if (!isset($materials[$material]))
|
||||
{
|
||||
echoProgress("material: {$material} generating random colors...\n");
|
||||
$new_material = new Material();
|
||||
$new_material->name = $material;
|
||||
$new_material->red = randomColorValue(65);
|
||||
$new_material->green = randomColorValue(65);
|
||||
$new_material->blue = randomColorValue(65);
|
||||
$materials[$material]=$new_material;
|
||||
}
|
||||
$current_material = $materials[$material];
|
||||
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if ($pass=='v')
|
||||
{
|
||||
$ftCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// a face!
|
||||
$fCount++;
|
||||
$percentComplete = sprintf("%.2f%%",($fCount/$ftCount)*100);
|
||||
echoProgress("face processing: $fCount of $ftCount {$percentComplete}");
|
||||
|
||||
$verticeCount = sizeof($parts) - 1;
|
||||
$faceVertices = Array();
|
||||
for ($i = 1; $i <= $verticeCount; $i++)
|
||||
{
|
||||
$vdata = $parts[$i];
|
||||
$vdataParts = explode('/',$vdata);
|
||||
$vref = $vdataParts[0]-1; // indexes in files are 1 based
|
||||
$actualVertice = $vertices[$vref];
|
||||
$faceVertices[] = $actualVertice;
|
||||
}
|
||||
|
||||
//echo "face: $fCount material:{$current_material->name}\n";
|
||||
|
||||
//echo " face:".print_r($faceVertices,1)."\n";
|
||||
$voxelsOfPolygon = findVoxelsOfPolygon($faceVertices);
|
||||
|
||||
//echo "face: $fCount sizeof(voxelOfPolygon)=".sizeof($voxelsOfPolygon)."\n";
|
||||
|
||||
foreach ($voxelsOfPolygon as $voxel)
|
||||
{
|
||||
$voxel->material_name = $current_material->name;
|
||||
add_voxels($voxel);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// something we don't currently recognize or care about.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose($inputFile);
|
||||
|
||||
// Now that we've made our object. We need to fill it in...
|
||||
|
||||
|
||||
if ($outputFileName)
|
||||
{
|
||||
$outputFile = fopen($outputFileName,'wb');
|
||||
|
||||
$vCount = 0;
|
||||
global $all_voxels;
|
||||
$vtCount = sizeof($all_voxels);
|
||||
foreach ($all_voxels as $voxel)
|
||||
{
|
||||
$vCount++;
|
||||
|
||||
$percentComplete = sprintf("%.2f%%",($vCount/$vtCount)*100);
|
||||
echoProgress("writing file: $vCount of $vtCount {$percentComplete}");
|
||||
|
||||
|
||||
$material = $materials[$voxel->material_name];
|
||||
$r = $material->red;
|
||||
$g = $material->green;
|
||||
$b = $material->blue;
|
||||
//echo "v:$vCount: starting \n";
|
||||
$voxelCode = pointToVoxel($voxel->x,$voxel->y,$voxel->z,$voxel->s,$r,$g,$b);
|
||||
//print_r($voxel);
|
||||
//echo "v:$vCount: (".sizeof($voxelCode).") ";
|
||||
//dumpVoxelCode($voxelCode);
|
||||
|
||||
// if we were given an output filename, then write to it.
|
||||
if ($outputFile)
|
||||
{
|
||||
//echo "voxel code size:".sizeof($voxelCode)."\n";
|
||||
foreach($voxelCode as $byte)
|
||||
{
|
||||
$packedByte = pack('C',$byte);
|
||||
fwrite($outputFile,$packedByte,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose($outputFile);
|
||||
}
|
||||
|
||||
echo "\n*******\n";
|
||||
echo "Total Vertices: ".sizeof($vertices)."\n";
|
||||
echo "Total Voxels: ".sizeof($all_voxels)."\n";
|
||||
global $maxOctet,$minOctet;
|
||||
echo "Shortest Octet length: {$minOctet}\n";
|
||||
echo "Largest Octet length: {$maxOctet}\n";
|
||||
}
|
||||
|
||||
// -i inputFileName
|
||||
// -o outputFileName
|
||||
// -s minVoxelSize
|
||||
// -m method (block|wireframe|surface) assumes surface
|
||||
|
||||
$options = getopt("i:o:s:m:");
|
||||
|
||||
global $renderMode;
|
||||
//echo "line ".__LINE__." renderMode=$renderMode\n";
|
||||
// render options
|
||||
switch($options['m']) {
|
||||
case 'blocks':
|
||||
case 'wireframe':
|
||||
case 'surface':
|
||||
$renderMode = $options['m'];
|
||||
break;
|
||||
default:
|
||||
$renderMode = 'surface';
|
||||
}
|
||||
//echo "line ".__LINE__." renderMode=$renderMode\n";
|
||||
|
||||
// voxelsize
|
||||
global $minVoxelSize;
|
||||
//echo "line ".__LINE__." minVoxelSize=$minVoxelSize\n";
|
||||
if (!empty($options['s'])) {
|
||||
if ($options['s'] < 1.0 && $options['s'] > 0.0) {
|
||||
$minVoxelSize = $options['s'];
|
||||
}
|
||||
}
|
||||
//echo "line ".__LINE__." minVoxelSize=$minVoxelSize\n";
|
||||
|
||||
//print_r($options);
|
||||
|
||||
if (empty($options['i'])) {
|
||||
echo "USAGE: objtohio.php -i 'inputFileName' -o 'outputFileName' -m [blocks|wireframe|surface] -s [voxel size] \n";
|
||||
}
|
||||
else {
|
||||
echo "Convering OBJ file input:{$options['i']} output:{$options['o']} mode:$renderMode voxelSize:{$minVoxelSize}\n";
|
||||
convertObjFile($options['i'],$options['o']);
|
||||
|
||||
/*
|
||||
$filename = $options['i'];
|
||||
$file_handle = fopen($filename, "rt"); // these are text files
|
||||
|
||||
$line_of_text = fgets($file_handle);
|
||||
echo "read: {$line_of_text}";
|
||||
|
||||
fseek($file_handle,0); // always rewind at the start of each pass
|
||||
echo "seek to 0\n";
|
||||
|
||||
$line_of_text = fgets($file_handle);
|
||||
echo "read: {$line_of_text}";
|
||||
|
||||
fclose($file_handle);
|
||||
*/
|
||||
}
|
||||
?>
|
68
tools/sendvoxels.php
Normal file
68
tools/sendvoxels.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
function send_voxels($inputFileName,$server,$port,$command) {
|
||||
$socketHandle = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||||
$serverIP = $server;
|
||||
$serverSendPort = $port;
|
||||
|
||||
$inputFile = fopen($inputFileName, "rb"); // these are text files
|
||||
$voxNum=0;
|
||||
while (!feof($inputFile) ) {
|
||||
// [1:'I'][2:num]...
|
||||
$netData = pack("cv",ord($command),$voxNum);
|
||||
|
||||
$packetSize = 3; // to start
|
||||
while ($packetSize < 800) {
|
||||
$octets = fread($inputFile,1);
|
||||
$octets = (int)ord($octets);
|
||||
echo "read octets=$octets\n";
|
||||
|
||||
$size = ceil($octets*3/8)+3;
|
||||
$fileData = fread($inputFile,$size);
|
||||
$size++; // add length of octet
|
||||
|
||||
// ...[1:octets][n:xxxxx]
|
||||
$netData .= pack("c",$octets).$fileData;
|
||||
$packetSize+=$size;
|
||||
echo "sending adding octets=$octets size=$size to packet packetSize=$packetSize\n";
|
||||
}
|
||||
|
||||
echo "sending packet server=$serverIP port=$serverSendPort $voxNum size=$packetSize result=$result\n";
|
||||
$result = socket_sendto($socketHandle, $netData, $packetSize, 0, $serverIP, $serverSendPort);
|
||||
usleep(20000); // 1,000,000 per second
|
||||
$voxNum++;
|
||||
}
|
||||
socket_close($socketHandle);
|
||||
}
|
||||
|
||||
function testmode_send_voxels($server,$port) {
|
||||
echo "psych! test mode not implemented!\n";
|
||||
}
|
||||
|
||||
$options = getopt("i:s:p:c:",array('testmode'));
|
||||
|
||||
if (empty($options['i']) || empty($options['i'])) {
|
||||
echo "USAGE: sendvoxels.php -i 'inputFileName' -s [serverip] -p [port] -c [I|R] \n";
|
||||
} else {
|
||||
$filename = $options['i'];
|
||||
$server = $options['s'];
|
||||
$port = empty($options['p']) ? 40106 : $options['p'];
|
||||
$command = empty($options['c']) ? 'I' : $options['c'];
|
||||
switch($command) {
|
||||
case 'I':
|
||||
case 'R':
|
||||
//$command is good
|
||||
break;
|
||||
default:
|
||||
$command='I';// insert by default!
|
||||
}
|
||||
|
||||
if ($options['testmode']) {
|
||||
echo "TEST MODE Sending Voxels server:$server port:$port \n";
|
||||
testmode_send_voxels($server,$port);
|
||||
} else {
|
||||
echo "Sending Voxels file:$filename server:$server port:$port command:$command \n";
|
||||
send_voxels($filename,$server,$port,$command);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Reference in a new issue