本内容是裁剪( Path编)的延申
裁剪( Path编) : https://blog.youkuaiyun.com/jinold/article/details/91345585
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - geometry - shapes</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<dir>
<input type="text" id = "qiangSize">
<input type="button" id = "qiangSizeBtn" value="设置" onclick="reSizeQiang()">
</dir>
<dir id="3DCon">
</dir>
<script src="js/three.js"></script>
<script src="js/controls/MapControls.js"></script>
<script>
var container;
var camera, scene, renderer;
var controls;
var targetRotation = 0;
var targetRotationOnMouseDown = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var loader = new THREE.TextureLoader();
var texture = loader.load( "module/brick_diffuse.jpg" );
// it's necessary to apply these settings in order to correctly display the texture on a shape geometry
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 0.008, 0.008 );
init();
animate();
function reSizeQiang() {
const newSize = Number(document.getElementById( 'qiangSize' ).value)
for (let idx = scene.children.length; idx--; idx >= 0 ) {
let objMesh = scene.children[idx]
if (objMesh.type2 === "qiang") {
var geometry = objMesh.geometry
for (let idx2 in geometry.attributes.position.array) {
if (geometry.attributes.position.array[idx2] === 320) {
geometry.attributes.position.array[idx2] = newSize;
}
}
for (let idx2 in geometry.attributes.uv.array) {
if (geometry.attributes.uv.array[idx2] === 320) {
geometry.attributes.uv.array[idx2] = newSize;
}
}
var mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, map: texture } ) );
mesh.position.set( objMesh.position.x, objMesh.position.y, objMesh.position.z);
mesh.rotation.set( objMesh.rotation.x, objMesh.rotation.y, objMesh.rotation.z );
mesh.scale.set( objMesh.scale.x, objMesh.scale.y, objMesh.scale.z );
mesh.type2 = "qiang"
scene.add( mesh );
objMesh.geometry.dispose(); // 删除几何体
objMesh.material.dispose(); // 删除材质
scene.remove(objMesh);
debugger
}
}
}
function addExtrudeShape( bGeometry, pi, rt, s ) {
// 原先是geometry, 但是bGeometry也可以
var mesh = new THREE.Mesh( bGeometry, new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, map: texture } ) );
mesh.position.set( pi.x, pi.y, pi.z - 10 );
mesh.rotation.set( rt.x, rt.y, rt.z );
mesh.scale.set( s, s, s );
mesh.type2 = "qiang"
scene.add( mesh );
}
function addShape( shape, pi, rt, s ) {
var geometry = new THREE.ShapeBufferGeometry( shape );
var bGeometry = new THREE.BufferGeometry();
bGeometry.attributes.position = geometry.attributes.position;
bGeometry.attributes.uv = geometry.attributes.uv;
bGeometry.index = geometry.index
var mesh = new THREE.Mesh( bGeometry, new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, map: texture } ) );
mesh.position.set( pi.x, pi.y, pi.z );
mesh.rotation.set( rt.x, rt.y, rt.z );
mesh.scale.set( s, s, s );
// group.add( mesh );
scene.add( mesh );
}
function QiangBufferGeometry(wdth, height, depth) {
var squareShape = new THREE.Shape();
squareShape.moveTo( 0, 0 );
squareShape.lineTo( 0, height);
squareShape.lineTo( wdth, height);
squareShape.lineTo( wdth, 0 );
squareShape.lineTo( 0, 0 );
var squareShapePath = new THREE.Path();
squareShapePath.moveTo( 10, 10 );
squareShapePath.lineTo( 10, height -10);
squareShapePath.lineTo( wdth - 10, height - 10);
squareShapePath.lineTo( wdth -10 , 10 );
squareShapePath.lineTo( 10, 10 );
squareShape.holes.push( squareShapePath );// 挖洞
var extrudeSettings = { depth: depth, bevelEnabled: true, bevelSegments: 0, steps: 1, bevelSize: 0, bevelThickness: 0 };
// extruded shape
var geometry = new THREE.ExtrudeBufferGeometry( squareShape, extrudeSettings );
// ExtrudeBufferGeometry转换BufferGeometry
var bGeometry = new THREE.BufferGeometry();
// bGeometry.attributes.normal = geometry.attributes.normal;
bGeometry.attributes.position = geometry.attributes.position;
bGeometry.attributes.uv = geometry.attributes.uv;
return bGeometry;
}
function init() {
container = document.getElementById( '3DCon' );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
var axes = new THREE.AxesHelper(10);
scene.add(axes);
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 100, 500 );
camera.up.x = 0;
camera.up.y = 0;
camera.up.z = 1;//相机以Z方向为上方
// scene.add( camera );
controls = new THREE.MapControls( camera, container );
var light = new THREE.PointLight( 0xffffff, 0.8 );
camera.add( light );
// Square
const sqLength = 80;
const squareShape = QiangBufferGeometry(sqLength * 4, sqLength, 8);
addExtrudeShape( squareShape, {x: -sqLength * 2, y: -sqLength * 2, z: 0}, {x: Math.PI / 2, y: 0, z: 0}, 1 );
addExtrudeShape( squareShape, {x: -sqLength * 2, y: sqLength * 2, z: 0}, {x: Math.PI / 2, y: 0, z: 0}, 1 );
addExtrudeShape( squareShape, {x: -sqLength * 2, y: -sqLength * 2, z: 0}, {x: Math.PI / 2, y: Math.PI / 2, z: 0}, 1 );
addExtrudeShape( squareShape, {x: sqLength * 2-8, y: -sqLength * 2, z: 0}, {x: Math.PI / 2, y: Math.PI / 2, z: 0}, 1 );
// Square
var sqDibanLength = 80;
var squareDibanShape = new THREE.Shape();
squareDibanShape.moveTo( -sqDibanLength, -sqDibanLength );
squareDibanShape.lineTo( -sqDibanLength, sqDibanLength );
squareDibanShape.lineTo( sqDibanLength, sqDibanLength );
squareDibanShape.lineTo( sqDibanLength, -sqDibanLength );
squareDibanShape.lineTo( -sqDibanLength, -sqDibanLength );
addShape( squareDibanShape, {x: - sqDibanLength / 2, y: 0, z: 0}, {x: 0, y: 0, z: 0}, 1 );
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//document.addEventListener( 'mousedown', onDocumentMouseDown, false );
//document.addEventListener( 'touchstart', onDocumentTouchStart, false );
//document.addEventListener( 'touchmove', onDocumentTouchMove, false );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut, false );
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
}
function onDocumentMouseUp() {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentMouseOut() {
document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
}
function onDocumentTouchStart( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
targetRotationOnMouseDown = targetRotation;
}
}
function onDocumentTouchMove( event ) {
if ( event.touches.length == 1 ) {
event.preventDefault();
mouseX = event.touches[ 0 ].pageX - windowHalfX;
targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
}
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
//group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
</script>
</body>
</html>
效果图
UV按Face分解
function QiangBufferGeometry(wdth, height, depth) {
var squareShape = new THREE.Shape();
squareShape.moveTo( 0, 0 );
squareShape.lineTo( 0, height);
squareShape.lineTo( wdth, height);
squareShape.lineTo( wdth, 0 );
squareShape.lineTo( 0, 0 );
var squareShapePath = new THREE.Path();
squareShapePath.moveTo( 10, 10 );
squareShapePath.lineTo( 10, height -10);
squareShapePath.lineTo( wdth - 10, height - 10);
squareShapePath.lineTo( wdth -10 , 10 );
squareShapePath.lineTo( 10, 10 );
squareShape.holes.push( squareShapePath );// 挖洞
var extrudeSettings = { depth: depth, bevelEnabled: true, bevelSegments: 0, steps: 1, bevelSize: 0, bevelThickness: 0 };
// extruded shape
var geometry = new THREE.ExtrudeBufferGeometry( squareShape, extrudeSettings );
// ExtrudeBufferGeometry转换BufferGeometry
var bGeometry = new THREE.BufferGeometry();
// bGeometry.attributes.normal = geometry.attributes.normal;
bGeometry.attributes.position = geometry.attributes.position;
bGeometry.attributes.uv = geometry.attributes.uv;
for (let idx2 in bGeometry.attributes.uv.array) {
// UV: 每一个Face有三个顶点组成,每个顶点由两个数字
// 所以每个Face由6个数字组成
if (idx2 > 5) {
geometry.attributes.uv.array[idx2] = 0;
}
/*
// 大face 1,
if (idx2 > 47) {
geometry.attributes.uv.array[idx2] = 0;
}
*/
/*
// 大face 2
if (idx2 < 48 || idx2 > 96) {
geometry.attributes.uv.array[idx2] = 0;
}
*/
}
return bGeometry;
}
只贴图第一个Face和Face的一小块儿。
正面和后面为例,每一面由8个Face组成,如果侧面或顶面地面应该由两个Face组成,这个自己可以试一下。
看到现在突然想起之前的记录
ThreeJs的学习:贴图(三)BufferGeometry
https://blog.youkuaiyun.com/jinold/article/details/99243957
ThreeJs的学习:BufferGeometry的理解(3),Geometry和BufferGeometry的关系
https://blog.youkuaiyun.com/jinold/article/details/98250783
饶了一大圈又回来了。恍然大悟,原来ThreeJs中BufferGeometry才是无敌的存在。
后面练习的球形圆柱形,多边形应该也是这样
结束本章结束前最后一个实验:
var geometry = new THREE.ExtrudeBufferGeometry( squareShape, extrudeSettings );
// ExtrudeBufferGeometry转换BufferGeometry
var bGeometry1 = new THREE.BufferGeometry();
bGeometry1.attributes.position = new THREE.Float32BufferAttribute( geometry.attributes.position.array.slice(0,72), 3);
bGeometry1.attributes.uv = new THREE.Float32BufferAttribute( geometry.attributes.uv.array.slice(0,48), 2);
addExtrudeShape( bGeometry1, {x: -sqLength * 2, y: -sqLength * 2, z: 0}, {x: Math.PI / 2, y: 0, z: 0}, 1 ,texture );
var bGeometry2 = new THREE.BufferGeometry();
bGeometry2.attributes.position = new THREE.Float32BufferAttribute( geometry.attributes.position.array.slice(72,144), 3);
bGeometry2.attributes.uv = new THREE.Float32BufferAttribute( geometry.attributes.uv.array.slice(48,96), 2);
addExtrudeShape( bGeometry2, {x: -sqLength * 2, y: -sqLength * 2, z: 0}, {x: Math.PI / 2, y: 0, z: 0}, 1 ,texture2 );
效果图:每个墙面不同的贴图