Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jun 11th, 2006, 3:06 AM   #11
splinter9x
Hobbyist Programmer
 
splinter9x's Avatar
 
Join Date: Jun 2006
Posts: 137
Rep Power: 0 splinter9x is an unknown quantity at this point
When I looked at BigK's site link it kinda scared me a little. Nice code, you should try to do something more with it and see how far you can take it... You know see if you can create anything usefull with it...
__________________
Visit my Blog
I support WINDOWS...
splinter9x is offline   Reply With Quote
Old Jun 11th, 2006, 5:55 AM   #12
dpsleep
Newbie
 
Join Date: May 2006
Posts: 16
Rep Power: 0 dpsleep is on a distinguished road
wow, thats pretty cool. yea, for the error mrynit had, you have to enable the gd modual in your php.ini. and for big k you have to add header("Content-type: image/png");
dpsleep is offline   Reply With Quote
Old Jun 11th, 2006, 9:49 PM   #13
grimpirate
King of Portal
 
grimpirate's Avatar
 
Join Date: Sep 2005
Posts: 395
Rep Power: 3 grimpirate is on a distinguished road
Send a message via Yahoo to grimpirate
Thumbs up Works with VRML now

I've actually modified the code now to work with certain types of VRML files. This is a web way of storing 3d objects to display the via your browser. Don't know if it's really in use any more since I couldn't find the official standard, but that's besides the point. I've included 4 types of file in the attachment: a cube, cylinder, sphere, and pyramid. They're low in polygon count because any higher and my pc wouldn't render them lol. Anyhow here's the code just place the four files in the same directory and if you want to see something other than the cylinder just change the variable $filename to whatever the name of the other file is. Again, this is only reading single object VRML files that have some sort of rotation applied to them. Won't work for others, that's somewhere else down the line I suppose.
<?php
	$filename = 'cylinder.wrl';
	$vrml_str = file_get_contents($filename);
	$vrml_tok = str_split($vrml_str);

	for($i = 0; $i < sizeof($vrml_tok); $i++){
		switch($vrml_tok[$i]){
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case '-':
			case '.':
			case ' ':
			case '{':
			case '}':
			case '[':
			case ']':
				break;
			default:
				$vrml_tok[$i] = "";
				break;
		}
	}

	$vrml_tok = implode($vrml_tok);
	$vrml_tok = explode(' 01 ', $vrml_tok);
	array_shift($vrml_tok);

	for($i = 0; $i < sizeof($vrml_tok); $i++){
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "{") + 2);
		$vrml_1[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "[") - 1);
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_3[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "]"));
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_4[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "]"));
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "]") + 1);

		$vrml_1[$i] = explode(" ", $vrml_1[$i]);
		$vrml_2[$i] = array_slice($vrml_1[$i], 3);
		$vrml_1[$i] = array_slice($vrml_1[$i], 0, 3);
		$vrml_3[$i] = explode(" ", $vrml_3[$i]);
		$vrml_4[$i] = explode(" ", $vrml_4[$i]);
		$temp = array_slice($vrml_4[$i], 0, 3);
		for($j = 4; $j < sizeof($vrml_4[$i]); $j += 4){
			$temp = array_merge($temp, array_slice($vrml_4[$i], $j, 3));
		}
		$vrml_4[$i] = $temp;
	}

	for($i = 0; $i < sizeof($vrml_1); $i++){
		$temp = $vrml_1[$i][1];
		$vrml_1[$i][1] = $vrml_1[$i][2];
		$vrml_1[$i][2] = $temp;
	}
	for($i = 0; $i < sizeof($vrml_2); $i++){
		$temp = $vrml_2[$i][1];
		$vrml_2[$i][1] = $vrml_2[$i][2];
		$vrml_2[$i][2] = $temp;
	}
	for($i = 0; $i < sizeof($vrml_3); $i++){
		for($j = 0; $j < sizeof($vrml_3[0]); $j += 3){
			$temp = $vrml_3[$i][$j + 1];
			$vrml_3[$i][$j + 1] = $vrml_3[$i][$j + 2];
			$vrml_3[$i][$j + 2] = $temp;
		}
	}

	for($i = 0; $i < sizeof($vrml_2); $i++){
		$theta_1 = asin(abs($vrml_2[$i][2]));
		if($vrml_2[$i][1] >= 0 && $vrml_2[$i][2] >= 0){
			$theta_1 = -(pi() / 2 - $theta_1);
		}else{
			if($vrml_2[$i][1] < 0 && $vrml_2[$i][2] >= 0){
				$theta_1 = pi() / 2 - $theta_1;
			}else{
				if($vrml_2[$i][1] < 0 && $vrml_2[$i][2] < 0){
					$theta_1 = pi() / 2 + $theta_1;
				}else{
					if($vrml_2[$i][1] >= 0 && $vrml_2[$i][2] < 0){
						$theta_1 = -pi() / 2 - $theta_1;
					}
				}
			}
		}

		$theta_2 = acos(abs($vrml_2[$i][0]) / sqrt(pow($vrml_2[$i][0], 2) + pow($vrml_2[$i][1], 2)));
		if($vrml_2[$i][0] >= 0 && $vrml_2[$i][1] >= 0){
			$theta_2 = -(pi() / 2 - $theta_2);
		}else{
			if($vrml_2[$i][0] < 0 && $vrml_2[$i][1] >= 0){
				$theta_2 = pi() / 2 - $theta_2;
			}else{
				if($vrml_2[$i][0] < 0 && $vrml_2[$i][1] < 0){
					$theta_2 = -(pi() / 2 - $theta_2);
				}else{
					if($vrml_2[$i][0] >= 0 && $vrml_2[$i][1] < 0){
						$theta_2 = pi() / 2 - $theta_2;
					}
				}
			}
		}

		$ini_orient[$i] = identity(3);

		$rotX =	array(
					array(1, 0, 0),
					array(0, cos($theta_1), -sin($theta_1)),
					array(0, sin($theta_1), cos($theta_1))
				);
		$ini_orient[$i] = multiply($rotX, $ini_orient[$i]);

		$rotZ = array(
					array(cos($theta_2), -sin($theta_2), 0),
					array(sin($theta_2), cos($theta_2), 0),
					array(0, 0, 1)
				);
		$ini_orient[$i] = multiply($rotZ, $ini_orient[$i]);

		$rotZ = array(
						array(cos($vrml_2[$i][3]), -sin($vrml_2[$i][3]), 0),
						array(sin($vrml_2[$i][3]), cos($vrml_2[$i][3]), 0),
						array(0, 0, 1)
				);
		$ini_orient[$i] = multiply($ini_orient[$i], $rotZ);
	}

	for($i = 0; $i < sizeof($vrml_1); $i++){
		$worldContainer[$i] = new VirtualObject();
		$temp = array(array());
		$temp[0][0] = $vrml_1[$i][0];
		$temp[1][0] = $vrml_1[$i][1];
		$temp[2][0] = $vrml_1[$i][2];
		$worldContainer[$i]->setCenter($temp);
		$worldContainer[$i]->setOrientation($ini_orient[$i]);
		for($j = 0; $j < sizeof($vrml_3[0]); $j += 3){
			$temp[0][0] = $vrml_3[$i][$j];
			$temp[1][0] = $vrml_3[$i][$j + 1];
			$temp[2][0] = $vrml_3[$i][$j + 2];
			$worldContainer[$i]->setVertex($temp);
		}
		$worldContainer[$i]->setPolygons($vrml_4[$i]);
	}

	class VirtualObject{
		// Member declarations
		private $center;
		private $orientation;
		private $vertices;
		private $polyOrder;

		// Constructor
		function __construct(){
		}

		// Method declarations

		public function setCenter($n){
			$this->center = $n;
		}

		public function getCenter(){
			return $this->center;
		}

		public function setOrientation($n){
			$this->orientation = $n;
		}

		public function getOrientation(){
			return $this->orientation;
		}

		public function setVertex($n){
			$this->vertices[] = $n;
		}

		public function getVertex($n){
			return $this->vertices[$n];
		}

		public function getVertexCount(){
			return sizeof($this->vertices);
		}

		public function setPolygons($n){
			$this->polyOrder = $n;
		}

		public function getPolygon($n){
			$i = 3 * $n;
			return	array(
						$this->getVertex($this->polyOrder[$i]),
						$this->getVertex($this->polyOrder[$i + 1]),
						$this->getVertex($this->polyOrder[$i + 2])
					);
		}

		public function getPolyCount(){
			return sizeof($this->polyOrder) / 3;
		}
	}

	// Viewable screen dimensions
	$width = 640;
	$height = 480;
	// Sets up the camera's orientation and its focal distance
	$x = sqrt(2) / 2;
	$focal = 300;
	$a =	array(
				array(-$x, 0.5, -0.5),
				array($x, 0.5, -0.5),
				array(0, -$x, -$x)
			);
	// 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];
	// Invert camera's plane to allow for change of basis
	$a = inverse($a);

	// 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 < $worldContainer[0]->getPolyCount(); $i++){
		// Retrieve the polygons from the cube object
		$points = $worldContainer[0]->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[$j][0][0] -= 150;
			$points[$j][1][0] -= 150;
			$points[$j][2][0] -= 300 * $x;
		}
		// Determine the normal vector for each polygon
		$n1 = crossProduct(addition($points[0], scale(-1, $points[1])), addition($points[2], scale(-1, $points[1])));
		// 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]
						)
					);
		}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])
					);
		}
	}

	// Computes the addition of two matrices
	// $A: an m x n matrix
	// $B: an m x n matrix
	function addition($A, $B){
		$M;	// The added 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
	function adjoint($A){
		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
	}
?>
If you wanna see what the VRML files look like just open them up in a text editor so you can check out the format.
Attached Files
File Type: zip vrml_objects.zip (2.1 KB, 75 views)
__________________
Lo, there do I see my father. 'Lo, there do I see My mother, and my sisters, and my brothers. 'Lo, there do I see The line of my people... Back to the beginning. 'Lo, they do call to me. They bid me take my place among them. In the halls of Valhalla... Where the brave... May live... ...forever.. GrimBB | Mimesis
grimpirate is offline   Reply With Quote
Old Jun 11th, 2006, 9:52 PM   #14
grimpirate
King of Portal
 
grimpirate's Avatar
 
Join Date: Sep 2005
Posts: 395
Rep Power: 3 grimpirate is on a distinguished road
Send a message via Yahoo to grimpirate
-_- I just noticed that code I added into the prog is HORRENDOUSLY uncommented, sorry about that, got too involved in it and forget to write them as I went along. But if there are any questions feel free to ask and I'll offer up an explanation gladly.
__________________
Lo, there do I see my father. 'Lo, there do I see My mother, and my sisters, and my brothers. 'Lo, there do I see The line of my people... Back to the beginning. 'Lo, they do call to me. They bid me take my place among them. In the halls of Valhalla... Where the brave... May live... ...forever.. GrimBB | Mimesis
grimpirate is offline   Reply With Quote
Old Jun 11th, 2006, 10:42 PM   #15
splinter9x
Hobbyist Programmer
 
splinter9x's Avatar
 
Join Date: Jun 2006
Posts: 137
Rep Power: 0 splinter9x is an unknown quantity at this point
Nice code, works, and your right you should have commented it more lol...
__________________
Visit my Blog
I support WINDOWS...
splinter9x is offline   Reply With Quote
Old Jun 14th, 2006, 4:59 PM   #16
grimpirate
King of Portal
 
grimpirate's Avatar
 
Join Date: Sep 2005
Posts: 395
Rep Power: 3 grimpirate is on a distinguished road
Send a message via Yahoo to grimpirate
Question Ran into a problem, need some help

I properly commented the code and this time I actually applied the rotations to the models. However, when I looked at the sphere.wrl model (the other models worked fine and cylinder.wrl just wouldn't render, too many operations I assume) I noticed that my code is actually drawing white some of the polygon faces that it should be drawing gray. Meaning that it's thinking these are faces which you could see from this perspective. I honestly can't think of the reason why this would be happening. I'm hoping someone here can find my error, so that the app will properly draw. Thanks for any help.
<?php
	$filename = 'sphere.wrl';
	$vrml_str = file_get_contents($filename);	// Convert the file into a string
	$vrml_tok = str_split($vrml_str);			// Split the string into an array of each character

	// Traverse the array and eliminate anything that isn't of numeric relevance
	// Also retain brackets to allow dissection of quantities
	for($i = 0; $i < sizeof($vrml_tok); $i++){
		switch($vrml_tok[$i]){
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case '-':
			case '.':
			case ' ':
			case '{':
			case '}':
			case '[':
			case ']':
				break;
			default:
				$vrml_tok[$i] = "";
				break;
		}
	}

	$vrml_tok = implode($vrml_tok);				// Join the array into a string
	$vrml_tok = explode(' 01 ', $vrml_tok);		// Split the string into arrays
	array_shift($vrml_tok);						// Destroy the first entry in the array

	// Extract the relevant pieces of info from the strings in each array
	// $vrml_1: Object's center location
	// $vrml_2: Object's rotational orientation
	// $vrml_3: Object's vertices
	// $vrml_4: Object's polygons
	for($i = 0; $i < sizeof($vrml_tok); $i++){
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "{") + 2);
		$vrml_1[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "[") - 1);
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_3[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "]"));
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_4[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "]"));
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "]") + 1);

		$vrml_1[$i] = explode(" ", $vrml_1[$i]);
		$vrml_2[$i] = array_slice($vrml_1[$i], 3);
		$vrml_1[$i] = array_slice($vrml_1[$i], 0, 3);
		$vrml_3[$i] = explode(" ", $vrml_3[$i]);
		$vrml_4[$i] = explode(" ", $vrml_4[$i]);
		$temp = array_slice($vrml_4[$i], 0, 3);
		for($j = 4; $j < sizeof($vrml_4[$i]); $j += 4){
			$temp = array_merge($temp, array_slice($vrml_4[$i], $j, 3));
		}
		$vrml_4[$i] = $temp;
	}

	// Swap the values of x z y to become x y z
	for($i = 0; $i < sizeof($vrml_1); $i++){
		$temp = $vrml_1[$i][1];
		$vrml_1[$i][1] = $vrml_1[$i][2];
		$vrml_1[$i][2] = $temp;
	}
	for($i = 0; $i < sizeof($vrml_2); $i++){
		$temp = $vrml_2[$i][1];
		$vrml_2[$i][1] = $vrml_2[$i][2];
		$vrml_2[$i][2] = $temp;
	}
	for($i = 0; $i < sizeof($vrml_3); $i++){
		for($j = 0; $j < sizeof($vrml_3[0]); $j += 3){
			$temp = $vrml_3[$i][$j + 1];
			$vrml_3[$i][$j + 1] = $vrml_3[$i][$j + 2];
			$vrml_3[$i][$j + 2] = $temp;
		}
	}

	// Compute the orientation of the object so as to find a rotational transform matrix
	for($i = 0; $i < sizeof($vrml_2); $i++){
		$theta_1 = asin(abs($vrml_2[$i][2]));
		if($vrml_2[$i][1] >= 0 && $vrml_2[$i][2] >= 0){
			$theta_1 = -(pi() / 2 - $theta_1);
		}else{
			if($vrml_2[$i][1] < 0 && $vrml_2[$i][2] >= 0){
				$theta_1 = pi() / 2 - $theta_1;
			}else{
				if($vrml_2[$i][1] < 0 && $vrml_2[$i][2] < 0){
					$theta_1 = pi() / 2 + $theta_1;
				}else{
					if($vrml_2[$i][1] >= 0 && $vrml_2[$i][2] < 0){
						$theta_1 = -pi() / 2 - $theta_1;
					}
				}
			}
		}

		$theta_2 = acos(abs($vrml_2[$i][0]) / sqrt(pow($vrml_2[$i][0], 2) + pow($vrml_2[$i][1], 2)));
		if($vrml_2[$i][0] >= 0 && $vrml_2[$i][1] >= 0){
			$theta_2 = -(pi() / 2 - $theta_2);
		}else{
			if($vrml_2[$i][0] < 0 && $vrml_2[$i][1] >= 0){
				$theta_2 = pi() / 2 - $theta_2;
			}else{
				if($vrml_2[$i][0] < 0 && $vrml_2[$i][1] < 0){
					$theta_2 = -(pi() / 2 - $theta_2);
				}else{
					if($vrml_2[$i][0] >= 0 && $vrml_2[$i][1] < 0){
						$theta_2 = pi() / 2 - $theta_2;
					}
				}
			}
		}

		$ini_orient[$i] = identity(3);

		// Rotate the object about the world's X axis according to the computed $theta_1
		$rotX =	array(
					array(1, 0, 0),
					array(0, cos($theta_1), -sin($theta_1)),
					array(0, sin($theta_1), cos($theta_1))
				);
		$ini_orient[$i] = multiply($rotX, $ini_orient[$i]);

		// Rotate the object about the world's Z axis according to the computed $theta_2
		$rotZ = array(
					array(cos($theta_2), -sin($theta_2), 0),
					array(sin($theta_2), cos($theta_2), 0),
					array(0, 0, 1)
				);
		$ini_orient[$i] = multiply($rotZ, $ini_orient[$i]);

		// Rotate the object about its own Z axis using the value given
		$rotZ = array(
						array(cos($vrml_2[$i][3]), -sin($vrml_2[$i][3]), 0),
						array(sin($vrml_2[$i][3]), cos($vrml_2[$i][3]), 0),
						array(0, 0, 1)
				);
		$ini_orient[$i] = multiply($ini_orient[$i], $rotZ);
	}

	// Create all the objects find in the world and store them in an array
	// Initialize these as well
	for($i = 0; $i < sizeof($vrml_1); $i++){
		$worldContainer[$i] = new VirtualObject();
		$temp = array(array());
		$temp[0][0] = $vrml_1[$i][0];
		$temp[1][0] = $vrml_1[$i][1];
		$temp[2][0] = $vrml_1[$i][2];
		$worldContainer[$i]->setCenter($temp);
		$worldContainer[$i]->setOrientation($ini_orient[$i]);
		for($j = 0; $j < sizeof($vrml_3[0]); $j += 3){
			$temp[0][0] = $vrml_3[$i][$j];
			$temp[1][0] = $vrml_3[$i][$j + 1];
			$temp[2][0] = $vrml_3[$i][$j + 2];
			$worldContainer[$i]->setVertex($temp);
		}
		$worldContainer[$i]->setPolygons($vrml_4[$i]);
	}

	// The class that stores virtual objects
	class VirtualObject{
		// Member declarations
		private $center;		// Object center
		private $orientation;	// Object orientation
		private $vertices;		// Object vertices
		private $polyOrder;		// Object polygons

		// Constructor
		function __construct(){
		}

		// Method declarations

		public function setCenter($n){
			$this->center = $n;
		}

		public function getCenter(){
			return $this->center;
		}

		public function setOrientation($n){
			$this->orientation = $n;
		}

		public function getOrientation(){
			return $this->orientation;
		}

		public function setVertex($n){
			$this->vertices[] = $n;
		}

		public function getVertex($n){
			return $this->vertices[$n];
		}

		public function getVertexCount(){
			return sizeof($this->vertices);
		}

		public function setPolygons($n){
			$this->polyOrder = $n;
		}

		public function getPolygon($n){
			$i = 3 * $n;
			return	array(
						$this->getVertex($this->polyOrder[$i]),
						$this->getVertex($this->polyOrder[$i + 1]),
						$this->getVertex($this->polyOrder[$i + 2])
					);
		}

		public function getPolyCount(){
			return sizeof($this->polyOrder) / 3;
		}
	}

	// Viewable screen dimensions
	$width = 640;
	$height = 480;
	// Sets up the camera's orientation and its focal distance
	$x = sqrt(2) / 2;
	$focal = 300;
	$a =	array(
				array(-$x, 0.5, -0.5),
				array($x, 0.5, -0.5),
				array(0, -$x, -$x)
			);
	// 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];
	// Invert camera's plane to allow for change of basis
	$a = inverse($a);

	// 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 < $worldContainer[0]->getPolyCount(); $i++){
		// Retrieve the polygons from the cube object
		$points = $worldContainer[0]->getPolygon($i);
		// Rotate each vertex vector according to the indicated object's orientation
		$points[0] = multiply($worldContainer[0]->getOrientation(), $points[0]);
		$points[1] = multiply($worldContainer[0]->getOrientation(), $points[1]);
		$points[2] = multiply($worldContainer[0]->getOrientation(), $points[2]);
		// Modify each point of the polygon so that its now distanced to the camera's center point
		for($j = 0; $j < 3; $j++){
			$points[$j][0][0] -= 150;
			$points[$j][1][0] -= 150;
			$points[$j][2][0] -= 300 * $x;
		}
		// Determine the normal vector for each polygon
		$n1 = crossProduct(addition($points[0], scale(-1, $points[1])), addition($points[2], scale(-1, $points[1])));
		// 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);
		}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);
		}
	}

	// 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);
	// Flip the image horizontally
	// Output the finished image
	header("Content-type: image/png");
	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]
						)
					);
		}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])
					);
		}
	}

	// Computes the addition of two matrices
	// $A: an m x n matrix
	// $B: an m x n matrix
	function addition($A, $B){
		$M;	// The added 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
	function adjoint($A){
		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
	}
?>
__________________
Lo, there do I see my father. 'Lo, there do I see My mother, and my sisters, and my brothers. 'Lo, there do I see The line of my people... Back to the beginning. 'Lo, they do call to me. They bid me take my place among them. In the halls of Valhalla... Where the brave... May live... ...forever.. GrimBB | Mimesis
grimpirate is offline   Reply With Quote
Old Jun 16th, 2006, 10:41 AM   #17
Lich
Professional Programmer
 
Lich's Avatar
 
Join Date: May 2005
Location: Detroit
Posts: 254
Rep Power: 4 Lich is on a distinguished road
Send a message via AIM to Lich Send a message via MSN to Lich
Mine doesn't compile
http://john.cruzweb.net/cube/cube.php
__________________
--John Cruz
Web Developer
www.cruzweb.net
Lich is offline   Reply With Quote
Old Jun 16th, 2006, 3:20 PM   #18
grimpirate
King of Portal
 
grimpirate's Avatar
 
Join Date: Sep 2005
Posts: 395
Rep Power: 3 grimpirate is on a distinguished road
Send a message via Yahoo to grimpirate
You have to download the zip file with the models, and put them into the same directory as the php file. If you already did that and it's not working try changing the $filename to 'pyramid.wrl' since that's the simplest of all the models. I know that my computer won't render the 'cylinder.wrl' model. Not sure if it's because of a computational error or it simply clocks out or something.
__________________
Lo, there do I see my father. 'Lo, there do I see My mother, and my sisters, and my brothers. 'Lo, there do I see The line of my people... Back to the beginning. 'Lo, they do call to me. They bid me take my place among them. In the halls of Valhalla... Where the brave... May live... ...forever.. GrimBB | Mimesis
grimpirate is offline   Reply With Quote
Old Jun 19th, 2006, 12:20 AM   #19
grimpirate
King of Portal
 
grimpirate's Avatar
 
Join Date: Sep 2005
Posts: 395
Rep Power: 3 grimpirate is on a distinguished road
Send a message via Yahoo to grimpirate
Angry Still not having any luck

I figured I'd put up an image of what the output produces with the sphere.wrl model. I've been trying to figure out the problem with my code, but honestly I just can't see what it is. I probably missed something small somewhere and I keep looking over it. Anyways, take a look at the pic closely and you'll see that some of the back faces are being drawn in white when they should be in gray.
Attached Images
File Type: png sphere.png (2.8 KB, 264 views)
__________________
Lo, there do I see my father. 'Lo, there do I see My mother, and my sisters, and my brothers. 'Lo, there do I see The line of my people... Back to the beginning. 'Lo, they do call to me. They bid me take my place among them. In the halls of Valhalla... Where the brave... May live... ...forever.. GrimBB | Mimesis
grimpirate is offline   Reply With Quote
Old Jun 19th, 2006, 5:53 PM   #20
grimpirate
King of Portal
 
grimpirate's Avatar
 
Join Date: Sep 2005
Posts: 395
Rep Power: 3 grimpirate is on a distinguished road
Send a message via Yahoo to grimpirate
Thumbs up Success!

Finally, fixed that hidden line problem with some help from a 3d expert by the name of MarkR over at gamedev.net. Turns out that the problem is that I was computing the angle between planes necessary to determine the hidden lines with the incorrect vector. I was using the vectors normal to the polgons and the vector normal to the camera plane. However, the vectors to be used are a vector from the viewing point to some point on the polygon and the normal to the polygon plane. Here's the new code and the output (you'll be able to see the difference between the two pics now):
<?php
	$filename = 'sphere.wrl';
	$vrml_str = file_get_contents($filename);	// Convert the file into a string
	$vrml_tok = str_split($vrml_str);			// Split the string into an array of each character

	// Traverse the array and eliminate anything that isn't of numeric relevance
	// Also retain brackets to allow dissection of quantities
	for($i = 0; $i < sizeof($vrml_tok); $i++){
		switch($vrml_tok[$i]){
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
			case '-':
			case '.':
			case ' ':
			case '{':
			case '}':
			case '[':
			case ']':
				break;
			default:
				$vrml_tok[$i] = "";
				break;
		}
	}

	$vrml_tok = implode($vrml_tok);				// Join the array into a string
	$vrml_tok = explode(' 01 ', $vrml_tok);		// Split the string into arrays
	array_shift($vrml_tok);						// Destroy the first entry in the array

	// Extract the relevant pieces of info from the strings in each array
	// $vrml_1: Object's center location
	// $vrml_2: Object's rotational orientation
	// $vrml_3: Object's vertices
	// $vrml_4: Object's polygons
	for($i = 0; $i < sizeof($vrml_tok); $i++){
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "{") + 2);
		$vrml_1[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "[") - 1);
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_3[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "]"));
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "[") + 1);
		$vrml_4[$i] = substr($vrml_tok[$i], 0, strpos($vrml_tok[$i], "]"));
		$vrml_tok[$i] = substr($vrml_tok[$i], strpos($vrml_tok[$i], "]") + 1);

		$vrml_1[$i] = explode(" ", $vrml_1[$i]);
		$vrml_2[$i] = array_slice($vrml_1[$i], 3);
		$vrml_1[$i] = array_slice($vrml_1[$i], 0, 3);
		$vrml_3[$i] = explode(" ", $vrml_3[$i]);
		$vrml_4[$i] = explode(" ", $vrml_4[$i]);
		$temp = array_slice($vrml_4[$i], 0, 3);
		for($j =