Browse Source

已完成loadObj.php类文件编写,有bug尚未修复

master
yuanjiajia 2 years ago
parent
commit
ce3c0d9e36
  1. 3
      .vscode/launch.json
  2. 13
      examples/loadObjDemo.php
  3. 245
      src/core/LoardObj.php

3
.vscode/launch.json

@ -1,6 +1,7 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for XDebug",
"type": "php",
@ -11,7 +12,7 @@
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${workspaceFolder}/examples/configBatch.php",
"program": "${workspaceFolder}/examples/loadObjDemo.php",
"cwd": "${workspaceFolder}",
"port": 9055
}

13
examples/loadObjDemo.php

@ -0,0 +1,13 @@
<?php
namespace Blobt\Luxcore\core;
use Blobt\Luxcore\core\LoardObj;
include dirname(dirname(__FILE__)) . "/vendor/autoload.php";
$ply = new LoardObj('/home/yuanjiajia/Desktop/blender/test/3D.obj');
$ply->toPly(LoardObj::TYPE_BINARY);
?>

245
src/core/LoardObj.php

@ -2,56 +2,28 @@
namespace Blobt\Luxcore\core;
class Base
class LoardObj
{
const TYPE_TXT = 'txt';
const TYPE_BINARY = 'binary';
const TYPE_TXT = 'ascii 1.0';
const TYPE_BINARY = 'binary_little_endian 1.0';
const OPEN = true;
const CLOSE = false;
/**
* @var string $objFile obj文件路径
*/
public $objFile;
/**
* @var string $plyFile ply文件路径
* @var array 储存obj模型数据
*/
public $plyFile = [];
public $objData = [];
/**
* @var string $format ply文件储存格式
* @var array 储存ply模型数据
*/
public $format = self::TYPE_TXT;
/**
* @var bool $flipYZ
*/
public $flipYZ;
/**
* @var array $vertexs 顶点坐标数组
*/
public $vertexs = [];
/**
* @var array $textureUV 纹理坐标数组
*/
public $textureUV = [];
/**
* @var array $normals 顶点法线数组
*/
public $normals = [];
/**
* @var array $faces 面片数组
*/
public $mesh = [];
public $plyData = [];
@ -60,24 +32,31 @@ class Base
* @param string $objFile 传入obj文件
* @param bool $flipYZ 是否翻转Z轴Y轴
*/
public function __construct(string $objFile,bool $flipYZ = self::OPEN)
public function __construct( string $objFile, bool $flipYZ = self::OPEN )
{
$this->file = $objFile;
$this->flipYZ = $flipYZ;
$this->objFile = $objFile;
$this->readObj();
if( $flipYZ ) $this->flipYZ();
}
public function toPly()
/**
* @param string $format 储存 ply模型 的格式
*/
public function toPly( string $format = self::TYPE_BINARY)
{
return $this->plyFile;
$this->createPly();
return $this->writePly($format);
}
/**
*
* 读取OBJ模型数据,并拆分模型
*/
public function readObj()
private function readObj()
{
$handle = null;
$line = true;
$line = null;
$keyName = null;
if( !file_exists($this->objFile) )
@ -86,7 +65,7 @@ class Base
}
else
{
$handle = fopen($this->file,'r');
$handle = fopen($this->objFile,'r');
}
@ -96,44 +75,192 @@ class Base
}
else
{
fseek($handle, 0);
while( !feof($handle) ) // 读取所有的 顶点坐标、UV坐标、顶点法线,并存入到相应的数组
while( !feof($handle) ) // 读取所有的 顶点坐标、UV坐标、顶点法线、面片,并存入到相应的数组
{
$line = fgets( $handle );
$line = ltrim( $line );
if( $line[0] == '#' ) continue;
switch( explode(' ', $line)[0] )
$line = explode(' ', $line);
switch( $line[0] )
{
case 'v':
$this->vertexs[] = $line;
array_shift($line); // 将 v 开头的数据行 存入顶点数组
$this->objData['v'][] = $line;
break;
case 'vn':
$this->normals[] = $line;
array_shift($line); // 将 vn 开头的数据行 存入顶点法线数组
$this->objData['vn'][] = $line;
break;
case 'vt':
$this->textureUV[] = $line;
array_shift($line); // 将 vt 开头的数据行 存入 UV坐标数组
$this->objData['vt'][] = $line;
break;
case 'o':
array_shift($line); // 将 o 开头的行(object名) 作为一个键名(按照 ‘o’ 关键字拆分OBJ模型)
$line = implode("_", $line);
$keyName = $line;
break;
case 'f':
array_shift($line); // 将 f 开头的行 存入 ['meshs'][$keyName] 指向的数组
$this->objData['meshs'][$keyName][] = $line;
default:
; // 丢弃无用的 数据行
}
}
}
}
fseek($handle, 0);
while( !feof($handle) ) // 读取 顶点坐标、UV坐标、顶点法线,并存入到相应的数组
{
$line = fgets( $handle );
$line = ltrim( $line );
if( $line[0] == '#' ) continue;
if ( explode(' ', $line)[0] == 'o' )
/**
* 翻转模型的YZ轴向
*/
private function flipYZ()
{
foreach( $this->objData['v'] as $key => $value)
{
$this->objData['v'][$key] = [];
$this->objData['v'][$key][] = $value[0];
$this->objData['v'][$key][] = $value[2];
$this->objData['v'][$key][] = $value[1];
}
}
/**
* 利用已经拆分的 obj 模型数据,生成多个 ply 模型,并将这些模型储存在 plyData 数组中
*/
private function createPly()
{
foreach( $this->objData['meshs'] as $meshs_key => $meshs_value )
{
var_dump($this->objData);
$ply = [];
$vCount = 0;
$fCount = 0;
foreach( $meshs_value as $face_value ) // 生成顶点和面数据
{
$face_value = implode('/', $face_value);
$face_value = explode('/', $face_value);
$lineFace = [];
$v = [];
$vt = [];
$vn = [];
foreach( $face_value as $v_key => $v_value )
{
switch( ($v_key+1) % 3 )
{
case 1:
$v = $this->objData['v'][$v_value-1];
break;
case 2:
$vt = array_splice($this->objData['vt'][$v_value-1],2);
break;
case 0;
$vn = $this->objData['vn'][$v_value-1];
$ply['vertex'][$vCount] = implode(' ',$v).' '.implode(' ',$vn).' '.implode(' ',$vt);
$lineFace[] = $vCount;
$vCount++;
break;
default:
;
}
}
$ply['face'][$fCount] = implode(' ',$lineFace);
$fCount++;
}
$ply['header'][] = 'ply'; // 生成头部数据
$ply['header'][] = "format ";
$ply['header'][] = "comment Created by reaiyunju, source file: ''";
$ply['header'][] = "element vertex ".$vCount;
$ply['header'][] = "property float x";
$ply['header'][] = "property float y";
$ply['header'][] = "property float z";
$ply['header'][] = "property float nx";
$ply['header'][] = "property float ny";
$ply['header'][] = "property float nz";
$ply['header'][] = "property float s";
$ply['header'][] = "property float t";
$ply['header'][] = "element face ".count($ply['face']);
$ply['header'][] = "property list uchar uint vertex_indices";
$ply['header'][] = "end_header";
$this->plyData[$meshs_key] = $ply; // 在 数组plyData 中添加一个 $key 所指名称的ply模型
}
}
/**
* $plyData 数组中的ply模型 写入硬盘
*/
private function writePly(string $format)
{
$plyFile = [];
$handle = null;
foreach( $this->plyData as $key => $value )
{
$plyFile[] = $key."ply";
$handle = fopen( $key."ply",'w+');
foreach( $value['header'] as $h_key => $h_value) // 写入头部数据
{
if( $h_key == 1 ) $data = $h_value.$format."\n";
else $data = $h_value."\n";
fwrite($handle,$data);
}
foreach( $value['vertex'] as $v_value ) // 写入顶点数据
{
if( $format == self::TYPE_BINARY ) // 二进制格试写入
{
foreach( explode(' ', $v_value) as $v )
{
$data .= pack('f',$v);
}
fwrite($handle,$data);
}
else
{
$data = $v_value."\n"; // 文本格试写入
fwrite($handle,$data);
}
}
foreach( $value['face'] as $f_value ) // 写入面片数据
{
if( $format == self::TYPE_BINARY ) // 二进制格试写入
{
foreach( explode(' ', $f_value) as $v )
{
$data .= pack('f',$v);
}
fwrite($handle,$data);
}
else
{
$data = $f_value."\n"; // 文本格试写入
fwrite($handle,$data);
}
}
}
return $plyFile;
}
}
Loading…
Cancel
Save