PageRenderTime 46ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/tools/objtohio.php

https://github.com/BrianPrz/hifi
PHP | 860 lines | 541 code | 125 blank | 194 comment | 73 complexity | 63c3985e63d6897bd82e4f5074c60d08 MD5 | raw file
Possible License(s): Apache-2.0
  1. <?php
  2. // Parse/Read OBJ file
  3. //
  4. // USAGE: php objtohio.php -i 'inputFileName' -o 'outputFileName' -m [blocks|wireframe|surface] -s [voxel size]
  5. // NOTE: Depending on the size of the model, it might take a lot of memory, so you will likely need to include
  6. // the -d memory_limit=4096M option
  7. //
  8. global $lastmsg;
  9. $lastmsg='';
  10. function echoProgress($msg,$keep=false) {
  11. global $lastmsg;
  12. for($bs=0;$bs<strlen($lastmsg);$bs++) {
  13. echo chr(8);
  14. }
  15. for($bs=0;$bs<strlen($lastmsg);$bs++) {
  16. echo ' ';
  17. }
  18. for($bs=0;$bs<strlen($lastmsg);$bs++) {
  19. echo chr(8);
  20. }
  21. echo $msg;
  22. if (!$keep)
  23. $lastmsg=$msg;
  24. else
  25. $lastmsg='';
  26. }
  27. class Vertice
  28. {
  29. public $x;
  30. public $y;
  31. public $z;
  32. }
  33. class Voxel
  34. {
  35. public $material_name;
  36. public $x;
  37. public $y;
  38. public $z;
  39. public $s;
  40. }
  41. global $renderMode;
  42. $renderMode = 'surface';
  43. global $minVoxelSize;
  44. $minVoxelSize = 0.003; // default
  45. function findVoxelsOfPolygon($vertices,$s=false,$material='default') {
  46. //echo "findVoxelsOfPolygon() vertices=".print_r($vertices,1);
  47. global $renderMode;
  48. switch ($renderMode)
  49. {
  50. case 'blocks':
  51. return polygonAsBlocks($vertices,$s,$material);
  52. case 'wireframe':
  53. //echo "findVoxelsOfPolygon() calling... polygonAsWireFrame() vertices=".print_r($vertices,1);
  54. return polygonAsWireFrame($vertices,$s,$material);
  55. default:
  56. case 'surface':
  57. return polygonAsSurface($vertices,$s,$material);
  58. }
  59. }
  60. function polygonAsWireFrame($vertices,$s=false,$material='default')
  61. {
  62. if ($s === false) {
  63. global $minVoxelSize;
  64. $s = $minVoxelSize;
  65. }
  66. //echo "polygonAsWireFrame()\n";
  67. //echo "polygonAsWireFrame() vertices=".print_r($vertices,1);
  68. $maxNdx = count($vertices);
  69. //echo "***** polygonAsWireFrame() maxNdx=$maxNdx\n";
  70. $voxels = array();
  71. for ($ndx = 0; $ndx < $maxNdx; $ndx++)
  72. {
  73. $v1 = $vertices[$ndx];
  74. $v2 = ($ndx < ($maxNdx-1)) ? $vertices[$ndx+1] : $vertices[0];
  75. $lineVoxels = voxelLine($v1->x,$v1->y,$v1->z,$v2->x,$v2->y,$v2->z,$s,$material);
  76. //echo "polygonAsWireFrame() lineVoxels=".print_r($lineVoxels,1);
  77. $voxels = array_merge($voxels,$lineVoxels);
  78. }
  79. return $voxels;
  80. }
  81. //////////////////////////////////////////////////////////////////////////////////////////
  82. // Find the smallest Voxel of a random polygon.
  83. // find minimums of X,Y,Z
  84. // find maximums of X,Y,Z
  85. // find lengths of max-mins for X,Y,Z
  86. // Voxel Point = (minX, minY, minZ,longest side)
  87. function polygonAsBlocks($vertices,$s=false,$material='default')
  88. {
  89. if ($s === false) {
  90. global $minVoxelSize;
  91. $s = $minVoxelSize;
  92. }
  93. //echo "polygonAsBlocks()\n";
  94. $minX = false;
  95. $minY = false;
  96. $minZ = false;
  97. $maxX = false;
  98. $maxY = false;
  99. $maxZ = false;
  100. foreach ($vertices as $vertex)
  101. {
  102. if ($minX === false || $vertex->x < $minX)
  103. $minX = $vertex->x;
  104. if ($minY === false || $vertex->y < $minY)
  105. $minY = $vertex->y;
  106. if ($minZ === false || $vertex->z < $minZ)
  107. $minZ = $vertex->z;
  108. if ($maxX === false || $vertex->x > $maxX)
  109. $maxX = $vertex->x;
  110. if ($maxY === false || $vertex->y > $maxY)
  111. $maxY = $vertex->y;
  112. if ($maxZ === false || $vertex->z > $maxZ)
  113. $maxZ = $vertex->z;
  114. }
  115. $longestSide = max($maxX-$minX,$maxY-$minY,$maxZ-$minZ);
  116. $shortestSide = max(0.0005,min($maxX-$minX,$maxY-$minY,$maxZ-$minZ));
  117. //printf("findVoxelsOfPolygon() shortestSide=$shortestSide\n");
  118. //printf("findVoxelsOfPolygon() minX=$minX, maxX=$maxX\n");
  119. //printf("findVoxelsOfPolygon() minY=$minY, maxY=$maxY\n");
  120. //printf("findVoxelsOfPolygon() minZ=$minZ, maxZ=$maxZ\n");
  121. $voxels = array();
  122. // Could we???
  123. // use the shortest side as our voxel unit, and build up
  124. // the partial volume from those blocks....???
  125. $x = $minX;
  126. while ($x <= $maxX)
  127. {
  128. //printf("findVoxelsOfPolygon() X loop x=$x, y=$y, z=$z\n");
  129. $y = $minY;
  130. while($y <= $maxY)
  131. {
  132. //printf("findVoxelsOfPolygon() x=$x, y=$y, z=$z\n");
  133. $z = $minZ;
  134. while ($z <= $maxZ)
  135. {
  136. //printf("findVoxelsOfPolygon() x=$x, y=$y, z=$z, shortestSide=$shortestSide\n");
  137. $voxel = new Voxel();
  138. $voxel->x = (float)$x;
  139. $voxel->y = (float)$y;
  140. $voxel->z = (float)$z;
  141. $voxel->s = (float)$shortestSide;
  142. $voxels[]=$voxel;
  143. $z+=$shortestSide;
  144. }
  145. $y+=$shortestSide;
  146. }
  147. $x+=$shortestSide;
  148. }
  149. return $voxels;
  150. }
  151. // $scaleU is the scale in universal coordinates that the voxels will
  152. // be scaled to fill. we use 1 by default
  153. function rescaleVoxels($voxels,$scaleU=1)
  154. {
  155. echo "rescaleVoxels()...\n";
  156. $minX = false;
  157. $minY = false;
  158. $minZ = false;
  159. $maxX = false;
  160. $maxY = false;
  161. $maxZ = false;
  162. $vc=0;
  163. foreach ($voxels as $voxel)
  164. {
  165. $vc++;
  166. echoProgress("searching for bounds voxel:$vc");
  167. //print_r($voxel);
  168. if ($minX === false || $voxel->x < $minX)
  169. {
  170. //echo "found new minX!\n";
  171. $minX = $voxel->x;
  172. }
  173. if ($minY === false || $voxel->y < $minY)
  174. {
  175. //echo "found new miny!\n";
  176. $minY = $voxel->y;
  177. }
  178. if ($minZ === false || $voxel->z < $minZ)
  179. {
  180. //echo "found new minZ!\n";
  181. $minZ = $voxel->z;
  182. }
  183. if ($maxX === false || ($voxel->x+$voxel->s) > $maxX)
  184. {
  185. $maxX = ($voxel->x+$voxel->s);
  186. }
  187. if ($maxY === false || ($voxel->y+$voxel->s) > $maxY)
  188. {
  189. //echo "found new maxY!\n";
  190. $maxY = ($voxel->y+$voxel->s);
  191. }
  192. if ($maxZ === false || ($voxel->z+$voxel->s) > $maxZ)
  193. {
  194. //echo "found new maxZ!\n";
  195. $maxZ = ($voxel->z+$voxel->s);
  196. }
  197. }
  198. echoProgress("Done searching for bounds...\n",true);
  199. echo "minX=$minX, minY=$minY, minZ=$minZ\n";
  200. echo "maxX=$maxX, maxY=$maxY, maxZ=$maxZ\n";
  201. $widthX = $maxX-$minX;
  202. $widthY = $maxY-$minY;
  203. $widthZ = $maxZ-$minZ;
  204. $widthU = max($widthX,$widthY,$widthZ);
  205. echo "widthX=$widthX, widthY=$widthY, widthZ=$widthZ, widthU=$widthU\n";
  206. $vc=0;
  207. foreach ($voxels as $voxel)
  208. {
  209. $vc++;
  210. echoProgress("Scaling voxel:$vc");
  211. $voxel->x = $widthX ? (($voxel->x - $minX)/$widthU)*$scaleU : 0;
  212. $voxel->y = $widthY ? (($voxel->y - $minY)/$widthU)*$scaleU : 0;
  213. $voxel->z = $widthZ ? (($voxel->z - $minZ)/$widthU)*$scaleU : 0;
  214. $voxel->s = ($voxel->s/$widthU)*$scaleU;
  215. }
  216. echoProgress("Done Rescaling Voxels!\n",true);
  217. }
  218. //////////////////////////////////////////////////////////////////////////////////////////
  219. // Function: voxelPolygon()
  220. // Description: Given an array of universal points forming a polygon in 3D space, this
  221. // will return an array of voxels that fill the interior of this polygon
  222. // The voxels will match size s. The input values x,y,z range 0.0 <= v < 1.0
  223. // To Do: Currently, this will only work on convex polygons. If the polygon is
  224. // concave, we need to partition it into smaller convex polygons.
  225. // Complaints: Brad :)
  226. function polygonAsSurface($vertices,$s=false,$material='default') {
  227. if ($s === false) {
  228. global $minVoxelSize;
  229. $s = $minVoxelSize;
  230. }
  231. //echo "polygonAsSurface()\n";
  232. //echoProgress("polygonAsSurface()");
  233. //echo "polygonAsSurface() vertices=".print_r($vertices,1);
  234. $voxels = array();
  235. // starting at v[1]
  236. // for each vertice v
  237. // for N over v[v+1] to v[v+2]
  238. // draw a line from v to v[v+1~v+2:N]
  239. // NOTE: this will result in several overlapping/duplicate voxels, so discard extras!!
  240. // ALSO NOTE: this will only work on convex polygons.
  241. // If the polygon is concave, we need to partition it into smaller convex polygons
  242. $count = count($vertices);
  243. $vO = $vertices[0];
  244. //echo "polygonAsSurface() count=$count\n";
  245. //echo "polygonAsSurface() vO=".print_r($vO,1);
  246. for($n = 1; $n < $count; $n++)
  247. {
  248. $nP1 = ($n+1)%$count;
  249. //echo "polygonAsSurface() n=$n nP1=$nP1\n";
  250. $vA = $vertices[$n];
  251. $vB = $vertices[$nP1];
  252. //echo "polygonAsSurface() vA=".print_r($vA,1);
  253. //echo "polygonAsSurface() vB=".print_r($vB,1);
  254. //echo "polygonAsSurface() ... voxelLine({$vA->x},{$vA->y},{$vA->z},{$vB->x},{$vB->y},{$vB->z},$s,$material)\n";
  255. $lAB = voxelLine($vA->x,$vA->y,$vA->z,$vB->x,$vB->y,$vB->z,$s,$material);
  256. //echo "**** polygonAsSurface() count(lAB)=".count($lAB)."\n";
  257. $lc=0;
  258. foreach($lAB as $vAB)
  259. {
  260. //echo ">>> polygonAsSurface() vAB=".print_r($vAB,1);
  261. //echo ">>> polygonAsSurface() ... voxelLine({$vO->x},{$vO->y},{$vO->z},{$vAB->x},{$vAB->y},{$vAB->z},$s,$material)\n";
  262. $lOAB = voxelLine($vO->x,$vO->y,$vO->z,$vAB->x,$vAB->y,$vAB->z,$s,$material);
  263. $lc++;
  264. //echoProgress("polygonAsSurface()... voxelLine() $lc");
  265. //echo ">>> polygonAsSurface() count(lOAB)=".count($lOAB)."\n";
  266. $voxels = array_merge($voxels,$lOAB);
  267. }
  268. }
  269. //echo "polygonAsSurface() count(voxels)=".count($voxels)."\n";
  270. //echoProgress("polygonAsSurface() count(voxels)=".count($voxels));
  271. return $voxels;
  272. }
  273. //////////////////////////////////////////////////////////////////////////////////////////
  274. // Function: voxelLine()
  275. // Description: Given two universal points with location x1,y1,z1 and x2,y2,z2 this will
  276. // return an array of voxels that connect these two points with a straight
  277. // line. The voxels will match size s.
  278. // The input values x,y,z range 0.0 <= v < 1.0
  279. // Complaints: Brad :)
  280. function voxelLine($x1,$y1,$z1,$x2,$y2,$z2,$s,$material='default')
  281. {
  282. $voxels = array();
  283. $xV = $x2-$x1;
  284. $yV = $y2-$y1;
  285. $zV = $z2-$z1;
  286. $mV = max(abs($xV),abs($yV),abs($zV)); // max vector, which is the one we'll iterate accoss!
  287. $its = round($mV/$s);
  288. /**
  289. echo "voxelLine() xV=$xV\n";
  290. echo "voxelLine() yV=$yV\n";
  291. echo "voxelLine() zV=$zV\n";
  292. echo "voxelLine() mV=$mV\n";
  293. echo "voxelLine() its=$its\n";
  294. **/
  295. for ($i = 0; $i < $its; $i++)
  296. {
  297. //echo "voxelLine() loop i=$i\n";
  298. $x = $x1+(($xV/$its)*$i);
  299. $y = $y1+(($yV/$its)*$i);
  300. $z = $z1+(($zV/$its)*$i);
  301. $voxel = new Voxel();
  302. $voxel->x=$x;
  303. $voxel->y=$y;
  304. $voxel->z=$z;
  305. $voxel->s=$s;
  306. $voxel->material_name=$material;
  307. $voxels[] = $voxel;
  308. }
  309. return $voxels;
  310. }
  311. //////////////////////////////////////////////////////////////////////////////////////////
  312. // Function: pointToVoxel()
  313. // Description: Given a universal point with location x,y,z this will return the voxel
  314. // voxel code corresponding to the closest voxel which encloses a cube with
  315. // lower corners at x,y,z, having side of length S.
  316. // The input values x,y,z range 0.0 <= v < 1.0
  317. // TO DO: This code is not very DRY. It should be cleaned up to be DRYer.
  318. // IMPORTANT: The voxel is returned to you a buffer which you MUST delete when you are
  319. // done with it.
  320. // Usage:
  321. // unsigned char* voxelData = pointToVoxel(x,y,z,s,red,green,blue);
  322. // tree->readCodeColorBufferToTree(voxelData);
  323. // delete voxelData;
  324. //
  325. // Complaints: Brad :)
  326. global $maxOctet,$minOctet;
  327. $maxOctet=0;
  328. $minOctet=100;
  329. function pointToVoxel($x,$y,$z,$s,$r=false,$g=false,$b=false)
  330. {
  331. $xTest = $yTest = $zTest = $sTest = 0.5;
  332. // First determine the voxelSize that will properly encode a
  333. // voxel of size S.
  334. $voxelSizeInBits = 0;
  335. while ($sTest > $s) {
  336. $sTest /= 2.0;
  337. $voxelSizeInBits+=3;
  338. }
  339. $voxelSizeInBytes = round(($voxelSizeInBits/8)+1);
  340. $voxelSizeInOctets = round($voxelSizeInBits/3);
  341. $voxelBufferSize = $voxelSizeInBytes+1+3; // 1 for size, 3 for color
  342. if ($voxelSizeInOctets < 1)
  343. {
  344. echo "************ WTH!! voxelSizeInOctets=$voxelSizeInOctets s=$s sTest=$sTest ************\n";
  345. }
  346. // for debugging, track our largest octet
  347. global $maxOctet,$minOctet;
  348. //echo "voxelSizeInOctets=$voxelSizeInOctets\n";
  349. $maxOctet = max($maxOctet,$voxelSizeInOctets);
  350. $minOctet = min($minOctet,$voxelSizeInOctets);
  351. if ($minOctet < 1)
  352. {
  353. echo "************ WTH!! minOctet=$minOctet\n";
  354. }
  355. //echo "maxOctet=$maxOctet\n";
  356. // allocate our resulting buffer
  357. $voxelOut = array();
  358. // first byte of buffer is always our size in octets
  359. $voxelOut[0]=$voxelSizeInOctets;
  360. $sTest = 0.5; // reset sTest so we can do this again.
  361. $byte = 0; // we will be adding coding bits here
  362. $bitInByteNDX = 0; // keep track of where we are in byte as we go
  363. $byteNDX = 1; // keep track of where we are in buffer of bytes as we go
  364. $octetsDone = 0;
  365. // Now we actually fill out the voxel code
  366. while ($octetsDone < $voxelSizeInOctets) {
  367. //echo "coding octet: octetsDone=$octetsDone voxelSizeInOctets=$voxelSizeInOctets\n";
  368. if ($x > $xTest) {
  369. //<write 1 bit>
  370. $byte = ($byte << 1) | true;
  371. $xTest += $sTest/2.0;
  372. }
  373. else {
  374. //<write 0 bit;>
  375. $byte = ($byte << 1) | false;
  376. $xTest -= $sTest/2.0;
  377. }
  378. $bitInByteNDX++;
  379. // If we've reached the last bit of the byte, then we want to copy this byte
  380. // into our buffer. And get ready to start on a new byte
  381. if ($bitInByteNDX > 7)
  382. {
  383. //printf("xTest: got 8 bits, write to array byteNDX=$byteNDX byte=[%08b]\n",$byte);
  384. $voxelOut[$byteNDX]=$byte;
  385. $byteNDX += 1;
  386. $bitInByteNDX=0;
  387. $byte=0;
  388. }
  389. if ($y > $yTest) {
  390. //<write 1 bit>
  391. $byte = ($byte << 1) | true;
  392. $yTest += $sTest/2.0;
  393. }
  394. else {
  395. //<write 0 bit;>
  396. $byte = ($byte << 1) | false;
  397. $yTest -= $sTest/2.0;
  398. }
  399. $bitInByteNDX++;
  400. //echo "coding octet: octetsDone=$octetsDone voxelSizeInOctets=$voxelSizeInOctets bitInByteNDX=$bitInByteNDX\n";
  401. // If we've reached the last bit of the byte, then we want to copy this byte
  402. // into our buffer. And get ready to start on a new byte
  403. if ($bitInByteNDX > 7)
  404. {
  405. //printf("yTest: got 8 bits, write to array byteNDX=$byteNDX byte=[%08b]\n",$byte);
  406. $voxelOut[$byteNDX]=$byte;
  407. $byteNDX += 1;
  408. $bitInByteNDX=0;
  409. $byte=0;
  410. }
  411. if ($z > $zTest) {
  412. //<write 1 bit>
  413. $byte = ($byte << 1) | true;
  414. $zTest += $sTest/2.0;
  415. }
  416. else {
  417. //<write 0 bit;>
  418. $byte = ($byte << 1) | false;
  419. $zTest -= $sTest/2.0;
  420. }
  421. $bitInByteNDX++;
  422. // If we've reached the last bit of the byte, then we want to copy this byte
  423. // into our buffer. And get ready to start on a new byte
  424. if ($bitInByteNDX > 7)
  425. {
  426. //printf("zTest: got 8 bits, write to array byteNDX=$byteNDX byte=[%08b]\n",$byte);
  427. $voxelOut[$byteNDX]=$byte;
  428. $byteNDX += 1;
  429. $bitInByteNDX=0;
  430. $byte=0;
  431. }
  432. $octetsDone++;
  433. $sTest /= 2.0;
  434. }
  435. //printf("done with bits: byteNDX=$byteNDX bitInByteNDX=$bitInByteNDX\n");
  436. // If we've got here, and we didn't fill the last byte, we need to zero pad this
  437. // byte before we copy it into our buffer.
  438. if ($bitInByteNDX > 0 && $bitInByteNDX < 8)
  439. {
  440. // Pad the last byte
  441. while ($bitInByteNDX <= 7)
  442. {
  443. $byte = ($byte << 1) | false;
  444. $bitInByteNDX++;
  445. }
  446. // Copy it into our output buffer
  447. //printf("padding: array byteNDX=$byteNDX byte=[%08b]\n",$byte);
  448. $voxelOut[$byteNDX]=$byte;
  449. $byteNDX += 1;
  450. }
  451. // copy color data
  452. if ($r !== false)
  453. {
  454. //printf("color: array byteNDX=$byteNDX red=$r [%08b] green=$g [%08b] blue=$b [%08b]\n",$r,$g,$b);
  455. }
  456. $voxelOut[$byteNDX]=$r;
  457. $voxelOut[$byteNDX+1]=$g;
  458. $voxelOut[$byteNDX+2]=$b;
  459. return $voxelOut;
  460. }
  461. function dumpVoxelCode($voxelCode)
  462. {
  463. foreach($voxelCode as $byte)
  464. {
  465. printf("[%08b]",$byte);
  466. }
  467. echo "\n";
  468. }
  469. class Material
  470. {
  471. public $name;
  472. public $red;
  473. public $green;
  474. public $blue;
  475. }
  476. function randomColorValue($miniumum) {
  477. return $miniumum + (rand() % (255 - $miniumum));
  478. }
  479. global $all_voxels;
  480. global $all_voxel_codes;
  481. $all_voxels = array();
  482. function add_voxels($voxels)
  483. {
  484. global $all_voxels;
  485. // users can pass an array or a single voxel,
  486. // we're rather work on arrays, so conver a single
  487. // voxel into an array
  488. if (!is_array($voxels))
  489. {
  490. $voxels = array($voxels);
  491. }
  492. //echo "add_voxels()...".print_r($voxels,1);
  493. foreach ($voxels as $voxel)
  494. {
  495. // we ignore color here!
  496. $voxelCode = pointToVoxel($voxel->x,$voxel->y,$voxel->z,$voxel->s,false,false,false);
  497. $voxelCode = implode(',',$voxelCode);
  498. $all_voxels[$voxelCode]=$voxel;
  499. }
  500. // echo "all_voxels count=".count($all_voxels)."\n";
  501. }
  502. function convertObjFile($inputFileName,$outputFileName)
  503. {
  504. $inputFile = fopen($inputFileName, "rt"); // these are text files
  505. $fCount=0;
  506. $default_material = new Material();
  507. $default_material->name = 'default';
  508. $default_material->red = 240;
  509. $default_material->green = 240;
  510. $default_material->blue = 240;
  511. $current_material = $default_material;
  512. $materials = Array('default'=>$default_material);
  513. $vertices = Array();
  514. $voxels = Array();
  515. // Note: AFAIK we can't be certain that all the vertices are included
  516. // at the start of the file before faces. So we need:
  517. // 1) scan the entire file, and pull out all the vertices.
  518. // 2) Then we can resample that set of vertices to match our coordinate system.
  519. // 3) THEN we can process the faces to make voxels
  520. $filePasses = array('v','f');
  521. $commands = array('v'=>array('v','f','fill_from'),'f'=>array('f','usemtl','material'));
  522. foreach ($filePasses as $pass)
  523. {
  524. fseek($inputFile,0); // always rewind at the start of each pass
  525. // Before we do the face pass, resample the vertices
  526. if ($pass == 'f')
  527. {
  528. // now we actually need to rescale our voxels to fit in a 0-1 coordinate space
  529. echo "vertices PRE-rescale:\n";
  530. //print_r($vertices);
  531. rescaleVoxels($vertices);
  532. echo "vertices POST-rescale:\n";
  533. //print_r($vertices);
  534. }
  535. while (!feof($inputFile) )
  536. {
  537. $line_of_text = fgets($inputFile);
  538. $line_of_text = ereg_replace('[[:blank:]]+', ' ', $line_of_text);
  539. $line_of_text = trim(str_replace('\n', '', $line_of_text));
  540. //echo "$line_of_text";
  541. $parts = explode(' ', $line_of_text);
  542. $cmd = $parts[0];
  543. if (in_array($cmd,$commands[$pass]))
  544. {
  545. switch ($cmd)
  546. {
  547. // Note: fill from
  548. case 'fill_from':
  549. // a vertice
  550. $v = new Vertice();
  551. $v->x = (float)$parts[1];
  552. $v->y = (float)$parts[2];
  553. $v->z = (float)$parts[3];
  554. $vertices[] = $v;
  555. //echo "vertice: ".sizeof($vertices)."\n";
  556. //echo " vertice:".print_r($v,1)."\n";
  557. break;
  558. case 'v':
  559. // a vertice
  560. $v = new Vertice();
  561. $v->x = (float)$parts[1];
  562. $v->y = (float)$parts[2];
  563. $v->z = (float)$parts[3];
  564. $vertices[] = $v;
  565. //echo "vertice: ".sizeof($vertices)."\n";
  566. //echo " vertice:".print_r($v,1)."\n";
  567. break;
  568. case 'material':
  569. // material group...
  570. $material_name = trim($parts[1]);
  571. $red = $parts[2];
  572. $green = $parts[3];
  573. $blue = $parts[4];
  574. echoProgress("material definition: {$material_name} $red $green $blue\n");
  575. if (!in_array($material,$materials))
  576. {
  577. $material = new Material();
  578. }
  579. else
  580. {
  581. $material = $materials[$material_name];
  582. }
  583. $material->name = $material_name;
  584. $material->red = $red;
  585. $material->green = $green;
  586. $material->blue = $blue;
  587. $materials[$material_name]=$material;
  588. break;
  589. case 'usemtl':
  590. // material group...
  591. $material = trim($parts[1]);
  592. echoProgress("usemtl: {$material}\n");
  593. if (!isset($materials[$material]))
  594. {
  595. echoProgress("material: {$material} generating random colors...\n");
  596. $new_material = new Material();
  597. $new_material->name = $material;
  598. $new_material->red = randomColorValue(65);
  599. $new_material->green = randomColorValue(65);
  600. $new_material->blue = randomColorValue(65);
  601. $materials[$material]=$new_material;
  602. }
  603. $current_material = $materials[$material];
  604. break;
  605. case 'f':
  606. if ($pass=='v')
  607. {
  608. $ftCount++;
  609. }
  610. else
  611. {
  612. // a face!
  613. $fCount++;
  614. $percentComplete = sprintf("%.2f%%",($fCount/$ftCount)*100);
  615. echoProgress("face processing: $fCount of $ftCount {$percentComplete}");
  616. $verticeCount = sizeof($parts) - 1;
  617. $faceVertices = Array();
  618. for ($i = 1; $i <= $verticeCount; $i++)
  619. {
  620. $vdata = $parts[$i];
  621. $vdataParts = explode('/',$vdata);
  622. $vref = $vdataParts[0]-1; // indexes in files are 1 based
  623. $actualVertice = $vertices[$vref];
  624. $faceVertices[] = $actualVertice;
  625. }
  626. //echo "face: $fCount material:{$current_material->name}\n";
  627. //echo " face:".print_r($faceVertices,1)."\n";
  628. $voxelsOfPolygon = findVoxelsOfPolygon($faceVertices);
  629. //echo "face: $fCount sizeof(voxelOfPolygon)=".sizeof($voxelsOfPolygon)."\n";
  630. foreach ($voxelsOfPolygon as $voxel)
  631. {
  632. $voxel->material_name = $current_material->name;
  633. add_voxels($voxel);
  634. }
  635. }
  636. break;
  637. default:
  638. // something we don't currently recognize or care about.
  639. }
  640. }
  641. }
  642. }
  643. fclose($inputFile);
  644. // Now that we've made our object. We need to fill it in...
  645. if ($outputFileName)
  646. {
  647. $outputFile = fopen($outputFileName,'wb');
  648. $vCount = 0;
  649. global $all_voxels;
  650. $vtCount = sizeof($all_voxels);
  651. foreach ($all_voxels as $voxel)
  652. {
  653. $vCount++;
  654. $percentComplete = sprintf("%.2f%%",($vCount/$vtCount)*100);
  655. echoProgress("writing file: $vCount of $vtCount {$percentComplete}");
  656. $material = $materials[$voxel->material_name];
  657. $r = $material->red;
  658. $g = $material->green;
  659. $b = $material->blue;
  660. //echo "v:$vCount: starting \n";
  661. $voxelCode = pointToVoxel($voxel->x,$voxel->y,$voxel->z,$voxel->s,$r,$g,$b);
  662. //print_r($voxel);
  663. //echo "v:$vCount: (".sizeof($voxelCode).") ";
  664. //dumpVoxelCode($voxelCode);
  665. // if we were given an output filename, then write to it.
  666. if ($outputFile)
  667. {
  668. //echo "voxel code size:".sizeof($voxelCode)."\n";
  669. foreach($voxelCode as $byte)
  670. {
  671. $packedByte = pack('C',$byte);
  672. fwrite($outputFile,$packedByte,1);
  673. }
  674. }
  675. }
  676. fclose($outputFile);
  677. }
  678. echo "\n*******\n";
  679. echo "Total Vertices: ".sizeof($vertices)."\n";
  680. echo "Total Voxels: ".sizeof($all_voxels)."\n";
  681. global $maxOctet,$minOctet;
  682. echo "Shortest Octet length: {$minOctet}\n";
  683. echo "Largest Octet length: {$maxOctet}\n";
  684. }
  685. // -i inputFileName
  686. // -o outputFileName
  687. // -s minVoxelSize
  688. // -m method (block|wireframe|surface) assumes surface
  689. $options = getopt("i:o:s:m:");
  690. global $renderMode;
  691. //echo "line ".__LINE__." renderMode=$renderMode\n";
  692. // render options
  693. switch($options['m']) {
  694. case 'blocks':
  695. case 'wireframe':
  696. case 'surface':
  697. $renderMode = $options['m'];
  698. break;
  699. default:
  700. $renderMode = 'surface';
  701. }
  702. //echo "line ".__LINE__." renderMode=$renderMode\n";
  703. // voxelsize
  704. global $minVoxelSize;
  705. //echo "line ".__LINE__." minVoxelSize=$minVoxelSize\n";
  706. if (!empty($options['s'])) {
  707. if ($options['s'] < 1.0 && $options['s'] > 0.0) {
  708. $minVoxelSize = $options['s'];
  709. }
  710. }
  711. //echo "line ".__LINE__." minVoxelSize=$minVoxelSize\n";
  712. //print_r($options);
  713. if (empty($options['i'])) {
  714. echo "USAGE: objtohio.php -i 'inputFileName' -o 'outputFileName' -m [blocks|wireframe|surface] -s [voxel size] \n";
  715. }
  716. else {
  717. echo "Convering OBJ file input:{$options['i']} output:{$options['o']} mode:$renderMode voxelSize:{$minVoxelSize}\n";
  718. convertObjFile($options['i'],$options['o']);
  719. /*
  720. $filename = $options['i'];
  721. $file_handle = fopen($filename, "rt"); // these are text files
  722. $line_of_text = fgets($file_handle);
  723. echo "read: {$line_of_text}";
  724. fseek($file_handle,0); // always rewind at the start of each pass
  725. echo "seek to 0\n";
  726. $line_of_text = fgets($file_handle);
  727. echo "read: {$line_of_text}";
  728. fclose($file_handle);
  729. */
  730. }
  731. ?>