PHP 3D Renderer


/ Published in: PHP
Save to your folder(s)



Copy this code and paste it in your HTML
  1. public function render() {
  2.  
  3. // find which map block the camera is in
  4.  
  5. $cameraBlockX = $this->camX >> 6;
  6. $cameraBlockY = $this->camY >> 6;
  7.  
  8. $offset = 0;
  9.  
  10. // clamp angle for lookup tables
  11.  
  12. if ($this->camAngle < 0) $this->camAngle += pi() * 2;
  13. if ($this->camAngle > pi() * 2) $this->camAngle -= pi() * 2;
  14.  
  15. $angle = $this->camAngle + $this->camFov * 0.5;
  16. if ($angle > pi() * 2) $angle -= pi() * 2;
  17.  
  18. $width = $this->width;
  19.  
  20. $this->camPCentre = $this->height / 2 - $this->camRoll;
  21.  
  22. $ang = ($this->camAngle * $this->divisor) | 0;
  23.  
  24. $invertZ = 64 - $this->camZ;
  25.  
  26. // loop through each vertical strip
  27.  
  28. while ($width-- > 0) {
  29.  
  30. // set nearest face to practical infinity
  31.  
  32. $nearestFace = 4294967296;
  33.  
  34. $angleLookup = ($angle * $this->divisor);
  35.  
  36. // find oriented face aligned to X axis of map
  37.  
  38. $x = $cameraBlockX;
  39. $y = $cameraBlockY;
  40.  
  41. if ($this->sin[$angleLookup] < 0) {
  42.  
  43. while ($y > -1 && $x > -1 && $x < $this->mapWidth) {
  44. $absY = $y << 6;
  45. $absX = $this->camX + ($absY - $this->camY) / $this->tan[$angleLookup];
  46. $x = $absX >> 6;
  47.  
  48. // check if there is a block here
  49.  
  50. if ($this->map[$x][--$y]) {
  51. $nearestFace = pow($absX - $this->camX, 2) + pow($absY - $this->camY, 2);
  52. $offset = $absX & 63;
  53. break;
  54. }
  55. }
  56.  
  57. } else {
  58.  
  59. while ($y++ < $this->mapHeight && $x > -1 && $x < $this->mapWidth) {
  60. $absY = $y << 6;
  61. $absX = $this->camX + ($absY - $this->camY) / $this->tan[$angleLookup];
  62. $x = $absX >> 6;
  63.  
  64. // check if there is a block here
  65.  
  66. if ($this->map[$x][$y]) {
  67. $nearestFace = pow($absX - $this->camX, 2) + pow($absY - $this->camY, 2);
  68. $offset = 64 - $absX & 63;
  69. break;
  70. }
  71. }
  72.  
  73. }
  74.  
  75. // find closest face oriented to Y axis of map
  76.  
  77. $x = $cameraBlockX;
  78. $y = $cameraBlockY;
  79.  
  80. if ($this->cos[$angleLookup] < 0) {
  81.  
  82. while ($x > -1 && $y > -1 && $y < $this->mapHeight) {
  83. $absX = $x << 6;
  84. $absY = $this->camY + ($absX - $this->camX) * $this->tan[$angleLookup];
  85. $y = $absY >> 6;
  86.  
  87. // check if there is a block here
  88.  
  89. if ($this->map[--$x][$y]) {
  90. $distance = pow($absX - $this->camX, 2) + pow($absY - $this->camY, 2);
  91.  
  92. if ($distance < $nearestFace) {
  93. $nearestFace = $distance;
  94. $offset = 64 - $absY & 63;
  95. }
  96. break;
  97. }
  98. }
  99.  
  100. } else {
  101.  
  102. while ($x++ < $this->mapWidth && $y > -1 && $y < $this->mapHeight) {
  103. $absX = $x << 6;
  104. $absY = $this->camY + ($absX - $this->camX) * $this->tan[$angleLookup];
  105. $y = $absY >> 6;
  106.  
  107. // check if there is a block here
  108.  
  109. if ($this->map[$x][$y]) {
  110. $distance = pow($absX - $this->camX, 2) + pow($absY - $this->camY, 2);
  111.  
  112. if ($distance < $nearestFace) {
  113. $nearestFace = $distance;
  114. $offset = $absY & 63;
  115. }
  116. break;
  117. }
  118. }
  119.  
  120. }
  121.  
  122. // check whether the current strip is looking left or right of centre angle
  123.  
  124. if ($angleLookup < $ang) {
  125. $distort = $this->camDistance / $this->cos[7200 + $angleLookup - $ang];
  126. } else {
  127. $distort = $this->camDistance / $this->cos[$angleLookup - $ang];
  128. }
  129.  
  130. $wallHeight = $distort / sqrt($nearestFace);
  131.  
  132. $distanceFloor = $invertZ * $distort;
  133. $distanceCeiling = $this->camZ * $distort;
  134.  
  135. $floorLevel = (int) ($this->camPCentre + $wallHeight * $this->camZ + 0.5);
  136. $wallLevel = (int) ($this->camPCentre - $wallHeight * $invertZ);
  137.  
  138. $height = $this->height;
  139.  
  140. // draw floor
  141.  
  142. while (--$height > $floorLevel && $height >= 0) {
  143. $distance = $distanceFloor / ($height - $this->camPCentre);
  144. imagesetpixel($this->canvas, $width, $height, imagecolorat($this->texFloor, ($this->camX + $this->cos[$angleLookup] * $distance) & 63, ($this->camY + $this->sin[$angleLookup] * $distance) & 63));
  145. }
  146.  
  147. // draw wall
  148.  
  149. while (--$height > $wallLevel && $height >= 0) {
  150. imagesetpixel($this->canvas, $width, $height, imagecolorat($this->texWall, $offset, ($height - $wallLevel) / $wallHeight));
  151. }
  152.  
  153. // draw ceiling
  154.  
  155. while (--$height > -1) {
  156. $distance = $distanceCeiling / ($this->camPCentre - $height);
  157. imagesetpixel($this->canvas, $width, $height, imagecolorat($this->texCeil, ($this->camX + $this->cos[$angleLookup] * $distance) & 63, ($this->camY + $this->sin[$angleLookup] * $distance) & 63));
  158. }
  159.  
  160. $angle -= $this->camPerRayAngle;
  161.  
  162. if ($angle < 0) $angle += pi() * 2;
  163. }
  164. }

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.