# 3D Engine

Page 1 of 1

## 7 Replies - 1757 Views - Last Post: 26 January 2011 - 08:33 PM

### #1 grimpirate

• Pirate King

Reputation: 149
• Posts: 717
• Joined: 03-August 06

# 3D Engine

Posted 15 November 2006 - 08:29 PM

Description: A 3D engine written in PHP which highlights you can do anything if you set your mind to it.
```<?php
// Creates a virtual cube composed of polygons
\$cube = new VirtualObject();
// Viewable screen dimensions
\$width = 640;
\$height = 480;
// Sets up the camera's orientation and its focal distance
\$x = sqrt(2) / 2;
\$focal = 500;
\$a =     array(
array(-\$x, 0.5, -0.5, 0),
array(\$x, 0.5, -0.5, 0),
array(0, -\$x, -\$x, 0),
array(0, 0, 0, 1)
);
// The vector normal to the viewing plane and parallel to the viewing direction
\$n2[0][0] = \$a[0][2];
\$n2[1][0] = \$a[1][2];
\$n2[2][0] = \$a[2][2];
\$n2[3][0] = 0;
// Invert camera's plane to allow for change of basis
\$a = inverse(\$a);
// Displace camera to its position in the world
\$a[0][3] = 150;
\$a[1][3] = 150;
\$a[2][3] = 300 * \$x;

// Create two images
\$image1 = imagecreate(\$width, \$height);
\$image2 = imagecreate(\$width, \$height);
// Set the line thickness of each image
imagesetthickness(\$image1, 1);
imagesetthickness(\$image2, 1);
// Set the background colors for each image
\$blue1 = imagecolorallocate(\$image1, 0, 0, 127);
\$blue2 = imagecolorallocate(\$image2, 0, 0, 127);
// Define some colors for each image
\$white = imagecolorallocate(\$image1, 255, 255, 255);
\$gray = imagecolorallocate(\$image2, 127, 127, 127);

// Draw each polygon
for(\$i = 0; \$i < \$cube->getPolyCount(); \$i++){
// Retrieve the polygons from the cube object
\$points = \$cube->getPolygon(\$i);
// Modify each point of the polygon so that its now distanced to the camera's center point
for(\$j = 0; \$j < 3; \$j++){
\$points[0][\$j][0] -= \$a[\$j][3];
\$points[1][\$j][0] -= \$a[\$j][3];
\$points[2][\$j][0] -= \$a[\$j][3];
}
// Determine the normal vector for each polygon
// Write each vector in terms of the camera's orientation (change of basis)
\$points[0] = multiply(\$a, \$points[0]);
\$points[1] = multiply(\$a, \$points[1]);
\$points[2] = multiply(\$a, \$points[2]);
// Determine the distortion due to perspective
\$focus[0] = \$focal / magnitude(\$points[0]);
\$focus[1] = \$focal / magnitude(\$points[1]);
\$focus[2] = \$focal / magnitude(\$points[2]);
// Transform the 3d points into 2d coordinates for drawing
\$x0 = \$width / 2 + (\$points[0][0][0] * \$focus[0]);
\$x1 = \$width / 2 + (\$points[1][0][0] * \$focus[1]);
\$x2 = \$width / 2 + (\$points[2][0][0] * \$focus[2]);
\$y0 = \$height / 2 + (\$points[0][1][0] * \$focus[0]);
\$y1 = \$height / 2 + (\$points[1][1][0] * \$focus[1]);
\$y2 = \$height / 2 + (\$points[2][1][0] * \$focus[2]);
// Determine the cosine of the angle between the viewing plane and the polygonal plane
\$cosTheta = dotProduct(\$n1, \$n2) / (magnitude(\$n1) * magnitude(\$n2));
if(\$cosTheta <= 0){
// White lines because these are the planes at the front of the object
imageline(\$image1, \$x0, \$y0, \$x1, \$y1, \$white);
imageline(\$image1, \$x1, \$y1, \$x2, \$y2, \$white);
//               imageline(\$image1, \$x2, \$y2, \$x0, \$y0, \$white);     // Draws the final polygon line
}else{
// Gray lines because these are the planes at the reare of the object
imageline(\$image2, \$x0, \$y0, \$x1, \$y1, \$gray);
imageline(\$image2, \$x1, \$y1, \$x2, \$y2, \$gray);
//               imageline(\$image2, \$x2, \$y2, \$x0, \$y0, \$gray);     // Draws the final polygon line
}
}

// Make transparent the background of the viewable polygon drawing
imagecolortransparent(\$image1, \$blue1);
// Layer it over the non-viewable polygon drawing
imagecopymerge(\$image2, \$image1, 0, 0, 0, 0, 640, 480, 100);
// Output the finished image
imagepng(\$image2);
// Destroy the images
imagedestroy(\$image1);
imagedestroy(\$image2);

// Computes the cross product of two vectors
// \$a: a row or column vector
// \$b: a row or column vector
function crossProduct(\$a, \$b){
if(sizeof(\$a) == 1){     // Cross product of row vectors
return     array(     // Return the cross product of row vectors as a row vector
array(     \$a[0][1] * \$b[0][2] - \$a[0][2] * \$b[0][1],
-1 * (\$a[0][0] * \$b[0][2] - \$a[0][2] * \$b[0][0]),
\$a[0][0] * \$b[0][1] - \$a[0][1] * \$b[0][0],
0
)
);
}else{     // Cross product of column vectors
return     array(     // Return the cross product of column vectors as a column vector
array(\$a[1][0] * \$b[2][0] - \$a[2][0] * \$b[1][0]),
array(-1 * (\$a[0][0] * \$b[2][0] - \$a[2][0] * \$b[0][0])),
array(\$a[0][0] * \$b[1][0] - \$a[1][0] * \$b[0][0]),
array(0)
);
}
}

// Computes the addition of two matrices
// \$A: an m x n matrix
// \$B: an m x n matrix

// Add the two matrices together
for(\$i = 0; \$i < sizeof(\$A); \$i++){
for(\$j = 0; \$j < sizeof(\$A[0]); \$j++){
\$M[\$i][\$j] = \$A[\$i][\$j] + \$B[\$i][\$j];
}
}

return \$M;     // Return the added matrix
}

// Computes a random matrix
// \$m: the row dimension
// \$n: the column dimension
// \$lower: the lower bound of random numbers
// \$upper: the upper bound of random numbers
function randMatrix(\$m, \$n, \$lower, \$upper){
\$M;     // A random matrix

// Generate the random matrix
for(\$i = 0; \$i < \$m; \$i++){
for(\$j = 0; \$j < \$n; \$j++){
\$M[\$i][\$j] = rand(\$lower, \$upper);
}
}

return \$M;     // Return the random matrix
}

// Computes the magnitude of a vector
// \$a: a row or column vector
function magnitude(\$a){
\$result = 0;     // The magnitude of the vector

// Use the Pythagorean theorem to determine the vector's magnitude
for(\$i = 0; \$i < sizeof(\$a); \$i++){
for(\$j = 0; \$j < sizeof(\$a[0]); \$j++){
\$result += pow(\$a[\$i][\$j], 2);
}
}

return sqrt(\$result);     // Return the magnitude of the vector
}

// Computes the adjoint of a matrix
// \$A: a square matrix
return scale(determinant(\$A), inverse(\$A));     // Returns the adjoint of a matrix
}

// Computes a scaled matrix
// \$k: a scalar number
// \$A: an m x n matrix
function scale(\$k, \$A){

// Scale the matrix by multiplying each entry by k
for(\$i = 0; \$i < sizeof(\$A); \$i++){
for(\$j = 0; \$j < sizeof(\$A[0]); \$j++){
\$A[\$i][\$j] *= \$k;
}
}

return \$A;     // Returns the scaled matrix
}

// Computes the determinant of a matrix
// \$A: a square matrix
function determinant(\$A){
\$determinant = 1;     // The determinant of the matrix
\$n = sizeof(\$A);     // Dimension of the square matrix
\$E = identity(\$n);     // An elementary matrix

// Find the determinant of a matrix by performing elementary matrix operations
// on an augmented matrix through the use of elementary matrices in order
// to convert the matrix into upper triangular form
// Multiply the diagonals of the upper triangular matrix to arrive at the
// determinant, only elementary operations I and III are allowed on the matrix.
// If operation I is performed at any time, multiply the determinant by a -1.
for(\$j = 0; \$j < \$n; \$j++){
for(\$i = \$j; \$i < \$n; \$i++){
if(\$i == \$j){
if(\$A[\$i][\$j] == 0){
for(\$k = \$j + 1; \$k < \$n; \$k++){
if(\$A[\$k][\$j] != 0){
\$swap = \$A[\$i];
\$A[\$i] = \$A[\$k];
\$A[\$k] = \$swap;
\$determinant *= -1;
\$k = \$n;
}
}
}
\$determinant *= \$A[\$i][\$j];
}else{
\$E[\$i][\$j] = -\$A[\$i][\$j] / \$A[\$j][\$j];
}
\$A = multiply(\$E, \$A);
\$E = identity(\$n);
}
}

return \$determinant;     // Return the determinant of the matrix
}

// Computes the inverse of a matrix
// \$A: a square matrix
function inverse(\$A){
\$n = sizeof(\$A);     // Dimension of the square matrix
\$V = identity(\$n);     // The inverse of the matrix
\$E = identity(\$n);     // An elementary matrix

// Find the inverse matrix by performing elementary matrix operations
// on an augmented matrix through the use of elementary matrices
for(\$j = 0; \$j < \$n; \$j++){
for(\$i = \$j; \$i < \$n; \$i++){
if(\$i == \$j){
if(\$A[\$i][\$j] == 0){
for(\$k = \$j + 1; \$k < \$n; \$k++){
if(\$A[\$k][\$j] != 0){
\$swap = \$A[\$i];
\$A[\$i] = \$A[\$k];
\$A[\$k] = \$swap;
\$swap = \$V[\$i];
\$V[\$i] = \$V[\$k];
\$V[\$k] = \$swap;
\$k = \$n;
}
}
}
\$E[\$i][\$j] = 1 / \$A[\$i][\$j];
}else{
\$E[\$i][\$j] = -\$A[\$i][\$j];
}
\$A = multiply(\$E, \$A);
\$V = multiply(\$E, \$V);
\$E = identity(\$n);
}
}
for(\$j = \$n - 1; \$j > 0; \$j--){
for(\$i = \$j - 1; \$i > -1; \$i--){
\$E[\$i][\$j] = -\$A[\$i][\$j];
\$A = multiply(\$E, \$A);
\$V = multiply(\$E, \$V);
\$E = identity(\$n);
}
}

return \$V;     // Return the inverse matrix
}

// Computes the product of a matrix multiplication
// \$A: An m x n matrix
// \$B: An n x o matrix
function multiply(\$A, \$B){
\$M;     // The product of the multiplication
\$B = transpose(\$B);     // Transpose the second matrix

// Do the multiplication by making use of the dot product
for(\$i = 0; \$i < sizeof(\$A); \$i++){
for(\$j = 0; \$j < sizeof(\$B); \$j++){
\$M[\$i][\$j] = dotProduct(array(\$A[\$i]), array(\$B[\$j]));
}
}

return \$M;     // Return the product
}

// Computes the dot product of two vectors
// \$a: a row or column vector
// \$b; a row or column vector
function dotProduct(\$a, \$b){
\$result = 0;     // The result of the dot product

// The dot product
for(\$i = 0; \$i < sizeof(\$a); \$i++){
for(\$j = 0; \$j < sizeof(\$a[0]); \$j++){
\$result += \$a[\$i][\$j] * \$b[\$i][\$j];
}
}

return \$result;     // Return the dot product
}

// Computes the transpose of a matrix
// \$A: the matrix to be transposed
function transpose(\$A){
\$T;          // Transpose matrix

// Switch the i,jth entry to the j,ith entry
for(\$i = 0; \$i < sizeof(\$A); \$i++){
for(\$j = 0; \$j < sizeof(\$A[0]); \$j++){
\$T[\$j][\$i] = \$A[\$i][\$j];
}
}

return \$T;     // Return the transpose matrix
}

// Computes an identity matrix of size n x n
// \$n: size of the matrix wanted
function identity(\$n){
\$I;          // Identity matrix

// Fill the matrices diagonal with 1's and everything else with 0's
for(\$i = 0; \$i < \$n; \$i++){
for(\$j = 0; \$j < \$n; \$j++){
if(\$i == \$j){
\$I[\$i][\$j] = 1;
}else{
\$I[\$i][\$j] = 0;
}
}
}

return \$I;     // Return the identity matrix
}

class VirtualObject{
// Member declarations
private \$polyObject;

// Constructor
function __construct(){
\$this->polyObject =
array(     // object
array(     // polygon
array(     // vector
array(50),
array(-50),
array(50),
array(0)
),
array(     // vector
array(-50),
array(-50),
array(50),
array(0)
),
array(     // vector
array(-50),
array(50),
array(50),
array(0)
)
),
array(     // polygon
array(     // vector
array(-50),
array(50),
array(50),
array(0)
),
array(     // vector
array(50),
array(50),
array(50),
array(0)
),
array(     // vector
array(50),
array(-50),
array(50),
array(0)
)
),
array(     // polygon
array(     // vector
array(50),
array(-50),
array(-50),
array(0)
),
array(     // vector
array(50),
array(-50),
array(50),
array(0)
),
array(     // vector
array(50),
array(50),
array(50),
array(0)
)
),
array(     // polygon
array(     // vector
array(50),
array(50),
array(50),
array(0)
),
array(     // vector
array(50),
array(50),
array(-50),
array(0)
),
array(     // vector
array(50),
array(-50),
array(-50),
array(0)
)
),
array(     // polygon
array(     // vector
array(50),
array(50),
array(-50),
array(0)
),
array(     // vector
array(50),
array(50),
array(50),
array(0)
),
array(     // vector
array(-50),
array(50),
array(50),
array(0)
)
),
array(     // polygon
array(     // vector
array(-50),
array(50),
array(50),
array(0)
),
array(     // vector
array(-50),
array(50),
array(-50),
array(0)
),
array(     // vector
array(50),
array(50),
array(-50),
array(0)
)
),
array(     // polygon
array(     // vector
array(-50),
array(-50),
array(-50),
array(0)
),
array(     // vector
array(50),
array(-50),
array(-50),
array(0)
),
array(     // vector
array(50),
array(50),
array(-50),
array(0)
)
),
array(     // polygon
array(     // vector
array(50),
array(50),
array(-50),
array(0)
),
array(     // vector
array(-50),
array(50),
array(-50),
array(0)
),
array(     // vector
array(-50),
array(-50),
array(-50),
array(0)
)
),
array(     // polygon
array(     // vector
array(-50),
array(50),
array(-50),
array(0)
),
array(     // vector
array(-50),
array(50),
array(50),
array(0)
),
array(     // vector
array(-50),
array(-50),
array(50),
array(0)
)
),
array(     // polygon
array(     // vector
array(-50),
array(-50),
array(50),
array(0)
),
array(     // vector
array(-50),
array(-50),
array(-50),
array(0)
),
array(     // vector
array(-50),
array(50),
array(-50),
array(0)
)
),
array(     // polygon
array(     // vector
array(-50),
array(-50),
array(-50),
array(0)
),
array(     // vector
array(-50),
array(-50),
array(50),
array(0)
),
array(     // vector
array(50),
array(-50),
array(50),
array(0)
)
),
array(     // polygon
array(     // vector
array(50),
array(-50),
array(50),
array(0)
),
array(     // vector
array(50),
array(-50),
array(-50),
array(0)
),
array(     // vector
array(-50),
array(-50),
array(-50),
array(0)
)
)
);
}

// Method declarations

// Returns the polygon count of the object
public function getPolyCount(){
return sizeof(\$this->polyObject);
}

// Returns a particular polygon of the object
public function getPolygon(\$n){
return \$this->polyObject[\$n];
}
}
?>
```

Is This A Good Question/Topic? 0

## Replies To: 3D Engine

### #2 Aurel300

Reputation: 13
• Posts: 230
• Joined: 10-November 07

## Re: 3D Engine

Posted 14 November 2007 - 08:22 AM

Hm... Little bit hard to use, but good.

### #3 Rohtie

Reputation: 0
• Posts: 44
• Joined: 07-March 07

## Re: 3D Engine

Posted 04 February 2009 - 11:04 AM

This is really cool :3 I combined this with javascript and the cube can now be controlled and moved around ^^

### #4 grimpirate

• Pirate King

Reputation: 149
• Posts: 717
• Joined: 03-August 06

## Re: 3D Engine

Posted 04 February 2009 - 04:43 PM

Sweet, I'd love to see that code in action. Mind sharing, or uploading so we can check it out live?

### #5 DingleNutZ

Reputation: 0
• Posts: 121
• Joined: 02-May 09

## Re: 3D Engine

Posted 05 May 2009 - 02:13 PM

bloody hell, must have taken ages

### #6 Xtron

Reputation: 9
• Posts: 28
• Joined: 20-May 09

## Re: 3D Engine

Posted 20 May 2009 - 09:54 PM

Oh my php! Diddn't know you can do that. Nice work.

### #7 SinisterIndieGaming

Reputation: 0
• Posts: 9
• Joined: 02-September 09

## Re: 3D Engine

Posted 03 September 2009 - 05:18 AM

This answered my question that I had for a very long time!

### #8 borninlyoko

• D.I.C Regular

Reputation: 7
• Posts: 350
• Joined: 03-December 09

## Re: 3D Engine

Posted 26 January 2011 - 08:33 PM

*Twitches in awe*