array('old' => 'mojang', 'default' => false), 'user' => array('old' => 'login', 'default' => false), 'vr' => array('old' => 'a', 'default' => '-25'), 'hr' => array('old' => 'w', 'default' => '35'), 'hrh' => array('old' => 'wt', 'default' => '0'), 'vrll' => array('old' => 'ajg', 'default' => '0'), 'vrrl' => array('old' => 'ajd', 'default' => '0'), 'vrla' => array('old' => 'abg', 'default' => '0'), 'vrra' => array('old' => 'abd', 'default' => '0'), 'displayHair' => array('old' => 'displayHairs', 'default' => 'true'), 'headOnly' => array('old' => 'headOnly', 'default' => 'false'), 'format' => array('old' => 'format', 'default' => 'png'), 'ratio' => array('old' => 'ratio', 'default' => '12'), 'aa' => array('old' => 'aa', 'default' => 'false'), 'layers' => array('old' => 'layers', 'default' => 'true') ); if(array_key_exists($name, $parameters)) { if(isset($_GET[$name])) { return $_GET[$name]; } else if (isset($_GET[$parameters[$name]['old']])) { return $_GET[$parameters[$name]['old']]; } return $parameters[$name]['default']; } return false; } // Check if the player name value has been set, and that we are not running as an included/required file. else do nothing. if(( basename(__FILE__) == basename($_SERVER["SCRIPT_FILENAME"]) ) && ((grabGetValue('user') !== false) || (grabGetValue('mojang') !== false))) { // There is a player name so they want an image output via url $renderparams = array(grabGetValue('mojang'), grabGetValue('user'), grabGetValue('vr'), grabGetValue('hr'), grabGetValue('hrh'), grabGetValue('vrll'), grabGetValue('vrrl'), grabGetValue('vrla'), grabGetValue('vrra'), grabGetValue('displayHair'), grabGetValue('headOnly'), grabGetValue('format'), grabGetValue('ratio'), grabGetValue('aa'), grabGetValue('layers')); $player = new render3DPlayer(...$renderparams); $res = $player->getSkinFile(); $skinRaw = $res[0]; $skinHash = $res[1]; if ($_GET['dl'] == 'true') {header('Content-Disposition: attachment; filename='. grabGetValue('user').'-'.hash('adler32', serialize($renderparams).$skinRaw).'.png');} $conttype = ['svg'=>'image/svg+xml','base64'=>'text/plain','png'=>'image/png','raw'=>'image/png']; header('Content-Type: '.$conttype[grabGetValue('format')]); // send content-type for any format if(grabGetValue('format') == 'raw'){ echo file_get_contents($skinRaw); } else { // cache system for "rendered" skins unset($renderparams[0]); unset($renderparams[1]); $cdir = __DIR__.'/../../'.$config['cache_dir']; mkdir($cdir, 0775, true); $cfile = $cdir.$skinHash.'-'.hash("md5", serialize($renderparams)); if (!is_file($cfile) or file_get_contents($cfile) == '') { $player->get3DRender($skinRaw, $cfile); } echo file_get_contents($cfile); touch($cfile); cacheClean(__DIR__.'/../../'); } } else { header('Content-Type: text/plain'); echo file_get_contents(__FILE__); } /* Render3DPlayer class * */ class render3DPlayer { // Use a fallback skin whenever something goes wrong. private $fallback_img = 'https://textures.minecraft.net/texture/dc1c77ce8e54925ab58125446ec53b0cdd3d0ca3db273eb908d5482787ef4016'; private $mojang = null; private $playerName = null; private $playerSkin = false; private $isNewSkinType = false; private $hd_ratio = 1; private $vR = null; private $hR = null; private $hrh = null; private $vrll = null; private $vrrl = null; private $vrla = null; private $vrra = null; private $head_only = null; private $display_hair = null; private $format = null; private $ratio = null; private $aa = null; private $layers = null; // Rotation variables in radians (3D Rendering) private $alpha = null; // Vertical rotation on the X axis. private $omega = null; // Horizontal rotation on the Y axis. private $members_angles = array(); // Head, Helmet, Torso, Arms, Legs private $visible_faces_format = null; private $visible_faces = null; private $all_faces = null; private $front_faces = null; private $back_faces = null; private $cube_points = null; private $polygons = null; private $times = null; public function __construct($mojang, $user, $vr, $hr, $hrh, $vrll, $vrrl, $vrla, $vrra, $displayHair, $headOnly, $format, $ratio, $aa, $layers) { $this->mojang = $mojang; $this->playerName = $user; $this->vR = $vr; $this->hR = $hr; $this->hrh = $hrh; $this->vrll = $vrll; $this->vrrl = $vrrl; $this->vrla = $vrla; $this->vrra = $vrra; $this->head_only = ($headOnly == 'true'); $this->display_hair = ($displayHair != 'false'); $this->format = $format; $this->ratio = $ratio; $this->aa = ($aa == 'true'); $this->layers = ($layers == 'true'); } /* Function can be used for tracking script duration * */ private function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float) $usec + (float) $sec); } /* Fetches skin URL from database using the given name * * Expects a name * returns a player skin file */ public function getSkinFile() { global $config; if ($this->mojang!=null) { preg_match('/[^\/]+$/', $this->mojang, $mj256); $skinURL = 'https://textures.minecraft.net/texture/'.$mj256[0];} else if ($this->playerName!=null) { // get existing skin from skinsrestorer. $skinName = query('sr', 'SELECT Skin FROM ' . $config['sr']['playertable'] . ' WHERE Nick = ?', [$this->playerName])->fetch(PDO::FETCH_ASSOC)['Skin']; $skinLookup = query('sr', 'SELECT Value FROM ' . $config['sr']['skintable'] . ' WHERE Nick = ?', [$skinName])->fetch(PDO::FETCH_ASSOC)['Value']; $skinURL = json_decode(base64_decode($skinLookup), true)['textures']['SKIN']['url']; if (!is_string($skinURL)) { // if cannot get skin from skinsrestorer, get skin from mojang. $mjdfskfl = __DIR__.'/../../'.$config['cache_dir'].'mojang_skin-'.strtolower($this->playerName); if (file_exists($mjdfskfl)) { // fetch cached mojang skin $skinURL = file_get_contents($mjdfskfl); } else { // fetch mojang version of skin $pf = json_decode(file_get_contents('https://api.mojang.com/users/profiles/minecraft/'.strtolower($this->playerName)), true); if(is_array($pf) and array_key_exists("id", $pf)) { $ca = json_decode(file_get_contents('https://sessionserver.mojang.com/session/minecraft/profile/'.$pf["id"]), true);} // $ca = json_decode(file_get_contents(cacheGrab('https://sessionserver.mojang.com/session/minecraft/profile/ef5db304c36841089a352fd0a072b73d', 'test', __DIR__.'/../../'))); if(is_array($ca) and array_key_exists("properties", $ca)) { foreach($ca["properties"] as $element) { if(array_key_exists("name", $element) && $element["name"] == "textures") { $content = base64_decode($element["value"]); $skinArray = json_decode($content, true); if(array_key_exists("textures", $skinArray) and array_key_exists("SKIN", $skinArray["textures"])){ file_put_contents($mjdfskfl, $skinArray["textures"]["SKIN"]["url"]); $skinURL = $skinArray["textures"]["SKIN"]["url"];}}}}}}} if (strlen($skinURL) < 1) { $skinURL = $this->fallback_img; } // if can't get skin, use steve. if (!$mj256) { preg_match('/[^\/]+$/', $skinURL, $mj256); } return [cacheGrab($skinURL, $mj256[0], __DIR__.'/../../', false, ['sha256', $mj256[0]]), $mj256[0]]; } /* Function renders the 3d image * */ public function get3DRender($skinRaw, $cacheFile) { global $minX, $maxX, $minY, $maxY; // Download and check the player skin $this->playerSkin = @imageCreateFromPng($skinRaw); if ((!$this->playerSkin) || (imagesy($this->playerSkin) % 32 != 0)) { // Player skin does not exist or bad ratio created $this->playerSkin = imageCreateFromPng($this->fallback_img); } $this->hd_ratio = imagesx($this->playerSkin) / 64; // Set HD ratio to 2 if the skin is 128x64. Check via width, not height because of new skin type. // check if new skin type. If both sides are equaly long: new skin type if(imagesx($this->playerSkin) == imagesy($this->playerSkin)) { $this->isNewSkinType = true; } $this->playerSkin = img::convertToTrueColor($this->playerSkin); // Convert the image to true color if not a true color image $this->times[] = array('Convert-to-true-color-if-needed', $this->microtime_float()); $this->makeBackgroundTransparent(); // make background transparent (fix for weird rendering skins) $this->times[] = array('Made-Background-Transparent', $this->microtime_float()); // Quick fix for 1.8: // Copy the extra layers ontop of the base layers if($this->layers) { $this->fixNewSkinTypeLayers(); } $this->calculateAngles(); $this->times[] = array('Angle-Calculations', $this->microtime_float()); $this->facesDetermination(); $this->times[] = array('Determination-of-faces', $this->microtime_float()); $this->generatePolygons(); $this->times[] = array('Polygon-generation', $this->microtime_float()); $this->memberRotation(); $this->times[] = array('Members-rotation', $this->microtime_float()); $this->createProjectionPlan(); $this->times[] = array('Projection-plan', $this->microtime_float()); $result = $this->displayImage($output); $this->times[] = array('Display-image', $this->microtime_float()); switch($this->format) { case 'svg': file_put_contents($cacheFile, ' ' . $result . "\n"); break; case 'base64': echo file_put_contents($cacheFile, $result); break; case 'png': default: imagepng($result, $cacheFile); imagedestroy($result); break; } } /* Function fixes issues with images that have a solid background * * Espects an tru color image. */ private function makeBackgroundTransparent() { // check if the corner box is one solid color $tempValue = null; $needRemove = true; for ($iH = 0; $iH < 8; $iH++) { for ($iV = 0; $iV < 8; $iV++) { $pixelColor = imagecolorat($this->playerSkin, $iH, $iV); $indexColor = imagecolorsforindex($this->playerSkin, $pixelColor); if($indexColor['alpha'] > 120) { // the image contains transparancy, noting to do $needRemove = false; } if($tempValue === null) { $tempValue = $pixelColor; } else if ($tempValue != $pixelColor){ // Cannot determine a background color, file is probably fine $needRemove = false; } } } $imgX = imagesx($this->playerSkin); $imgY = imagesy($this->playerSkin); $dst = img::createEmptyCanvas($imgX, $imgY); imagesavealpha($this->playerSkin, false); if($needRemove) { // the entire block is one solid color. Use this color to clear the background. $r = ($tempValue >> 16) & 0xFF; $g = ($tempValue >> 8) & 0xFF; $b = $tempValue & 0xFF; //imagealphablending($dst, true); $transparant = imagecolorallocate($this->playerSkin, $r, $g, $b); imagecolortransparent($this->playerSkin, $transparant); // create fill $color = imagecolorallocate($dst, $r, $g, $b); } else { // create fill $color = imagecolorallocate($dst, 0, 0, 0); } // fill the areas that should not be transparant $positionMultiply = $imgX / 64; // head imagefilledrectangle($dst, 8*$positionMultiply, 0*$positionMultiply, 23*$positionMultiply, 7*$positionMultiply, $color); imagefilledrectangle($dst, 0*$positionMultiply, 8*$positionMultiply, 31*$positionMultiply, 15*$positionMultiply, $color); // right leg, body, right arm imagefilledrectangle($dst, 4*$positionMultiply, 16*$positionMultiply, 11*$positionMultiply, 19*$positionMultiply, $color); imagefilledrectangle($dst, 20*$positionMultiply, 16*$positionMultiply, 35*$positionMultiply, 19*$positionMultiply, $color); imagefilledrectangle($dst, 44*$positionMultiply, 16*$positionMultiply, 51*$positionMultiply, 19*$positionMultiply, $color); imagefilledrectangle($dst, 0*$positionMultiply, 20*$positionMultiply, 54*$positionMultiply, 31*$positionMultiply, $color); // left leg, left arm imagefilledrectangle($dst, 20*$positionMultiply, 48*$positionMultiply, 27*$positionMultiply, 51*$positionMultiply, $color); imagefilledrectangle($dst, 36*$positionMultiply, 48*$positionMultiply, 43*$positionMultiply, 51*$positionMultiply, $color); imagefilledrectangle($dst, 16*$positionMultiply, 52*$positionMultiply, 47*$positionMultiply, 63*$positionMultiply, $color); imagecopy($dst, $this->playerSkin, 0, 0, 0, 0, $imgX, $imgY); $this->playerSkin = $dst; return; } /* Function converts a 1.8 skin (which is not supported by * the script) to the old skin format. * * Espects an image. * Returns a croped image. */ private function cropToOldSkinFormat() { if(imagesx($this->playerSkin) !== imagesy($this->playerSkin)) { return $this->playerSkin; } $newWidth = imagesx($this->playerSkin); $newHeight = $newWidth / 2; $newImgPng = img::createEmptyCanvas($newWidth, $newHeight); imagecopy($newImgPng, $this->playerSkin, 0, 0, 0, 0, $newWidth, $newHeight); $this->playerSkin = $newImgPng; } /* Function copys the extra layers of a 1.8 skin * onto the base layers so that it will still show. QUICK FIX, NEEDS BETTER FIX * * Espects an image. * Returns a croped image. */ private function fixNewSkinTypeLayers() { if(!$this->isNewSkinType) { return; } imagecopy($this->playerSkin, $this->playerSkin, 0, 16, 0, 32, 56, 16); // RL2, BODY2, RA2 imagecopy($this->playerSkin, $this->playerSkin, 16, 48, 0, 48, 16, 16); // LL2 imagecopy($this->playerSkin, $this->playerSkin, 32, 48, 48, 48, 16, 16); // LA2 } /* Function Calculates the angels * */ private function calculateAngles() { global $cos_alpha, $sin_alpha, $cos_omega, $sin_omega; global $minX, $maxX, $minY, $maxY; // Rotation variables in radians (3D Rendering) $this->alpha = deg2rad($this->vR); // Vertical rotation on the X axis. $this->omega = deg2rad($this->hR); // Horizontal rotation on the Y axis. // Cosine and Sine values $cos_alpha = cos($this->alpha); $sin_alpha = sin($this->alpha); $cos_omega = cos($this->omega); $sin_omega = sin($this->omega); $this->members_angles['torso'] = array( 'cos_alpha' => cos(0), 'sin_alpha' => sin(0), 'cos_omega' => cos(0), 'sin_omega' => sin(0) ); $alpha_head = 0; $omega_head = deg2rad($this->hrh); $this->members_angles['head'] = $this->members_angles['helmet'] = array( // Head and helmet get the same calculations 'cos_alpha' => cos($alpha_head), 'sin_alpha' => sin($alpha_head), 'cos_omega' => cos($omega_head), 'sin_omega' => sin($omega_head) ); $alpha_right_arm = deg2rad($this->vrra); $omega_right_arm = 0; $this->members_angles['rightArm'] = array( 'cos_alpha' => cos($alpha_right_arm), 'sin_alpha' => sin($alpha_right_arm), 'cos_omega' => cos($omega_right_arm), 'sin_omega' => sin($omega_right_arm) ); $alpha_left_arm = deg2rad($this->vrla); $omega_left_arm = 0; $this->members_angles['leftArm'] = array( 'cos_alpha' => cos($alpha_left_arm), 'sin_alpha' => sin($alpha_left_arm), 'cos_omega' => cos($omega_left_arm), 'sin_omega' => sin($omega_left_arm) ); $alpha_right_leg = deg2rad($this->vrrl); $omega_right_leg = 0; $this->members_angles['rightLeg'] = array( 'cos_alpha' => cos($alpha_right_leg), 'sin_alpha' => sin($alpha_right_leg), 'cos_omega' => cos($omega_right_leg), 'sin_omega' => sin($omega_right_leg) ); $alpha_left_leg = deg2rad($this->vrll); $omega_left_leg = 0; $this->members_angles['leftLeg'] = array( 'cos_alpha' => cos($alpha_left_leg), 'sin_alpha' => sin($alpha_left_leg), 'cos_omega' => cos($omega_left_leg), 'sin_omega' => sin($omega_left_leg) ); $minX = 0; $maxX = 0; $minY = 0; $maxY = 0; } /* Function determinates faces * */ private function facesDetermination() { $this->visible_faces_format = array( 'front' => array(), 'back' => array () ); $this->visible_faces = array( 'head' => $this->visible_faces_format, 'torso' => $this->visible_faces_format, 'rightArm' => $this->visible_faces_format, 'leftArm' => $this->visible_faces_format, 'rightLeg' => $this->visible_faces_format, 'leftLeg' => $this->visible_faces_format ); $this->all_faces = array( 'back', 'right', 'top', 'front', 'left', 'bottom' ); // Loop each preProject and Project then calculate the visible faces for each - also display foreach ($this->visible_faces as $k => &$v) { unset($cube_max_depth_faces, $this->cube_points); $this->setCubePoints(); foreach ($this->cube_points as $cube_point) { $cube_point[0]->preProject(0, 0, 0, $this->members_angles[$k]['cos_alpha'], $this->members_angles[$k]['sin_alpha'], $this->members_angles[$k]['cos_omega'], $this->members_angles[$k]['sin_omega']); $cube_point[0]->project(); if (!isset($cube_max_depth_faces)) { $cube_max_depth_faces = $cube_point; } else if ($cube_max_depth_faces[0]->getDepth() > $cube_point[0]->getDepth()) { $cube_max_depth_faces = $cube_point; } } $v['back'] = $cube_max_depth_faces[1]; $v['front'] = array_diff($this->all_faces, $v['back']); } $this->setCubePoints(); unset($cube_max_depth_faces); foreach ($this->cube_points as $cube_point) { $cube_point[0]->project(); if (!isset($cube_max_depth_faces)) { $cube_max_depth_faces = $cube_point; } else if ($cube_max_depth_faces[0]->getDepth() > $cube_point[ 0 ]->getDepth()) { $cube_max_depth_faces = $cube_point; } $this->back_faces = $cube_max_depth_faces[ 1 ]; $this->front_faces = array_diff($this->all_faces, $this->back_faces ); } } /* Function sets all cube points * */ private function setCubePoints() { $this->cube_points = array(); $this->cube_points[] = array( new Point(array( 'x' => 0, 'y' => 0, 'z' => 0 )), array( 'back', 'right', 'top' )); // 0 $this->cube_points[] = array( new Point(array( 'x' => 0, 'y' => 0, 'z' => 1 )), array( 'front', 'right', 'top' )); // 1 $this->cube_points[] = array( new Point(array( 'x' => 0, 'y' => 1, 'z' => 0 )), array( 'back', 'right', 'bottom' )); // 2 $this->cube_points[] = array( new Point(array( 'x' => 0, 'y' => 1, 'z' => 1 )), array( 'front', 'right', 'bottom' )); // 3 $this->cube_points[] = array( new Point(array( 'x' => 1, 'y' => 0, 'z' => 0 )), array( 'back', 'left', 'top' )); // 4 $this->cube_points[] = array( new Point(array( 'x' => 1, 'y' => 0, 'z' => 1 )), array( 'front', 'left', 'top' )); // 5 $this->cube_points[] = array( new Point(array( 'x' => 1, 'y' => 1, 'z' => 0 )), array( 'back', 'left', 'bottom' )); // 6 $this->cube_points[] = array( new Point(array( 'x' => 1, 'y' => 1, 'z' => 1 )), array( 'front', 'left', 'bottom' )); // 7 } /* Function generates polygons * */ private function generatePolygons() { $depths_of_face = array(); $this->polygons = array(); $cube_faces_array = array( 'front' => array(), 'back' => array(), 'top' => array(), 'bottom' => array(), 'right' => array(), 'left' => array () ); $this->polygons = array('helmet' => $cube_faces_array, 'head' => $cube_faces_array, 'torso' => $cube_faces_array, 'rightArm' => $cube_faces_array, 'leftArm' => $cube_faces_array, 'rightLeg' => $cube_faces_array, 'leftLeg' => $cube_faces_array ); $hd_ratio = $this->hd_ratio; $img_png = $this->playerSkin; // HEAD for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 9 * $hd_ratio; $j++ ) { if ( !isset( $volume_points[ $i ][ $j ][ -2 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ -2 * $hd_ratio ] = new Point( array( 'x' => $i, 'y' => $j, 'z' => -2 * $hd_ratio ) ); } if ( !isset( $volume_points[ $i ][ $j ][ 6 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ 6 * $hd_ratio ] = new Point( array( 'x' => $i, 'y' => $j, 'z' => 6 * $hd_ratio ) ); } } } for ( $j = 0; $j < 9 * $hd_ratio; $j++ ) { for ( $k = -2 * $hd_ratio; $k < 7 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ 0 ][ $j ][ $k ] ) ) { $volume_points[ 0 ][ $j ][ $k ] = new Point( array( 'x' => 0, 'y' => $j, 'z' => $k ) ); } if ( !isset( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] ) ) { $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] = new Point( array( 'x' => 8 * $hd_ratio, 'y' => $j, 'z' => $k ) ); } } } for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $k = -2 * $hd_ratio; $k < 7 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ $i ][ 0 ][ $k ] ) ) { $volume_points[ $i ][ 0 ][ $k ] = new Point( array( 'x' => $i, 'y' => 0, 'z' => $k ) ); } if ( !isset( $volume_points[ $i ][ 8 * $hd_ratio ][ $k ] ) ) { $volume_points[ $i ][ 8 * $hd_ratio ][ $k ] = new Point( array( 'x' => $i, 'y' => 8 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 8 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 8 * $hd_ratio; $j++ ) { $this->polygons[ 'head' ][ 'back' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ -2 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ -2 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ -2 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ -2 * $hd_ratio ] ), imagecolorat( $img_png, ( 32 * $hd_ratio - 1 ) - $i, 8 * $hd_ratio + $j ) ); $this->polygons[ 'head' ][ 'front' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 6 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ 6 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ 6 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ 6 * $hd_ratio ] ), imagecolorat( $img_png, 8 * $hd_ratio + $i, 8 * $hd_ratio + $j ) ); } } for ( $j = 0; $j < 8 * $hd_ratio; $j++ ) { for ( $k = -2 * $hd_ratio; $k < 6 * $hd_ratio; $k++ ) { $this->polygons[ 'head' ][ 'right' ][] = new Polygon( array( $volume_points[ 0 ][ $j ][ $k ], $volume_points[ 0 ][ $j ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, $k + 2 * $hd_ratio, 8 * $hd_ratio + $j ) ); $this->polygons[ 'head' ][ 'left' ][] = new Polygon( array( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ], $volume_points[ 8 * $hd_ratio ][ $j ][ $k + 1 ], $volume_points[ 8 * $hd_ratio ][ $j + 1 ][ $k + 1 ], $volume_points[ 8 * $hd_ratio ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, ( 24 * $hd_ratio - 1 ) - $k - 2 * $hd_ratio, 8 * $hd_ratio + $j ) ); } } for ( $i = 0; $i < 8 * $hd_ratio; $i++ ) { for ( $k = -2 * $hd_ratio; $k < 6 * $hd_ratio; $k++ ) { $this->polygons[ 'head' ][ 'top' ][] = new Polygon( array( $volume_points[ $i ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k + 1 ], $volume_points[ $i ][ 0 ][ $k + 1 ] ), imagecolorat( $img_png, 8 * $hd_ratio + $i, $k + 2 * $hd_ratio ) ); $this->polygons[ 'head' ][ 'bottom' ][] = new Polygon( array( $volume_points[ $i ][ 8 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 8 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 8 * $hd_ratio ][ $k + 1 ], $volume_points[ $i ][ 8 * $hd_ratio ][ $k + 1 ] ), imagecolorat( $img_png, 16 * $hd_ratio + $i, 2 * $hd_ratio + $k ) ); } } if ($this->display_hair) { // HELMET/HAIR $volume_points = array(); for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 9 * $hd_ratio; $j++ ) { if ( !isset( $volume_points[ $i ][ $j ][ -2 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ -2 * $hd_ratio ] = new Point( array( 'x' => $i * 9 / 8 - 0.5 * $hd_ratio, 'y' => $j * 9 / 8 - 0.5 * $hd_ratio, 'z' => -2.5 * $hd_ratio ) ); } if ( !isset( $volume_points[ $i ][ $j ][ 6 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ 6 * $hd_ratio ] = new Point( array( 'x' => $i * 9 / 8 - 0.5 * $hd_ratio, 'y' => $j * 9 / 8 - 0.5 * $hd_ratio, 'z' => 6.5 * $hd_ratio ) ); } } } for ( $j = 0; $j < 9 * $hd_ratio; $j++ ) { for ( $k = -2 * $hd_ratio; $k < 7 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ 0 ][ $j ][ $k ] ) ) { $volume_points[ 0 ][ $j ][ $k ] = new Point( array( 'x' => -0.5 * $hd_ratio, 'y' => $j * 9 / 8 - 0.5 * $hd_ratio, 'z' => $k * 9 / 8 - 0.5 * $hd_ratio ) ); } if ( !isset( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] ) ) { $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] = new Point( array( 'x' => 8.5 * $hd_ratio, 'y' => $j * 9 / 8 - 0.5 * $hd_ratio, 'z' => $k * 9 / 8 - 0.5 * $hd_ratio ) ); } } } for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $k = -2 * $hd_ratio; $k < 7 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ $i ][ 0 ][ $k ] ) ) { $volume_points[ $i ][ 0 ][ $k ] = new Point( array( 'x' => $i * 9 / 8 - 0.5 * $hd_ratio, 'y' => -0.5 * $hd_ratio, 'z' => $k * 9 / 8 - 0.5 * $hd_ratio ) ); } if ( !isset( $volume_points[ $i ][ 8 * $hd_ratio ][ $k ] ) ) { $volume_points[ $i ][ 8 * $hd_ratio ][ $k ] = new Point( array( 'x' => $i * 9 / 8 - 0.5 * $hd_ratio, 'y' => 8.5 * $hd_ratio, 'z' => $k * 9 / 8 - 0.5 * $hd_ratio ) ); } } } for ( $i = 0; $i < 8 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 8 * $hd_ratio; $j++ ) { $this->polygons[ 'helmet' ][ 'back' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ -2 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ -2 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ -2 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ -2 * $hd_ratio ] ), imagecolorat( $img_png, 32 * $hd_ratio + ( 32 * $hd_ratio - 1 ) - $i, 8 * $hd_ratio + $j ) ); $this->polygons[ 'helmet' ][ 'front' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 6 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ 6 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ 6 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ 6 * $hd_ratio ] ), imagecolorat( $img_png, 32 * $hd_ratio + 8 * $hd_ratio + $i, 8 * $hd_ratio + $j ) ); } } for ( $j = 0; $j < 8 * $hd_ratio; $j++ ) { for ( $k = -2 * $hd_ratio; $k < 6 * $hd_ratio; $k++ ) { $this->polygons[ 'helmet' ][ 'right' ][] = new Polygon( array( $volume_points[ 0 ][ $j ][ $k ], $volume_points[ 0 ][ $j ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, 32 * $hd_ratio + $k + 2 * $hd_ratio, 8 * $hd_ratio + $j ) ); $this->polygons[ 'helmet' ][ 'left' ][] = new Polygon( array( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ], $volume_points[ 8 * $hd_ratio ][ $j ][ $k + 1 ], $volume_points[ 8 * $hd_ratio ][ $j + 1 ][ $k + 1 ], $volume_points[ 8 * $hd_ratio ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, 32 * $hd_ratio + ( 24 * $hd_ratio - 1 ) - $k - 2 * $hd_ratio, 8 * $hd_ratio + $j ) ); } } for ( $i = 0; $i < 8 * $hd_ratio; $i++ ) { for ( $k = -2 * $hd_ratio; $k < 6 * $hd_ratio; $k++ ) { $this->polygons[ 'helmet' ][ 'top' ][] = new Polygon( array( $volume_points[ $i ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k + 1 ], $volume_points[ $i ][ 0 ][ $k + 1 ] ), imagecolorat( $img_png, 32 * $hd_ratio + 8 * $hd_ratio + $i, $k + 2 * $hd_ratio ) ); $this->polygons[ 'helmet' ][ 'bottom' ][] = new Polygon( array( $volume_points[ $i ][ 8 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 8 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 8 * $hd_ratio ][ $k + 1 ], $volume_points[ $i ][ 8 * $hd_ratio ][ $k + 1 ] ), imagecolorat( $img_png, 32 * $hd_ratio + 16 * $hd_ratio + $i, 2 * $hd_ratio + $k ) ); } } } if ( !$this->head_only ) { // TORSO $volume_points = array(); for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { if ( !isset( $volume_points[ $i ][ $j ][ 0 ] ) ) { $volume_points[ $i ][ $j ][ 0 ] = new Point( array( 'x' => $i, 'y' => $j + 8 * $hd_ratio, 'z' => 0 ) ); } if ( !isset( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] = new Point( array( 'x' => $i, 'y' => $j + 8 * $hd_ratio, 'z' => 4 * $hd_ratio ) ); } } } for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ 0 ][ $j ][ $k ] ) ) { $volume_points[ 0 ][ $j ][ $k ] = new Point( array( 'x' => 0, 'y' => $j + 8 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] ) ) { $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] = new Point( array( 'x' => 8 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ $i ][ 0 ][ $k ] ) ) { $volume_points[ $i ][ 0 ][ $k ] = new Point( array( 'x' => $i, 'y' => 0 + 8 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] ) ) { $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] = new Point( array( 'x' => $i, 'y' => 12 * $hd_ratio + 8 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 8 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { $this->polygons[ 'torso' ][ 'back' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j + 1 ][ 0 ], $volume_points[ $i ][ $j + 1 ][ 0 ] ), imagecolorat( $img_png, ( 40 * $hd_ratio - 1 ) - $i, 20 * $hd_ratio + $j ) ); $this->polygons[ 'torso' ][ 'front' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ 4 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ 4 * $hd_ratio ] ), imagecolorat( $img_png, 20 * $hd_ratio + $i, 20 * $hd_ratio + $j ) ); } } for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { $this->polygons[ 'torso' ][ 'right' ][] = new Polygon( array( $volume_points[ 0 ][ $j ][ $k ], $volume_points[ 0 ][ $j ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, 16 * $hd_ratio + $k, 20 * $hd_ratio + $j ) ); $this->polygons[ 'torso' ][ 'left' ][] = new Polygon( array( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ], $volume_points[ 8 * $hd_ratio ][ $j ][ $k + 1 ], $volume_points[ 8 * $hd_ratio ][ $j + 1 ][ $k + 1 ], $volume_points[ 8 * $hd_ratio ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, ( 32 * $hd_ratio - 1 ) - $k, 20 * $hd_ratio + $j ) ); } } for ( $i = 0; $i < 8 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { $this->polygons[ 'torso' ][ 'top' ][] = new Polygon( array( $volume_points[ $i ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k + 1 ], $volume_points[ $i ][ 0 ][ $k + 1 ] ), imagecolorat( $img_png, 20 * $hd_ratio + $i, 16 * $hd_ratio + $k ) ); $this->polygons[ 'torso' ][ 'bottom' ][] = new Polygon( array( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k + 1 ], $volume_points[ $i ][ 12 * $hd_ratio ][ $k + 1 ] ), imagecolorat( $img_png, 28 * $hd_ratio + $i, ( 20 * $hd_ratio - 1 ) - $k ) ); } } // RIGHT ARM $volume_points = array(); for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { if ( !isset( $volume_points[ $i ][ $j ][ 0 ] ) ) { $volume_points[ $i ][ $j ][ 0 ] = new Point( array( 'x' => $i - 4 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => 0 ) ); } if ( !isset( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] = new Point( array( 'x' => $i - 4 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => 4 * $hd_ratio ) ); } } } for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ 0 ][ $j ][ $k ] ) ) { $volume_points[ 0 ][ $j ][ $k ] = new Point( array( 'x' => 0 - 4 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] ) ) { $volume_points[ 4 * $hd_ratio ][ $j ][ $k ] = new Point( array( 'x' => 4 * $hd_ratio - 4 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ $i ][ 0 ][ $k ] ) ) { $volume_points[ $i ][ 0 ][ $k ] = new Point( array( 'x' => $i - 4 * $hd_ratio, 'y' => 0 + 8 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] ) ) { $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] = new Point( array( 'x' => $i - 4 * $hd_ratio, 'y' => 12 * $hd_ratio + 8 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { $this->polygons[ 'rightArm' ][ 'back' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j + 1 ][ 0 ], $volume_points[ $i ][ $j + 1 ][ 0 ] ), imagecolorat( $img_png, ( 56 * $hd_ratio - 1 ) - $i, 20 * $hd_ratio + $j ) ); $this->polygons[ 'rightArm' ][ 'front' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ 4 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ 4 * $hd_ratio ] ), imagecolorat( $img_png, 44 * $hd_ratio + $i, 20 * $hd_ratio + $j ) ); } } for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { $this->polygons[ 'rightArm' ][ 'right' ][] = new Polygon( array( $volume_points[ 0 ][ $j ][ $k ], $volume_points[ 0 ][ $j ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, 40 * $hd_ratio + $k, 20 * $hd_ratio + $j ) ); $this->polygons[ 'rightArm' ][ 'left' ][] = new Polygon( array( $volume_points[ 4 * $hd_ratio ][ $j ][ $k ], $volume_points[ 4 * $hd_ratio ][ $j ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, ( 52 * $hd_ratio - 1 ) - $k, 20 * $hd_ratio + $j ) ); } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { $this->polygons[ 'rightArm' ][ 'top' ][] = new Polygon( array( $volume_points[ $i ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k + 1 ], $volume_points[ $i ][ 0 ][ $k + 1 ] ), imagecolorat( $img_png, 44 * $hd_ratio + $i, 16 * $hd_ratio + $k ) ); $this->polygons[ 'rightArm' ][ 'bottom' ][] = new Polygon( array( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k + 1 ], $volume_points[ $i ][ 12 * $hd_ratio ][ $k + 1 ] ), imagecolorat( $img_png, 48 * $hd_ratio + $i, 16 * $hd_ratio + $k ) ); } } // LEFT ARM $volume_points = array(); for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { if ( !isset( $volume_points[ $i ][ $j ][ 0 ] ) ) { $volume_points[ $i ][ $j ][ 0 ] = new Point( array( 'x' => $i + 8 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => 0 ) ); } if ( !isset( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] = new Point( array( 'x' => $i + 8 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => 4 * $hd_ratio ) ); } } } for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ 0 ][ $j ][ $k ] ) ) { $volume_points[ 0 ][ $j ][ $k ] = new Point( array( 'x' => 0 + 8 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] ) ) { $volume_points[ 4 * $hd_ratio ][ $j ][ $k ] = new Point( array( 'x' => 4 * $hd_ratio + 8 * $hd_ratio, 'y' => $j + 8 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ $i ][ 0 ][ $k ] ) ) { $volume_points[ $i ][ 0 ][ $k ] = new Point( array( 'x' => $i + 8 * $hd_ratio, 'y' => 0 + 8 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] ) ) { $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] = new Point( array( 'x' => $i + 8 * $hd_ratio, 'y' => 12 * $hd_ratio + 8 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { if($this->isNewSkinType) { $color1 = imagecolorat( $img_png, 47 * $hd_ratio - $i, 52 * $hd_ratio + $j ); // from right to left $color2 = imagecolorat( $img_png, 36 * $hd_ratio + $i , 52 * $hd_ratio + $j ); // from left to right } else { $color1 = imagecolorat( $img_png, ( 56 * $hd_ratio - 1 ) - ( ( 4 * $hd_ratio - 1 ) - $i ), 20 * $hd_ratio + $j ); $color2 = imagecolorat( $img_png, 44 * $hd_ratio + ( ( 4 * $hd_ratio - 1 ) - $i ), 20 * $hd_ratio + $j ); } $this->polygons[ 'leftArm' ][ 'back' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j + 1 ][ 0 ], $volume_points[ $i ][ $j + 1 ][ 0 ] ), $color1 ); $this->polygons[ 'leftArm' ][ 'front' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ 4 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ 4 * $hd_ratio ] ), $color2 ); } } for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { if($this->isNewSkinType) { $color1 = imagecolorat( $img_png, 32 * $hd_ratio + $k, 52 * $hd_ratio + $j ); // from left to right $color2 = imagecolorat( $img_png, 43 * $hd_ratio - $k, 52 * $hd_ratio + $j ); // from right to left } else { $color1 = imagecolorat( $img_png, 40 * $hd_ratio + ( ( 4 * $hd_ratio - 1 ) - $k ), 20 * $hd_ratio + $j ); $color2 = imagecolorat( $img_png, ( 52 * $hd_ratio - 1 ) - ( ( 4 * $hd_ratio - 1 ) - $k ), 20 * $hd_ratio + $j ); } $this->polygons[ 'leftArm' ][ 'right' ][] = new Polygon( array( $volume_points[ 0 ][ $j ][ $k ], $volume_points[ 0 ][ $j ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k ] ), $color1 ); $this->polygons[ 'leftArm' ][ 'left' ][] = new Polygon( array( $volume_points[ 4 * $hd_ratio ][ $j ][ $k ], $volume_points[ 4 * $hd_ratio ][ $j ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k ] ), $color2 ); } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { if($this->isNewSkinType) { $color1 = imagecolorat( $img_png, 36 * $hd_ratio + $i, 48 * $hd_ratio + $k ); // from left to right $color2 = imagecolorat( $img_png, 40 * $hd_ratio + $i, 48 * $hd_ratio + $k ); // from left to right } else { $color1 = imagecolorat( $img_png, 44 * $hd_ratio + ( ( 4 * $hd_ratio - 1 ) - $i ), 16 * $hd_ratio + $k ); $color2 = imagecolorat( $img_png, 48 * $hd_ratio + ( ( 4 * $hd_ratio - 1 ) - $i ), ( 20 * $hd_ratio - 1 ) - $k ); } $this->polygons[ 'leftArm' ][ 'top' ][] = new Polygon( array( $volume_points[ $i ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k + 1 ], $volume_points[ $i ][ 0 ][ $k + 1 ] ), $color1 ); $this->polygons[ 'leftArm' ][ 'bottom' ][] = new Polygon( array( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k + 1 ], $volume_points[ $i ][ 12 * $hd_ratio ][ $k + 1 ] ), $color2 ); } } // RIGHT LEG $volume_points = array(); for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { if ( !isset( $volume_points[ $i ][ $j ][ 0 ] ) ) { $volume_points[ $i ][ $j ][ 0 ] = new Point( array( 'x' => $i, 'y' => $j + 20 * $hd_ratio, 'z' => 0 ) ); } if ( !isset( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] = new Point( array( 'x' => $i, 'y' => $j + 20 * $hd_ratio, 'z' => 4 * $hd_ratio ) ); } } } for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ 0 ][ $j ][ $k ] ) ) { $volume_points[ 0 ][ $j ][ $k ] = new Point( array( 'x' => 0, 'y' => $j + 20 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] ) ) { $volume_points[ 4 * $hd_ratio ][ $j ][ $k ] = new Point( array( 'x' => 4 * $hd_ratio, 'y' => $j + 20 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ $i ][ 0 ][ $k ] ) ) { $volume_points[ $i ][ 0 ][ $k ] = new Point( array( 'x' => $i, 'y' => 0 + 20 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] ) ) { $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] = new Point( array( 'x' => $i, 'y' => 12 * $hd_ratio + 20 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { $this->polygons[ 'rightLeg' ][ 'back' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j + 1 ][ 0 ], $volume_points[ $i ][ $j + 1 ][ 0 ] ), imagecolorat( $img_png, ( 16 * $hd_ratio - 1 ) - $i, 20 * $hd_ratio + $j ) ); $this->polygons[ 'rightLeg' ][ 'front' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ 4 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ 4 * $hd_ratio ] ), imagecolorat( $img_png, 4 * $hd_ratio + $i, 20 * $hd_ratio + $j ) ); } } for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { $this->polygons[ 'rightLeg' ][ 'right' ][] = new Polygon( array( $volume_points[ 0 ][ $j ][ $k ], $volume_points[ 0 ][ $j ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, 0 + $k, 20 * $hd_ratio + $j ) ); $this->polygons[ 'rightLeg' ][ 'left' ][] = new Polygon( array( $volume_points[ 4 * $hd_ratio ][ $j ][ $k ], $volume_points[ 4 * $hd_ratio ][ $j ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k ] ), imagecolorat( $img_png, ( 12 * $hd_ratio - 1 ) - $k, 20 * $hd_ratio + $j ) ); } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { $this->polygons[ 'rightLeg' ][ 'top' ][] = new Polygon( array( $volume_points[ $i ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k + 1 ], $volume_points[ $i ][ 0 ][ $k + 1 ] ), imagecolorat( $img_png, 4 * $hd_ratio + $i, 16 * $hd_ratio + $k ) ); $this->polygons[ 'rightLeg' ][ 'bottom' ][] = new Polygon( array( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k + 1 ], $volume_points[ $i ][ 12 * $hd_ratio ][ $k + 1 ] ), imagecolorat( $img_png, 8 * $hd_ratio + $i, 16 * $hd_ratio + $k ) ); } } // LEFT LEG $volume_points = array(); for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { if ( !isset( $volume_points[ $i ][ $j ][ 0 ] ) ) { $volume_points[ $i ][ $j ][ 0 ] = new Point( array( 'x' => $i + 4 * $hd_ratio, 'y' => $j + 20 * $hd_ratio, 'z' => 0 ) ); } if ( !isset( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] ) ) { $volume_points[ $i ][ $j ][ 4 * $hd_ratio ] = new Point( array( 'x' => $i + 4 * $hd_ratio, 'y' => $j + 20 * $hd_ratio, 'z' => 4 * $hd_ratio ) ); } } } for ( $j = 0; $j < 13 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ 0 ][ $j ][ $k ] ) ) { $volume_points[ 0 ][ $j ][ $k ] = new Point( array( 'x' => 0 + 4 * $hd_ratio, 'y' => $j + 20 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ 8 * $hd_ratio ][ $j ][ $k ] ) ) { $volume_points[ 4 * $hd_ratio ][ $j ][ $k ] = new Point( array( 'x' => 4 * $hd_ratio + 4 * $hd_ratio, 'y' => $j + 20 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 9 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 5 * $hd_ratio; $k++ ) { if ( !isset( $volume_points[ $i ][ 0 ][ $k ] ) ) { $volume_points[ $i ][ 0 ][ $k ] = new Point( array( 'x' => $i + 4 * $hd_ratio, 'y' => 0 + 20 * $hd_ratio, 'z' => $k ) ); } if ( !isset( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] ) ) { $volume_points[ $i ][ 12 * $hd_ratio ][ $k ] = new Point( array( 'x' => $i + 4 * $hd_ratio, 'y' => 12 * $hd_ratio + 20 * $hd_ratio, 'z' => $k ) ); } } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { if($this->isNewSkinType) { $color1 = imagecolorat( $img_png, 31 * $hd_ratio - $i, 52 * $hd_ratio + $j ); // from right to left $color2 = imagecolorat( $img_png, 20 * $hd_ratio + $i , 52 * $hd_ratio + $j ); // from left to right } else { $color1 = imagecolorat( $img_png, ( 16 * $hd_ratio - 1 ) - ( ( 4 * $hd_ratio - 1 ) - $i ), 20 * $hd_ratio + $j ); $color2 = imagecolorat( $img_png, 4 * $hd_ratio + ( ( 4 * $hd_ratio - 1 ) - $i ), 20 * $hd_ratio + $j ); } $this->polygons[ 'leftLeg' ][ 'back' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j ][ 0 ], $volume_points[ $i + 1 ][ $j + 1 ][ 0 ], $volume_points[ $i ][ $j + 1 ][ 0 ] ), $color1 ); $this->polygons[ 'leftLeg' ][ 'front' ][] = new Polygon( array( $volume_points[ $i ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j ][ 4 * $hd_ratio ], $volume_points[ $i + 1 ][ $j + 1 ][ 4 * $hd_ratio ], $volume_points[ $i ][ $j + 1 ][ 4 * $hd_ratio ] ), $color2 ); } } for ( $j = 0; $j < 12 * $hd_ratio; $j++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { if($this->isNewSkinType) { $color1 = imagecolorat( $img_png, 16 * $hd_ratio + $k , 52 * $hd_ratio + $j ); // from left to right $color2 = imagecolorat( $img_png, 27 * $hd_ratio - $k , 52 * $hd_ratio + $j ); // from right to left } else { $color1 = imagecolorat( $img_png, 0 + ( ( 4 * $hd_ratio - 1 ) - $k ), 20 * $hd_ratio + $j ); $color2 = imagecolorat( $img_png, ( 12 * $hd_ratio - 1 ) - ( ( 4 * $hd_ratio - 1 ) - $k ), 20 * $hd_ratio + $j ); } $this->polygons[ 'leftLeg' ][ 'right' ][] = new Polygon( array( $volume_points[ 0 ][ $j ][ $k ], $volume_points[ 0 ][ $j ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k + 1 ], $volume_points[ 0 ][ $j + 1 ][ $k ] ), $color1 ); $this->polygons[ 'leftLeg' ][ 'left' ][] = new Polygon( array( $volume_points[ 4 * $hd_ratio ][ $j ][ $k ], $volume_points[ 4 * $hd_ratio ][ $j ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k + 1 ], $volume_points[ 4 * $hd_ratio ][ $j + 1 ][ $k ] ), $color2 ); } } for ( $i = 0; $i < 4 * $hd_ratio; $i++ ) { for ( $k = 0; $k < 4 * $hd_ratio; $k++ ) { if($this->isNewSkinType) { $color1 = imagecolorat( $img_png, 20 * $hd_ratio + $i , 48 * $hd_ratio + $k ); // from left to right $color2 = imagecolorat( $img_png, 24 * $hd_ratio + $i , 48 * $hd_ratio + $k ); // from left to right } else { $color1 = imagecolorat( $img_png, 4 * $hd_ratio + ( ( 4 * $hd_ratio - 1 ) - $i ), 16 * $hd_ratio + $k ); $color2 = imagecolorat( $img_png, 8 * $hd_ratio + ( ( 4 * $hd_ratio - 1 ) - $i ), ( 20 * $hd_ratio - 1 ) - $k ); } $this->polygons[ 'leftLeg' ][ 'top' ][] = new Polygon( array( $volume_points[ $i ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k ], $volume_points[ $i + 1 ][ 0 ][ $k + 1 ], $volume_points[ $i ][ 0 ][ $k + 1 ] ), $color1 ); $this->polygons[ 'leftLeg' ][ 'bottom' ][] = new Polygon( array( $volume_points[ $i ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k ], $volume_points[ $i + 1 ][ 12 * $hd_ratio ][ $k + 1 ], $volume_points[ $i ][ 12 * $hd_ratio ][ $k + 1 ] ), $color2 ); } } } } /* Function rotates members * */ private function memberRotation() { foreach ($this->polygons['head'] as $face ) { foreach ( $face as $poly ) { $poly->preProject( 4, 8, 2, $this->members_angles[ 'head' ][ 'cos_alpha' ], $this->members_angles[ 'head' ][ 'sin_alpha' ], $this->members_angles[ 'head' ][ 'cos_omega' ], $this->members_angles[ 'head' ][ 'sin_omega' ] ); } } if ($this->display_hair) { foreach ( $this->polygons[ 'helmet' ] as $face ) { foreach ( $face as $poly ) { $poly->preProject( 4, 8, 2, $this->members_angles[ 'head' ][ 'cos_alpha' ], $this->members_angles[ 'head' ][ 'sin_alpha' ], $this->members_angles[ 'head' ][ 'cos_omega' ], $this->members_angles[ 'head' ][ 'sin_omega' ] ); } } } if (!$this->head_only) { foreach ( $this->polygons[ 'rightArm' ] as $face ) { foreach ( $face as $poly ) { $poly->preProject( -2, 8, 2, $this->members_angles[ 'rightArm' ][ 'cos_alpha' ], $this->members_angles[ 'rightArm' ][ 'sin_alpha' ], $this->members_angles[ 'rightArm' ][ 'cos_omega' ], $this->members_angles[ 'rightArm' ][ 'sin_omega' ] ); } } foreach ( $this->polygons[ 'leftArm' ] as $face ) { foreach ( $face as $poly ) { $poly->preProject( 10, 8, 2, $this->members_angles[ 'leftArm' ][ 'cos_alpha' ], $this->members_angles[ 'leftArm' ][ 'sin_alpha' ], $this->members_angles[ 'leftArm' ][ 'cos_omega' ], $this->members_angles[ 'leftArm' ][ 'sin_omega' ] ); } } foreach ( $this->polygons[ 'rightLeg' ] as $face ) { foreach ( $face as $poly ) { $poly->preProject( 2, 20, ( $this->members_angles[ 'rightLeg' ][ 'sin_alpha' ] < 0 ? 0 : 4 ), $this->members_angles[ 'rightLeg' ][ 'cos_alpha' ], $this->members_angles[ 'rightLeg' ][ 'sin_alpha' ], $this->members_angles[ 'rightLeg' ][ 'cos_omega' ], $this->members_angles[ 'rightLeg' ][ 'sin_omega' ] ); } } foreach ( $this->polygons[ 'leftLeg' ] as $face ) { foreach ( $face as $poly ) { $poly->preProject( 6, 20, ( $this->members_angles[ 'leftLeg' ][ 'sin_alpha' ] < 0 ? 0 : 4 ), $this->members_angles[ 'leftLeg' ][ 'cos_alpha' ], $this->members_angles[ 'leftLeg' ][ 'sin_alpha' ], $this->members_angles[ 'leftLeg' ][ 'cos_omega' ], $this->members_angles[ 'leftLeg' ][ 'sin_omega' ] ); } } } } /* Create projection plan * */ private function createProjectionPlan() { foreach ($this->polygons as $piece) { foreach ($piece as $face) { foreach ($face as $poly) { if (!$poly->isProjected()) { $poly->project(); } } } } } /* Function displays the image * */ private function displayImage($output) { global $minX, $maxX, $minY, $maxY; global $seconds_to_cache; $width = $maxX - $minX; $height = $maxY - $minY; $ratio = $this->ratio; if ( $ratio < 2 ) { $ratio = 2; } if($this->aa === true) { // double the ration for downscaling later (sort of AA) $ratio = $ratio * 2; } if ($seconds_to_cache > 0) { $ts = gmdate( "D, d M Y H:i:s", time() + $seconds_to_cache ) . ' GMT'; if($output != 'return') { header( 'Expires: ' . $ts ); header( 'Pragma: cache' ); header( 'Cache-Control: max-age=' . $seconds_to_cache ); } } if ($this->format != 'svg') { $srcWidth = $ratio * $width + 1; $srcHeight = $ratio * $height + 1; $realWidth = $srcWidth / 2; $realHeight = $srcHeight / 2; $image = img::createEmptyCanvas($srcWidth, $srcHeight); } $display_order = $this->getDisplayOrder(); $imgOutput = ''; if($this->format == 'svg') { $imgOutput .= ''; } foreach ($display_order as $pieces) { foreach ($pieces as $piece => $faces) { foreach ($faces as $face) { foreach ($this->polygons[$piece][$face] as $poly) { if ($this->format == 'svg') { $imgOutput .= $poly->getSvgPolygon(1); } else { $poly->addPngPolygon($image, $minX, $minY, $ratio); } } } } } if($this->format == 'svg') { $imgOutput .= ''; } if ($this->format !== 'svg') { if($this->aa === true) { // image normal size (sort of AA). // resize the image down to it's normal size so it will be smoother $destImage = img::createEmptyCanvas($realWidth, $realHeight); imagecopyresampled($destImage, $image, 0, 0, 0, 0, $realWidth, $realHeight, $srcWidth, $srcHeight); $image = $destImage; } $imgData = null; if($this->format == 'base64') { // output png;base64 ob_start(); imagepng($image); $imgData = ob_get_contents(); ob_end_clean(); } else { $imgOutput = $image; } if($imgData !== null) { $imgOutput = base64_encode($imgData); imagedestroy($image); } } return $imgOutput; } /* Function retuns display order * */ private function getDisplayOrder() { $display_order = array(); if ( in_array( 'top', $this->front_faces ) ) { if ( in_array( 'right', $this->front_faces ) ) { $display_order[] = array('leftLeg' => $this->back_faces); $display_order[] = array('leftLeg' => $this->visible_faces['leftLeg']['front']); $display_order[] = array('rightLeg' => $this->back_faces); $display_order[] = array('rightLeg' => $this->visible_faces['rightLeg']['front']); $display_order[] = array('leftArm' => $this->back_faces); $display_order[] = array('leftArm' => $this->visible_faces['leftArm']['front']); $display_order[] = array('torso' => $this->back_faces); $display_order[] = array('torso' => $this->visible_faces['torso']['front']); $display_order[] = array('rightArm' => $this->back_faces); $display_order[] = array('rightArm' => $this->visible_faces['rightArm']['front']); } else { $display_order[] = array('rightLeg' => $this->back_faces); $display_order[] = array('rightLeg' => $this->visible_faces['rightLeg' ]['front']); $display_order[] = array('leftLeg' => $this->back_faces); $display_order[] = array('leftLeg' => $this->visible_faces['leftLeg']['front']); $display_order[] = array('rightArm' => $this->back_faces); $display_order[] = array('rightArm' => $this->visible_faces['rightArm']['front']); $display_order[] = array('torso' => $this->back_faces); $display_order[] = array('torso' => $this->visible_faces['torso']['front']); $display_order[] = array('leftArm' => $this->back_faces); $display_order[] = array('leftArm' => $this->visible_faces['leftArm']['front']); } $display_order[] = array('helmet' => $this->back_faces); $display_order[] = array('head' => $this->back_faces); $display_order[] = array('head' => $this->visible_faces['head']['front']); $display_order[] = array('helmet' => $this->visible_faces['head']['front']); } else { $display_order[] = array('helmet' => $this->back_faces); $display_order[] = array('head' => $this->back_faces); $display_order[] = array('head' => $this->visible_faces['head']['front']); $display_order[] = array('helmet' => $this->visible_faces['head']['front']); if ( in_array( 'right', $this->front_faces ) ) { $display_order[] = array('leftArm' => $this->back_faces); $display_order[] = array('leftArm' => $this->visible_faces['leftArm']['front']); $display_order[] = array('torso' => $this->back_faces); $display_order[] = array('torso' => $this->visible_faces['torso']['front']); $display_order[] = array('rightArm' => $this->back_faces); $display_order[] = array('rightArm' => $this->visible_faces['rightArm']['front']); $display_order[] = array('leftLeg' => $this->back_faces); $display_order[] = array('leftLeg' => $this->visible_faces['leftLeg' ]['front']); $display_order[] = array('rightLeg' => $this->back_faces); $display_order[] = array('rightLeg' => $this->visible_faces['rightLeg']['front']); } else { $display_order[] = array('rightArm' => $this->back_faces); $display_order[] = array('rightArm' => $this->visible_faces['rightArm']['front']); $display_order[] = array('torso' => $this->back_faces); $display_order[] = array('torso' => $this->visible_faces['torso']['front']); $display_order[] = array('leftArm' => $this->back_faces); $display_order[] = array('leftArm' => $this->visible_faces['leftArm']['front']); $display_order[] = array('rightLeg' => $this->back_faces); $display_order[] = array('rightLeg' => $this->visible_faces['rightLeg']['front']); $display_order[] = array('leftLeg' => $this->back_faces); $display_order[] = array('leftLeg' => $this->visible_faces['leftLeg']['front']); } } return $display_order; } } /* Img class * * Handels image related things */ class img { private function __construct() { } /* Function creates a blank canvas * with transparancy with the size of the * given image. * * Espects canvas with and canvast height. * Returns a empty canvas. */ public static function createEmptyCanvas($w, $h) { $dst = imagecreatetruecolor($w, $h); imagesavealpha($dst, true); $trans_colour = imagecolorallocatealpha($dst, 255, 255, 255, 127); imagefill($dst, 0, 0, $trans_colour); return $dst; } /* Function converts a non true color image to * true color. This fixes the dark blue skins. * * Espects an image. * Returns a true color image. */ public static function convertToTrueColor($img) { if(imageistruecolor($img)) { return $img; } $dst = img::createEmptyCanvas(imagesx($img), imagesy($img)); imagecopy($dst, $img, 0, 0, 0, 0, imagesx($img), imagesy($img)); imagedestroy($img); return $dst; } } /* Point Class * */ class Point { private $_originCoord; private $_destCoord = array(); private $_isProjected = false; private $_isPreProjected = false; public function __construct( $originCoord ) { if ( is_array( $originCoord ) && count( $originCoord ) == 3 ) { $this->_originCoord = array( 'x' => ( isset( $originCoord[ 'x' ] ) ? $originCoord[ 'x' ] : 0 ), 'y' => ( isset( $originCoord[ 'y' ] ) ? $originCoord[ 'y' ] : 0 ), 'z' => ( isset( $originCoord[ 'z' ] ) ? $originCoord[ 'z' ] : 0 ) ); } else { $this->_originCoord = array( 'x' => 0, 'y' => 0, 'z' => 0 ); } } public function project() { global $cos_alpha, $sin_alpha, $cos_omega, $sin_omega; global $minX, $maxX, $minY, $maxY; // 1, 0, 1, 0 $x = $this->_originCoord['x']; $y = $this->_originCoord['y']; $z = $this->_originCoord['z']; $this->_destCoord['x'] = $x * $cos_omega + $z * $sin_omega; $this->_destCoord['y'] = $x * $sin_alpha * $sin_omega + $y * $cos_alpha - $z * $sin_alpha * $cos_omega; $this->_destCoord['z'] = -$x * $cos_alpha * $sin_omega + $y * $sin_alpha + $z * $cos_alpha * $cos_omega; $this->_isProjected = true; $minX = min($minX, $this->_destCoord['x']); $maxX = max($maxX, $this->_destCoord['x']); $minY = min($minY, $this->_destCoord['y']); $maxY = max($maxY, $this->_destCoord['y']); } public function preProject( $dx, $dy, $dz, $cos_alpha, $sin_alpha, $cos_omega, $sin_omega ) { if ( !$this->_isPreProjected ) { $x = $this->_originCoord[ 'x' ] - $dx; $y = $this->_originCoord[ 'y' ] - $dy; $z = $this->_originCoord[ 'z' ] - $dz; $this->_originCoord[ 'x' ] = $x * $cos_omega + $z * $sin_omega + $dx; $this->_originCoord[ 'y' ] = $x * $sin_alpha * $sin_omega + $y * $cos_alpha - $z * $sin_alpha * $cos_omega + $dy; $this->_originCoord[ 'z' ] = -$x * $cos_alpha * $sin_omega + $y * $sin_alpha + $z * $cos_alpha * $cos_omega + $dz; $this->_isPreProjected = true; } } public function getOriginCoord() { return $this->_originCoord; } public function getDestCoord() { return $this->_destCoord; } public function getDepth() { if ( !$this->_isProjected ) { $this->project(); } return $this->_destCoord[ 'z' ]; } public function isProjected() { return $this->_isProjected; } } /* Polygon Class * */ class Polygon { private $_dots; private $_colour; private $_isProjected = false; private $_face = 'w'; private $_faceDepth = 0; public function __construct( $dots, $colour ) { $this->_dots = $dots; $this->_colour = $colour; $coord_0 = $dots[ 0 ]->getOriginCoord(); $coord_1 = $dots[ 1 ]->getOriginCoord(); $coord_2 = $dots[ 2 ]->getOriginCoord(); if ( $coord_0[ 'x' ] == $coord_1[ 'x' ] && $coord_1[ 'x' ] == $coord_2[ 'x' ] ) { $this->_face = 'x'; $this->_faceDepth = $coord_0[ 'x' ]; } else if ( $coord_0[ 'y' ] == $coord_1[ 'y' ] && $coord_1[ 'y' ] == $coord_2[ 'y' ] ) { $this->_face = 'y'; $this->_faceDepth = $coord_0[ 'y' ]; } else if ( $coord_0[ 'z' ] == $coord_1[ 'z' ] && $coord_1[ 'z' ] == $coord_2[ 'z' ] ) { $this->_face = 'z'; $this->_faceDepth = $coord_0[ 'z' ]; } } // never used private function getFace() { return $this->_face; } // never used private function getFaceDepth() { if ( !$this->_isProjected ) { $this->project(); } return $this->_faceDepth; } public function getSvgPolygon( $ratio ) { $points_2d = ''; $r = ( $this->_colour >> 16 ) & 0xFF; $g = ( $this->_colour >> 8 ) & 0xFF; $b = $this->_colour & 0xFF; $vR = ( 127 - ( ( $this->_colour & 0x7F000000 ) >> 24 ) ) / 127; if ( $vR == 0 ) return ''; foreach ( $this->_dots as $dot ) { $coord = $dot->getDestCoord(); $points_2d .= $coord[ 'x' ] * $ratio . ',' . $coord[ 'y' ] * $ratio . ' '; } $comment = ''; return $comment . '' . "\n"; } public function addPngPolygon( &$image, $minX, $minY, $ratio ) { $points_2d = array(); $nb_points = 0; $r = ( $this->_colour >> 16 ) & 0xFF; $g = ( $this->_colour >> 8 ) & 0xFF; $b = $this->_colour & 0xFF; $vR = ( 127 - ( ( $this->_colour & 0x7F000000 ) >> 24 ) ) / 127; if ( $vR == 0 ) return; $same_plan_x = true; $same_plan_y = true; foreach ( $this->_dots as $dot ) { $coord = $dot->getDestCoord(); if ( !isset( $coord_x ) ) $coord_x = $coord[ 'x' ]; if ( !isset( $coord_y ) ) $coord_y = $coord[ 'y' ]; if ( $coord_x != $coord[ 'x' ] ) $same_plan_x = false; if ( $coord_y != $coord[ 'y' ] ) $same_plan_y = false; $points_2d[] = ( $coord[ 'x' ] - $minX ) * $ratio; $points_2d[] = ( $coord[ 'y' ] - $minY ) * $ratio; $nb_points++; } if ( !( $same_plan_x || $same_plan_y ) ) { $colour = imagecolorallocate( $image, $r, $g, $b ); imagefilledpolygon( $image, $points_2d, $nb_points, $colour ); } } public function isProjected() { return $this->_isProjected; } public function project() { foreach ( $this->_dots as &$dot ) { if ( !$dot->isProjected() ) { $dot->project(); } } $this->_isProjected = true; } public function preProject( $dx, $dy, $dz, $cos_alpha, $sin_alpha, $cos_omega, $sin_omega ) { foreach ( $this->_dots as &$dot ) { $dot->preProject( $dx, $dy, $dz, $cos_alpha, $sin_alpha, $cos_omega, $sin_omega ); } } } ?>