Browse Source

已经修复转gltf模型时不能转大模型的bug

master
yuanjiajia 2 years ago
parent
commit
12f8ebe016
  1. 14
      examples/loadObjDemo.php
  2. 154
      src/core/LoardObj.php

14
examples/loadObjDemo.php

@ -6,17 +6,11 @@ namespace Blobt\Luxcore\core;
use Blobt\Luxcore\core\LoardObj; use Blobt\Luxcore\core\LoardObj;
include dirname(dirname(__FILE__)) . "/vendor/autoload.php"; include dirname(dirname(__FILE__)) . "/vendor/autoload.php";
ini_set('memory_limit','4096M'); 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 );
?> ?>

154
src/core/LoardObj.php

@ -10,39 +10,51 @@ class LoardObj
const OPEN = true; const OPEN = true;
const CLOSE = false; const CLOSE = false;
/** /**
* @var string $objFile obj文件路径 * @var string $objFile obj文件路径
*/ */
public $objFile;
private $objFile;
/** /**
* @var array 储存obj模型数据 * @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模型数据 * @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 $path ply模型 保存路径
* @param string $format ply模型 保存格式 * @param string $format ply模型 保存格式
*/ */
public function toGltf( string $path = null,string $format = self::TYPE_BINARY)
public function toGltf( string $path = null)
{ {
$this->createGltf(); $this->createGltf();
if( $path == null) $path = getcwd()."/gltf"; 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() private function createGltf()
{ {
@ -277,23 +289,30 @@ class LoardObj
$animation = null; $animation = null;
$meshCount = 0; $meshCount = 0;
$bufferCount = 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 ) 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 = implode('/', $face_value);
$face_value = explode('/', $face_value); $face_value = explode('/', $face_value);
$lineFace = [];
$v = null;
$vt = null;
$vn = null;
foreach( $face_value as $v_key => $v_value ) foreach( $face_value as $v_key => $v_value )
{ {
switch( ($v_key+1) % 3 ) switch( ($v_key+1) % 3 )
@ -319,30 +338,31 @@ class LoardObj
default: default:
; ;
} }
$v .= pack('g',(float)$xyz_value);
} }
$lineFace .= pack('V',((int)$v_value) - 1);
$v = $this->objData['v'][$v_value-1];
break; break;
case 2: 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; break;
case 0; 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; 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 = null;
$buffer = "\t\t{\n"; $buffer = "\t\t{\n";
$buffer .= "\t\t\t\"byteLength\" : ".strlen($vtnf).",\n"; $buffer .= "\t\t\t\"byteLength\" : ".strlen($vtnf).",\n";
@ -368,7 +395,7 @@ class LoardObj
$byteOffset = 0; $byteOffset = 0;
$bufferView = "\t\t{\n"; $bufferView = "\t\t{\n";
$bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\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\"byteOffset\" : ".$byteOffset.",\n";
$bufferView .= "\t\t\t\"target\" : 34962\n"; $bufferView .= "\t\t\t\"target\" : 34962\n";
$bufferView .= "\t\t}"; $bufferView .= "\t\t}";
@ -378,7 +405,7 @@ class LoardObj
$accessor = "\t\t{\n"; $accessor = "\t\t{\n";
$accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n";
$accessor .= "\t\t\t\"componentType\" : 5126,\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\"max\" :\n";
$accessor .= "\t\t\t[\n"; $accessor .= "\t\t\t[\n";
$accessor .= "\t\t\t\t".$maxX.",\n"; $accessor .= "\t\t\t\t".$maxX.",\n";
@ -400,10 +427,10 @@ class LoardObj
$bufferView = null; $bufferView = null;
$byteOffset = $byteOffset + strlen($v);
$byteOffset = $byteOffset + $vLength;
$bufferView = "\t\t{\n"; $bufferView = "\t\t{\n";
$bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\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\"byteOffset\" : ".$byteOffset.",\n";
$bufferView .= "\t\t\t\"target\" : 34962\n"; $bufferView .= "\t\t\t\"target\" : 34962\n";
$bufferView .= "\t\t}"; $bufferView .= "\t\t}";
@ -413,7 +440,7 @@ class LoardObj
$accessor = "\t\t{\n"; $accessor = "\t\t{\n";
$accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n";
$accessor .= "\t\t\t\"componentType\" : 5126,\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\t\"type\" : \"VEC3\"\n";
$accessor .= "\t\t}"; $accessor .= "\t\t}";
$this->gltfData['accessors'][$bufferCount] = $accessor; $this->gltfData['accessors'][$bufferCount] = $accessor;
@ -424,10 +451,10 @@ class LoardObj
$bufferView = null; $bufferView = null;
$byteOffset = $byteOffset + strlen($vn);
$byteOffset = $byteOffset + $vnLength;
$bufferView = "\t\t{\n"; $bufferView = "\t\t{\n";
$bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\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\"byteOffset\" : ".$byteOffset.",\n";
$bufferView .= "\t\t\t\"target\" : 34962\n"; $bufferView .= "\t\t\t\"target\" : 34962\n";
$bufferView .= "\t\t}"; $bufferView .= "\t\t}";
@ -437,7 +464,7 @@ class LoardObj
$accessor = "\t\t{\n"; $accessor = "\t\t{\n";
$accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n";
$accessor .= "\t\t\t\"componentType\" : 5126,\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\t\"type\" : \"VEC2\"\n";
$accessor .= "\t\t}"; $accessor .= "\t\t}";
$this->gltfData['accessors'][$bufferCount] = $accessor; $this->gltfData['accessors'][$bufferCount] = $accessor;
@ -447,10 +474,10 @@ class LoardObj
$bufferView = null; $bufferView = null;
$byteOffset = $byteOffset + strlen($vt);
$byteOffset = $byteOffset + $vtLength;
$bufferView = "\t\t{\n"; $bufferView = "\t\t{\n";
$bufferView .= "\t\t\t\"buffer\" : ".$meshCount.",\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\"byteOffset\" : ".$byteOffset.",\n";
$bufferView .= "\t\t\t\"target\" : 34963\n"; $bufferView .= "\t\t\t\"target\" : 34963\n";
$bufferView .= "\t\t}"; $bufferView .= "\t\t}";
@ -460,7 +487,7 @@ class LoardObj
$accessor = "\t\t{\n"; $accessor = "\t\t{\n";
$accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n"; $accessor .= "\t\t\t\"bufferView\" : ".($bufferCount).",\n";
$accessor .= "\t\t\t\"componentType\" : 5125,\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\t\"type\" : \"SCALAR\"\n";
$accessor .= "\t\t}"; $accessor .= "\t\t}";
$this->gltfData['accessors'][$bufferCount] = $accessor; $this->gltfData['accessors'][$bufferCount] = $accessor;
@ -596,7 +623,7 @@ class LoardObj
/** /**
* $gltfData 数组中的gltf模型 写入硬盘 * $gltfData 数组中的gltf模型 写入硬盘
*/ */
private function writeGltf( string $path, string $format )
private function writeGltf( string $path )
{ {
if( !is_dir($path) ) if( !is_dir($path) )
{ {
@ -643,6 +670,5 @@ class LoardObj
} }
fwrite($handle,"}\n"); fwrite($handle,"}\n");
fclose($handle); fclose($handle);
$handle = null;
} }
} }
Loading…
Cancel
Save