引用:官方源码
在官方给出的源码中采用的模型格式是tfgl格式,查看源码可知新建DecalGeometry对象时,传入的参数为mesh, position, orientation, size,因此对obj文件不可以直接操作,需要遍历obj中的children,在这里采用drc格式(drc为使用Draco压缩后的格式)的模型实现贴花效果。
DecalGeometry源码中传入的参数:
function DecalGeometry( mesh, position, orientation, size ){...}
实现贴花效果,需要借助DecalGeometry.js,因此要其进行引入:
<script src="js/geometries/DecalGeometry.js"></script>
接着新建贴花时需要的参数,raycaster用于拾取鼠标点击的对象,intersection中有intersect、point、normal,intersect为boolean用于判断鼠标点击的位置是否属于模型表面,point与normal用于存储鼠标点击模型时的point与normal。
var mouse=new THREE.Vector2();
var moved;//
var line;//跟随鼠标
var raycaster;//拾取射线
var intersection;//相交线
var decalPosition;//贴花位置
var decalOrientation;//贴花方向
var decalMaterial;//贴花材质
var decals;//贴花数组
var decalSize;//贴花数组
var mouseHelper;
对参数进行初始化,首先在场景中添加line,若物体表面出现线条,则表明当前位置允许进行贴花操作,通过textureLoader加载所需要的贴花纹理:
function initDecalData(){
let geometry=new THREE.BufferGeometry();
geometry.setFromPoints([new THREE.Vector3(),new THREE.Vector3()]);
line=new THREE.Line(geometry,new THREE.LineBasicMaterial({color:0xff0000}));
scene.add(line);
decalSize=new THREE.Vector3( 10, 10, 10 );
decalPosition=new THREE.Vector3();
decalOrientation=new THREE.Euler();
decals=[];
mouseHelper = new THREE.Mesh( new THREE.BoxBufferGeometry( 1, 1, 10 ), new THREE.MeshNormalMaterial() );
mouseHelper.visible = false;
scene.add( mouseHelper );//
let textureLoader=new THREE.TextureLoader();
let decalDiffuse=textureLoader.load( 'textures/decal/decal-diffuse.png' );//贴花
let decalNormal=textureLoader.load( 'textures/decal/decal-normal.jpg' );
decalMaterial=new THREE.MeshLambertMaterial( {
pecular: 0x444444,
map: decalDiffuse,//贴花图
normalMap: decalNormal,//法向量纹理
normalScale: new THREE.Vector2( 1, 1 ),
shininess: 30,
transparent: true,//透明度
depthTest: true,
depthWrite: false,
polygonOffset: true,
polygonOffsetFactor: - 4,
wireframe: false
} );
intersection={//相交线
intersects:false,
point:new THREE.Vector3(),
normal:new THREE.Vector3()
};
}
通过拾取射线对选取的贴花的位置进行判断,是否位于模型表面。当位于模型表面时,获取点击模型时的point:
function checkIntersection(){
if(!model) return;
raycaster=new THREE.Raycaster();//拾取射线
raycaster.setFromCamera(mouse,camera);
let intersects=raycaster.intersectObjects([model]);
//console.log(intersects);
if(intersects.length>0){//在模型表面
let modelPoint=intersects[0].point;//获取模型的point
mouseHelper.position.copy(modelPoint);
intersection.point.copy(modelPoint);
let modelNormal=intersects[0].face.normal;//.clone();
modelNormal.transformDire