Three.js 对齐屋顶上的木瓦

问题描述 投票:0回答:1

使用 Three.js,我尝试在挤压屋顶面上正确对齐木瓦纹理。对于每个屋顶面,我都有一个平面上的 Vector3 位置列表。我将位置捕捉到平面并将位置转换为 Vector2。然后,我构建一个 Shape 并使用 ExtrudeGeometry 为屋顶面提供一定的深度。然后我使用这个拉伸几何体创建一个网格。然后我重新定位网格以匹配原始 Vector3 位置。然后我将木瓦纹理应用到挤压网格上。不幸的是,木瓦纹理未对齐。它应该与地面水平对齐(就像屋顶上的实际木瓦一样)。相反,纹理在每个拉伸网格上似乎具有不同的对齐方式。如何纠正纹理的对齐方式?另外,有没有更简单的方法来完成这一切?

这是我的代码:

import * as THREE from "https://threejs.org/build/three.module.js";

import { OrbitControls } from "https://threejs.org/examples/jsm/controls/OrbitControls.js";

// Initialize variables.
var camera, scene, renderer;

// Construct a first facet.
const facetA = {
    constant: 91.61580281251129,
    normal: new THREE.Vector3(0.295196273024157, -0.7734475261474146, 0.5609260955679382),
    positions: [
        new THREE.Vector3(-0.43264564724512017, 0.39861787856381, -10.811021142221584),
        new THREE.Vector3(-0.3603916879324139, 0.62325788852944, -10.672222577778967),
        new THREE.Vector3(-3.438495501227518, 3.90763891140433, -4.443674443873537),
        new THREE.Vector3(-4.468878632744621, 3.4661899184247, -4.521952858193468),
        new THREE.Vector3(-6.261958684067886, 3.4661899184247, -3.5885344644729096),
        new THREE.Vector3(-11.501336764455012, 0.39861787856381, -5.0490252538672)
    ]
};

// Construct a second facet.
const facetB = {
    constant: 102.2695562384374,
    normal: new THREE.Vector3(0.47299246405089335, -0.8710230296599417, 0.13265372498758107),
    positions: [
        new THREE.Vector3(-11.501336764455012, 0.39861787856381, -5.0490252538672),
        new THREE.Vector3(-6.261958684067886, 3.4661899184247, -3.5885344644729096),
        new THREE.Vector3(-11.90307662122538, 0.39861787856381, -3.616574527141971)
    ]
};

// Construct a facet list.
const facets = [facetA, facetB];

// Initialize the scene.
init();

// Begin the animation.
animate();

// Initializes the scene.
function init() {
    
    // Construct a scene.
    scene = new THREE.Scene();
    
    // Construct a camera.
    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.set(-20, 5, -5);
    scene.add(camera);
    
    // Construct an axes helper.
    const axesHelper = new THREE.AxesHelper(5);
    scene.add(axesHelper);
    
    // Construct facet meshes.
    const count = facets.length;
    for(var index = 0; index < count; index++) {
        const facet = facets[index];
        const mesh = getMesh(facet);
        scene.add(mesh);
    }
    
    // Construct a renderer.
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    // Construct orbit controls.
    const controls = new OrbitControls( camera, renderer.domElement );
    controls.update();
    
}

// Animates the scene.
function animate() {
    
    // Request an animation frame.
    requestAnimationFrame(animate);
    
    //  Render the scene.
    render();
    
}

// Renders the scene.
function render() {
    
    // Render the scene.
    renderer.render(scene, camera);
    
}

// Gets a mesh representing a facet.
function getMesh(facet) {
    
    // Get the facet's constant.
    const constant = facet.constant;
    
    // Get the facet's normal.
    const normal = facet.normal;
    
    // Get the facet's plane.
    const plane = new THREE.Plane(normal, constant);
    
    // Get the facet's positions.
    const positions = facet.positions;
    
    // Load a texture.
    //const texture = new THREE.TextureLoader().load("https://raw.githubusercontent.com/mrdoob/three.js/master/examples/textures/uv_grid_opengl.jpg");
    const texture = new THREE.TextureLoader().load("https://dl.dropboxusercontent.com/s/nckrp8ydlaietr8/shingles.jpg");
    
    // Scale the texture.
    texture.repeat.set(0.2, 0.2);
    
    // Wrap the texture.
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    
    // Construct a material.
    const material = new THREE.MeshBasicMaterial({map: texture});
    
    // Get an extruded mesh.
    const mesh = getExtrudedMesh(plane, positions, material);
    
    // Return the mesh.
    return mesh;
    
}

// Gets an extruded mesh.
function getExtrudedMesh(plane, positions, material) {
    
    // Get a shape representing the facet.
    const shape = getShape(plane, positions);
    
    // Construct geometry.
    const geometry = new THREE.ExtrudeGeometry(shape, {depth: 0.2, bevelEnabled: false});
    
    // Construct an origin.
    const origin = new THREE.Vector3(0, 0, 0);
    
    // Get the plane's normal.
    const normal = plane.normal;
    
    // Construct an x-axis vector.
    const axisX = new THREE.Vector3(1, 0, 0);
    
    // Construct an orientation matrix to offset pivot.
    const orientation = new THREE.Matrix4();
    
    // Construct a matrix to fix the pivot rotation.
    const offsetRotation = new THREE.Matrix4();
    
    // Construct a matrix to fix the pivot position.
    const offsetPosition = new THREE.Matrix4();
    
    // Look at the destination.
    orientation.lookAt(origin, normal, axisX);
    
    // Rotate 90 degrees around z axis.
    offsetRotation.makeRotationZ(Math.PI / 2);
    
    // Combine orientation and rotation.
    orientation.multiply(offsetRotation);
  
  // Rotate the geometry.
    geometry.applyMatrix4(orientation);
    
    // Construct a mesh.
    const mesh = new THREE.Mesh(geometry, material);
  
    // Get the first position.
    const firstPosition = positions[0];
    
    // Position the mesh.
    mesh.position.set(firstPosition.x, firstPosition.y, firstPosition.z);
    
    // Return the mesh.
    return mesh;
    
}

// Snaps 3D points to a plane and returns the resulting 2D shape.
function getShape(plane, inputPositions) {
    
    // Construct a shape.
    const shape = new THREE.Shape();
    
    // Convert the positions to 2D.
    const outputPositions = toVector2(plane, inputPositions);
    
    // Count the positions.
    const count = outputPositions.length;
    
    // For each position...
    for(var index = 0; index < count; index++) {
        
        // Get the current position.
        const outputPosition = outputPositions[index];
        
        // Get the position's coordinates.
        const x = outputPosition.x;
        const y = outputPosition.y;
        
        // Add the position to the shape 
        shape.lineTo(x, y);
        
    }
    
    // Return the shape.
    return shape;
    
}

// Snaps 3D points to a plane and returns the resulting 2D points.
function toVector2(plane, inputPositions) {
    
    // Get the first position.
    const positionA = inputPositions[0];
    
    // Construct a second position above the first.
    const positionB = positionA.clone();
    positionB.x += 1;
    
    // Snap the positions to the plane.
    const p1 = new THREE.Vector3();
    const p2 = new THREE.Vector3();
    plane.projectPoint(positionA, p1);
    plane.projectPoint(positionB, p2);
    
    // Get normal vector to plane.
    const normal = plane.normal;
    
    // Get new x-axis in the plane.
    const axisX = (new THREE.Vector3().subVectors(p2, p1)).normalize();
    
    // Get the new z-axis.
    const axisZ = normal;
    
    // Get new y-axis in the plane.
    const axisY = (new THREE.Vector3().crossVectors(axisX, axisZ)).normalize();
    
    // Get new origin in the plane.
    const origin = p1;
    
    // Initialize an output position list.
    const outputPositions = new Array();
    
    // Count the positions.
    const positionCount = inputPositions.length;
    
    // For each position...
    for(var positionIndex = 0; positionIndex < positionCount; positionIndex++) {
        
        // Get the current input position.
        const inputPosition = inputPositions[positionIndex];
        
        // Construct an output position.
        const outputPosition = new THREE.Vector2();
        
        // Set the output position's coordinates.
        outputPosition.x = (new THREE.Vector3().subVectors(inputPosition, origin)).dot(axisX);
        outputPosition.y = (new THREE.Vector3().subVectors(inputPosition, origin)).dot(axisY);
        
        // Add the output position to the list.
        outputPositions.push(outputPosition);
        
    }
    
    // Return the output positions.
    return outputPositions;
    
}

这是一个 JSFiddle:

https://jsfiddle.net/rmibert/2aw47Lj1/41/

这是显示两个屋顶面上未对齐的木瓦的屏幕截图:

three.js
1个回答
0
投票

这个问题你解决了吗?是怎么解决的

© www.soinside.com 2019 - 2024. All rights reserved.