|
|
@ -25,6 +25,26 @@ class LoardObj |
|
|
|
*/ |
|
|
|
public $plyData = []; |
|
|
|
|
|
|
|
/** |
|
|
|
* @var array 储存gltf模型数据 |
|
|
|
*/ |
|
|
|
public $gltfData = [ |
|
|
|
'asset' => '{ "version" : "2.0" }', |
|
|
|
'scene' => 0, |
|
|
|
'scenes' => [], |
|
|
|
'nodes' => [], |
|
|
|
'cameras' => [], |
|
|
|
'skins' => [], |
|
|
|
'meshes' => [], |
|
|
|
'accessors' => [], |
|
|
|
'bufferViews' => [], |
|
|
|
'buffers' => [], |
|
|
|
'material' => [], |
|
|
|
'textures' => [], |
|
|
|
'images' => [], |
|
|
|
'samplers' => [] |
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -57,9 +77,9 @@ class LoardObj |
|
|
|
*/ |
|
|
|
public function toGltf( string $path = null,string $format = self::TYPE_BINARY) |
|
|
|
{ |
|
|
|
// $this->createGltf();
|
|
|
|
// if( $path == null) $path = getcwd()."/gltf";
|
|
|
|
// return $this->writeGltf( $path, $format );
|
|
|
|
$this->createGltf(); |
|
|
|
if( $path == null) $path = getcwd()."/gltf"; |
|
|
|
return $this->writeGltf( $path, $format ); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -237,6 +257,240 @@ class LoardObj |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 利用已经拆分的 obj 模型数据,生成多个 gltf 模型,并将这些模型储存在 gltfData 数组中 |
|
|
|
*/ |
|
|
|
private function createGltf() |
|
|
|
{ |
|
|
|
$scene = null; |
|
|
|
$node = null; |
|
|
|
$mesh = null; |
|
|
|
$camera = null; |
|
|
|
$skin = null; |
|
|
|
$accessor = null; |
|
|
|
$bufferView = null; |
|
|
|
$buffer = null; |
|
|
|
$material = null; |
|
|
|
$texture = null; |
|
|
|
$sampler = null; |
|
|
|
$image = null; |
|
|
|
$animation = null; |
|
|
|
$meshCount = 0; |
|
|
|
$bufferCount = 0; |
|
|
|
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 ) // 生成顶点和面数据
|
|
|
|
{ |
|
|
|
$face_value = implode('/', $face_value); |
|
|
|
$face_value = explode('/', $face_value); |
|
|
|
foreach( $face_value as $v_key => $v_value ) |
|
|
|
{ |
|
|
|
switch( ($v_key+1) % 3 ) |
|
|
|
{ |
|
|
|
case 1: |
|
|
|
foreach($this->objData['v'][$v_value-1] as $xyz_value) |
|
|
|
{ |
|
|
|
// $v .= pack('f',$xyz_value);
|
|
|
|
$v .= (float)$xyz_value; |
|
|
|
} |
|
|
|
// $lineFace .= pack('L',$v_value);
|
|
|
|
$lineFace .= (int)$v_value; |
|
|
|
break; |
|
|
|
|
|
|
|
case 2: |
|
|
|
if( $v_value == null ) |
|
|
|
{ |
|
|
|
// $vt .= pack('f',0.0000);
|
|
|
|
// $vt .= pack('f',0.0000);
|
|
|
|
$vt .= (float)0.0000; |
|
|
|
$vt .= (float)0.0000; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
foreach(array_slice($this->objData['vt'][$v_value-1],0,2) as $t_value) |
|
|
|
{ |
|
|
|
// $vt .= pack('f',$t_value);
|
|
|
|
$vt .= (float)$t_value; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
case 0; |
|
|
|
foreach($this->objData['vn'][$v_value-1] as $n_value) |
|
|
|
{ |
|
|
|
// $vn .= pack('f',$n_value);
|
|
|
|
$vn .= (float)$n_value; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
$vtnf = $v.$vn.$vt.$lineFace; |
|
|
|
$buffer = null; |
|
|
|
$buffer = "\t\t{\n"; |
|
|
|
$buffer .= "\t\t\t\"byteLength\" : ".strlen($vtnf).",\n"; |
|
|
|
$vtnf = base64_encode($vtnf); |
|
|
|
$buffer .= "\t\t\t\"uri\" : \"data:application/octet-stream;base64,".$vtnf."\"\n"; |
|
|
|
$buffer .= "\t\t}\n"; |
|
|
|
$this->gltfData['buffers'][$meshCount] = $buffer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$bufferView = null; |
|
|
|
$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\"byteOffset\" : ".$byteOffset."\n"; |
|
|
|
$bufferView .= "\t\t}\n"; |
|
|
|
$this->gltfData['bufferViews'][$bufferCount] = $bufferView; |
|
|
|
|
|
|
|
$accessor = null; |
|
|
|
$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\"max\" : []";
|
|
|
|
// $accessor .= "\t\t\t\"min\" : []";
|
|
|
|
$accessor .= "\t\t\t\"type\" : \"VEC3\"\n"; |
|
|
|
$accessor .= "\t\t}\n"; |
|
|
|
$this->gltfData['accessors'][$bufferCount] = $accessor; |
|
|
|
$bufferCount++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$bufferView = null; |
|
|
|
$byteOffset = $byteOffset + strlen($v); |
|
|
|
$bufferView = "\t\t{\n"; |
|
|
|
$bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\n"; |
|
|
|
$bufferView .= "\t\t\t\"byteLength\" : ".strlen($vn).",\n"; |
|
|
|
$bufferView .= "\t\t\t\"byteOffset\" : ".$byteOffset."\n"; |
|
|
|
$bufferView .= "\t\t}\n"; |
|
|
|
$this->gltfData['bufferViews'][$bufferCount] = $bufferView; |
|
|
|
|
|
|
|
$accessor = null; |
|
|
|
$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\"type\" : \"VEC3\"\n"; |
|
|
|
$accessor .= "\t\t}\n"; |
|
|
|
$this->gltfData['accessors'][$bufferCount] = $accessor; |
|
|
|
$bufferCount++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$bufferView = null; |
|
|
|
$byteOffset = $byteOffset + strlen($vn); |
|
|
|
$bufferView = "\t\t{\n"; |
|
|
|
$bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\n"; |
|
|
|
$bufferView .= "\t\t\t\"byteLength\" : ".strlen($vt).",\n"; |
|
|
|
$bufferView .= "\t\t\t\"byteOffset\" : ".$byteOffset."\n"; |
|
|
|
$bufferView .= "\t\t}\n"; |
|
|
|
$this->gltfData['bufferViews'][$bufferCount] = $bufferView; |
|
|
|
|
|
|
|
$accessor = null; |
|
|
|
$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\"type\" : \"VEC2\"\n"; |
|
|
|
$accessor .= "\t\t}\n"; |
|
|
|
$this->gltfData['accessors'][$bufferCount] = $accessor; |
|
|
|
$bufferCount++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$bufferView = null; |
|
|
|
$byteOffset = $byteOffset + strlen($vt); |
|
|
|
$bufferView = "\t\t{\n"; |
|
|
|
$bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\n"; |
|
|
|
$bufferView .= "\t\t\t\"byteLength\" : ".strlen($lineFace).",\n"; |
|
|
|
$bufferView .= "\t\t\t\"byteOffset\" : ".$byteOffset."\n"; |
|
|
|
$bufferView .= "\t\t}\n"; |
|
|
|
$this->gltfData['bufferViews'][$bufferCount] = $bufferView; |
|
|
|
|
|
|
|
$accessor = null; |
|
|
|
$accessor = "\t\t{\n"; |
|
|
|
$accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; |
|
|
|
$accessor .= "\t\t\t\"componentType\" : 5125,\n"; |
|
|
|
$accessor .= "\t\t\t\"count\" : ".(strlen($vt) / 4).",\n"; |
|
|
|
$accessor .= "\t\t\t\"type\" : \"SCALAR\"\n"; |
|
|
|
$accessor .= "\t\t}\n"; |
|
|
|
$this->gltfData['accessors'][$bufferCount] = $accessor; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$mesh = null; |
|
|
|
$mesh = "\t\t{\n"; |
|
|
|
$mesh .= "\t\t\t\"name\" : \"".$meshs_key."\",\n"; |
|
|
|
$mesh .= "\t\t\t\"primitives\" :\n"; |
|
|
|
$mesh .= "\t\t\t[\n"; |
|
|
|
$mesh .= "\t\t\t\t{\n"; |
|
|
|
$mesh .= "\t\t\t\t\t\"attributes\" :\n"; |
|
|
|
$mesh .= "\t\t\t\t\t{\n"; |
|
|
|
$mesh .= "\t\t\t\t\t\t\"POSITION\" :".($bufferCount -3).",\n"; |
|
|
|
$mesh .= "\t\t\t\t\t\t\"NORMAL\" :".($bufferCount -2).",\n"; |
|
|
|
$mesh .= "\t\t\t\t\t\t\"TEXCOORD_0\" :".($bufferCount -1).",\n"; |
|
|
|
$mesh .= "\t\t\t\t\t}\n"; |
|
|
|
$mesh .= "\t\t\t\t\t\"indices\" :".($bufferCount).",\n"; |
|
|
|
$mesh .= "\t\t\t\t}\n"; |
|
|
|
$mesh .= "\t\t\t]\n"; |
|
|
|
$mesh .= "\t\t}\n"; |
|
|
|
$this->gltfData['meshes'][$meshCount] = $mesh; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$node = null; |
|
|
|
$node = "\t\t{\n"; |
|
|
|
$node .= "\t\t\t\"mesh\" : ".$meshCount.",\n"; |
|
|
|
$node .= "\t\t\t\"name\" : \"".$meshs_key."\"\n"; |
|
|
|
$node .= "\t\t}\n"; |
|
|
|
$this->gltfData['nodes'][$meshCount] = $node; |
|
|
|
$bufferCount++; |
|
|
|
$meshCount++; |
|
|
|
} |
|
|
|
|
|
|
|
$scene = null; |
|
|
|
$scene = "\t\t{\n"; |
|
|
|
$scene .= "\t\t\t\"name\" : \"".'Scene'."\",\n"; |
|
|
|
$scene .= "\t\t\t\"nodes\" :\n"; |
|
|
|
$scene .= "\t\t\t[\n"; |
|
|
|
foreach ($this->gltfData['nodes'] as $key => $value) |
|
|
|
{ |
|
|
|
if( ($key+1) == count($this->gltfData['nodes']) ) |
|
|
|
{ |
|
|
|
$scene .= "\t\t\t\t".$key."\n"; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
$scene .= "\t\t\t\t".$key.",\n"; |
|
|
|
} |
|
|
|
} |
|
|
|
$scene .= "\t\t\t]\n"; |
|
|
|
$scene .= "\t\t}\n"; |
|
|
|
$this->gltfData['scenes'][] = $scene; |
|
|
|
|
|
|
|
$this->gltfData['asset'] = '{ "version" : "2.0" }'; |
|
|
|
$this->gltfData['scene'] = 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 将 $plyData 数组中的ply模型 写入硬盘 |
|
|
@ -307,4 +561,51 @@ class LoardObj |
|
|
|
return $plyFile; |
|
|
|
} |
|
|
|
|
|
|
|
private function writeGltf( string $path, string $format ) |
|
|
|
{ |
|
|
|
if( !is_dir($path) ) |
|
|
|
{ |
|
|
|
if( !mkdir( $path,0777,true) ) |
|
|
|
{ |
|
|
|
throw new \Exception("!!! Failed to create the specified directory:".$path); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
$gltfFile = preg_split("/[.]+/", basename($this->objFile)); |
|
|
|
$gltfFile = array_reverse($gltfFile); |
|
|
|
array_shift($gltfFile); |
|
|
|
$gltfFile = implode('.', array_reverse($gltfFile)); |
|
|
|
$gltfFile = $path.'/'.$gltfFile.".gltf"; |
|
|
|
|
|
|
|
$handle = fopen( $gltfFile,'w+'); |
|
|
|
fwrite($handle,"{\n"); |
|
|
|
foreach ( $this->gltfData as $key => $value) |
|
|
|
{ |
|
|
|
if( !($value == []) ) |
|
|
|
{ |
|
|
|
$data = null; |
|
|
|
if( is_array($value) ) |
|
|
|
{ |
|
|
|
$data = "\t\"".$key."\" :\n"; |
|
|
|
$data .= "\t[\n"; |
|
|
|
foreach( $value as $key => $value ) |
|
|
|
{ |
|
|
|
$data .= $value; |
|
|
|
} |
|
|
|
if( $key == 'buffers' ) $data .= "\t]\n"; |
|
|
|
else $data .= "\t],\n"; |
|
|
|
fwrite($handle,$data); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
$data = "\t\"".$key."\" :"; |
|
|
|
$data .= $value.",\n"; |
|
|
|
fwrite($handle,$data); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
fwrite($handle,"}\n"); |
|
|
|
fclose($handle); |
|
|
|
$handle = null; |
|
|
|
} |
|
|
|
} |