From 12f8ebe01638b1425c96bb7ba11af5ffa926853a Mon Sep 17 00:00:00 2001 From: yuanjiajia <1139393632@qq.com> Date: Wed, 18 May 2022 19:33:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=B2=E7=BB=8F=E4=BF=AE=E5=A4=8D=E8=BD=ACgl?= =?UTF-8?q?tf=E6=A8=A1=E5=9E=8B=E6=97=B6=E4=B8=8D=E8=83=BD=E8=BD=AC?= =?UTF-8?q?=E5=A4=A7=E6=A8=A1=E5=9E=8B=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/loadObjDemo.php | 14 +--- src/core/LoardObj.php | 154 +++++++++++++++++++++++---------------- 2 files changed, 94 insertions(+), 74 deletions(-) diff --git a/examples/loadObjDemo.php b/examples/loadObjDemo.php index 9c1429b..d660a3c 100644 --- a/examples/loadObjDemo.php +++ b/examples/loadObjDemo.php @@ -6,17 +6,11 @@ namespace Blobt\Luxcore\core; use Blobt\Luxcore\core\LoardObj; include dirname(dirname(__FILE__)) . "/vendor/autoload.php"; - ini_set('memory_limit','4096M'); -$ply = new LoardObj('/home/yuanjiajia/Desktop/blender/test/6D.obj'); -$ply = $ply->toGltf(); -var_dump( $ply ); - -// $UUII = base64_decode("AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA="); - -// $finfo = new \finfo(FILEINFO_MIME); - -// echo $finfo->buffer($UUII) . "\n"; +$transform = new LoardObj('/home/yuanjiajia/Desktop/blender/test/椅子.obj'); +$transform->toGltf(); +$transform = $transform->toPly(); +var_dump( $transform ); ?> diff --git a/src/core/LoardObj.php b/src/core/LoardObj.php index 92901be..31a662c 100644 --- a/src/core/LoardObj.php +++ b/src/core/LoardObj.php @@ -10,39 +10,51 @@ class LoardObj const OPEN = true; const CLOSE = false; + + + /** * @var string $objFile obj文件路径 */ - public $objFile; + private $objFile; /** * @var array 储存obj模型数据 */ - public $objData = []; + private $objData = [ + 'v' => [], // 顶点坐标数据,每行存储一个描述顶点xyz坐标的数组; + 'vt' => [], // UV坐标数据,每行存储一个描述顶点 UV 坐标的数组; + 'vn' => [], // 顶点法线数据,每行存储一个描述顶点xyz法线的数组; + 'f' => [], // 面片数据,每行数据是对顶点坐标、顶点法线及UV坐标的素引。 + ]; /** - * @var array 储存ply模型数据 + * @var array 1、储存ply模型数据,Ply文件头部数据(内容包括顶点数据、面数据、线数据、材质数据或其他数据的格式及属性) + * 2、顶点数据,每行数据描述了顶点的坐标、法线、及UV坐标; + * 3、索引顶点数据,每行数据描述了索引顶点的个数,及顶点数据的素引。 */ - public $plyData = []; + private $plyData = []; /** * @var array 储存gltf模型数据 */ - public $gltfData = [ - 'asset' => '{ "version" : "2.0" }', - 'scene' => 0, - 'scenes' => [], - 'nodes' => [], - 'cameras' => [], - 'skins' => [], - 'meshes' => [], - 'accessors' => [], - 'bufferViews' => [], - 'buffers' => [], - 'material' => [], - 'textures' => [], - 'images' => [], - 'samplers' => [] + private $gltfData = [ + 'asset' => '{}', // 用这个对象{},标识这是一个gltf文件,并说明其文件版本规范 + 'scene' => 0, // 用一个整数标识加载一个默认的场景 + 'scenes' => [], // 1、场景数组,解析一个gltf文件将从这里开始; + // 2、每一个元素值是一个对象类型,每一个对象描述了对 nodes数组 的元素索引,同时也是每一个场景的根节点; + 'nodes' => [], // 节点数组,每一个元素值是一个对象类型,每一个对象描述一个 mesh(模型)、camera()或skin(蒙皮) + // 数组的元素索引; + 'cameras' => [], // 相机数组,每一个元素值是一个对象类型,每一个对象是对一个相机的描述; + 'skins' => [], // 蒙皮数组,每一个元素值是一个对象类型,每一个对象是对一个蒙皮的描述; + 'meshes' => [], // 模型数组,每一个元素值是一个对象类型,每一个对象是对一个模型的描述; + 'accessors' => [], // 访问器数组,每一个元素是一个对象类型,每一个对象描一段数据的格式或属性; + 'bufferViews' => [], // 数据视图数组,每一个元素是一个对象类型,每一个对象描述一段切割数据的属性及用途; + 'buffers' => [], // 缓存器数组,每一个元素是一个对象类型,每一个对象描述一个Base64编码的二进制数据缓存; + 'material' => [], // 材质数组,每一个元素值是一个对象类型,每一个对象是对一个材质的描述; + 'textures' => [], // 纹理数组,每一个元素值是一个对象类型,每一个对象是对一个纹理的描述; + 'images' => [], // 图像数组,每一个元素值是一个对象类型,每一个对象是对一个图像的描述; + 'samplers' => [] // 图像采样数组,每一个元素值是一个对象类型,每一个对象是对一个图像的描述。 ]; @@ -75,11 +87,11 @@ class LoardObj * @param string $path ply模型 保存路径 * @param string $format ply模型 保存格式 */ - public function toGltf( string $path = null,string $format = self::TYPE_BINARY) + public function toGltf( string $path = null) { $this->createGltf(); if( $path == null) $path = getcwd()."/gltf"; - return $this->writeGltf( $path, $format ); + return $this->writeGltf( $path ); } @@ -258,7 +270,7 @@ class LoardObj } /** - * 利用已经拆分的 obj 模型数据,生成多个 gltf 模型,并将这些模型储存在 gltfData 数组中 + * 利用已经拆分的 obj 模型数据,生成 gltf 模型,并将这些模型数据储存在 gltfData 数组中 */ private function createGltf() { @@ -277,23 +289,30 @@ class LoardObj $animation = null; $meshCount = 0; $bufferCount = 0; - $maxX = -10000000; - $maxY = -10000000; - $maxZ = -10000000; - $minX = 10000000; - $minY = 10000000; - $minZ = 10000000; + $maxX = -100000000; + $maxY = -100000000; + $maxZ = -100000000; + $minX = 100000000; + $minY = 100000000; + $minZ = 100000000; + foreach( $this->objData['meshs'] as $meshs_key => $meshs_value ) { - $lineFace = null; - $v = null; - $vt = null; - $vn = null; - $byteOffset = 0; - foreach( $meshs_value as $face_value ) // 生成顶点和面数据 + $gltf['v'] = null; + $gltf['vt'] = null; + $gltf['vn'] = null; + $gltf['face'] = null; + $indexesList = []; + $vConst = 0; + foreach( $meshs_value as $face_value ) { + // 生成顶点和面数据 $face_value = implode('/', $face_value); $face_value = explode('/', $face_value); + $lineFace = []; + $v = null; + $vt = null; + $vn = null; foreach( $face_value as $v_key => $v_value ) { switch( ($v_key+1) % 3 ) @@ -319,30 +338,31 @@ class LoardObj default: ; } - $v .= pack('g',(float)$xyz_value); } - $lineFace .= pack('V',((int)$v_value) - 1); + $v = $this->objData['v'][$v_value-1]; break; case 2: - if( $v_value == null ) - { - $vt .= pack('g',(float)0.0000); - $vt .= pack('g',(float)0.0000); - } - else - { - foreach(array_slice($this->objData['vt'][$v_value-1],0,2) as $t_value) - { - $vt .= pack('g',(float)$t_value); - } - } + if( $v_value == null ) $vt = ['0.0000','0.0000']; + else $vt = array_slice($this->objData['vt'][$v_value-1],0,2); break; case 0; - foreach($this->objData['vn'][$v_value-1] as $n_value) + $vn = $this->objData['vn'][$v_value-1]; + $hashVar = implode(' ',$v).' '.implode(' ',$vn).' '.implode(' ',$vt); + $hashVar = hash('md5', $hashVar); + if( !array_key_exists($hashVar, $indexesList) ) { - $vn .= pack('g',(float)$n_value); + foreach( $v as $valueP ) $gltf['v'] .= pack('g',(float)$valueP); + foreach( $vt as $valueT ) $gltf['vt'] .= pack('g',(float)$valueT); + foreach( $vn as $valueN ) $gltf['vn'] .= pack('g',(float)$valueN); + $lineFace[] = $vConst; + $indexesList[$hashVar] = $vConst; + $vConst++; + } + else + { + $lineFace[] = $indexesList[$hashVar]; } break; @@ -350,9 +370,16 @@ class LoardObj ; } } + foreach( $lineFace as $valueF ) $gltf['face'] .= pack('V',(int)$valueF); } - $vtnf = $v.$vn.$vt.$lineFace; + // 生成gltf语法格式,并与顶点、面片数据组织为一个gltf模型 + $vLength = strlen($gltf['v']); + $vtLength = strlen($gltf['vt']); + $vnLength = strlen($gltf['vn']); + $vfLength = strlen($gltf['face']); + + $vtnf = $gltf['v'].$gltf['vn'].$gltf['vt'].$gltf['face']; $buffer = null; $buffer = "\t\t{\n"; $buffer .= "\t\t\t\"byteLength\" : ".strlen($vtnf).",\n"; @@ -368,7 +395,7 @@ class LoardObj $byteOffset = 0; $bufferView = "\t\t{\n"; $bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\n"; - $bufferView .= "\t\t\t\"byteLength\" : ".strlen($v).",\n"; + $bufferView .= "\t\t\t\"byteLength\" : ".$vLength.",\n"; $bufferView .= "\t\t\t\"byteOffset\" : ".$byteOffset.",\n"; $bufferView .= "\t\t\t\"target\" : 34962\n"; $bufferView .= "\t\t}"; @@ -378,7 +405,7 @@ class LoardObj $accessor = "\t\t{\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"componentType\" : 5126,\n"; - $accessor .= "\t\t\t\"count\" : ".(strlen($v) / 4 / 3).",\n"; + $accessor .= "\t\t\t\"count\" : ".($vLength / 4 / 3).",\n"; $accessor .= "\t\t\t\"max\" :\n"; $accessor .= "\t\t\t[\n"; $accessor .= "\t\t\t\t".$maxX.",\n"; @@ -400,10 +427,10 @@ class LoardObj $bufferView = null; - $byteOffset = $byteOffset + strlen($v); + $byteOffset = $byteOffset + $vLength; $bufferView = "\t\t{\n"; $bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\n"; - $bufferView .= "\t\t\t\"byteLength\" : ".strlen($vn).",\n"; + $bufferView .= "\t\t\t\"byteLength\" : ".$vnLength.",\n"; $bufferView .= "\t\t\t\"byteOffset\" : ".$byteOffset.",\n"; $bufferView .= "\t\t\t\"target\" : 34962\n"; $bufferView .= "\t\t}"; @@ -413,7 +440,7 @@ class LoardObj $accessor = "\t\t{\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"componentType\" : 5126,\n"; - $accessor .= "\t\t\t\"count\" : ".(strlen($vn) / 4 / 3).",\n"; + $accessor .= "\t\t\t\"count\" : ".($vnLength / 4 / 3).",\n"; $accessor .= "\t\t\t\"type\" : \"VEC3\"\n"; $accessor .= "\t\t}"; $this->gltfData['accessors'][$bufferCount] = $accessor; @@ -424,10 +451,10 @@ class LoardObj $bufferView = null; - $byteOffset = $byteOffset + strlen($vn); + $byteOffset = $byteOffset + $vnLength; $bufferView = "\t\t{\n"; $bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\n"; - $bufferView .= "\t\t\t\"byteLength\" : ".strlen($vt).",\n"; + $bufferView .= "\t\t\t\"byteLength\" : ".$vtLength.",\n"; $bufferView .= "\t\t\t\"byteOffset\" : ".$byteOffset.",\n"; $bufferView .= "\t\t\t\"target\" : 34962\n"; $bufferView .= "\t\t}"; @@ -437,7 +464,7 @@ class LoardObj $accessor = "\t\t{\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"componentType\" : 5126,\n"; - $accessor .= "\t\t\t\"count\" : ".(strlen($vt) / 4 / 2).",\n"; + $accessor .= "\t\t\t\"count\" : ".($vtLength / 4 / 2).",\n"; $accessor .= "\t\t\t\"type\" : \"VEC2\"\n"; $accessor .= "\t\t}"; $this->gltfData['accessors'][$bufferCount] = $accessor; @@ -447,10 +474,10 @@ class LoardObj $bufferView = null; - $byteOffset = $byteOffset + strlen($vt); + $byteOffset = $byteOffset + $vtLength; $bufferView = "\t\t{\n"; $bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\n"; - $bufferView .= "\t\t\t\"byteLength\" : ".strlen($lineFace).",\n"; + $bufferView .= "\t\t\t\"byteLength\" : ".$vfLength.",\n"; $bufferView .= "\t\t\t\"byteOffset\" : ".$byteOffset.",\n"; $bufferView .= "\t\t\t\"target\" : 34963\n"; $bufferView .= "\t\t}"; @@ -460,7 +487,7 @@ class LoardObj $accessor = "\t\t{\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"componentType\" : 5125,\n"; - $accessor .= "\t\t\t\"count\" : ".(strlen($lineFace) / 4).",\n"; + $accessor .= "\t\t\t\"count\" : ".($vfLength / 4).",\n"; $accessor .= "\t\t\t\"type\" : \"SCALAR\"\n"; $accessor .= "\t\t}"; $this->gltfData['accessors'][$bufferCount] = $accessor; @@ -596,7 +623,7 @@ class LoardObj /** * 将 $gltfData 数组中的gltf模型 写入硬盘 */ - private function writeGltf( string $path, string $format ) + private function writeGltf( string $path ) { if( !is_dir($path) ) { @@ -643,6 +670,5 @@ class LoardObj } fwrite($handle,"}\n"); fclose($handle); - $handle = null; } }