threejs 8随机生成千个cube和点击选中模型

Posted Jessica巨人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了threejs 8随机生成千个cube和点击选中模型相关的知识,希望对你有一定的参考价值。

有滑动条和白边:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html,body{
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
    </style>
</head>

<body>

</body>

</html>

效果:模型选中之后变红,点击选择其他的模型之后恢复原来的颜色
第一个实现:

/**
 * 一个基本的threejs例子
 */

import * as THREE from "three"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
import { AmbientLight, AxesHelper, BoxBufferGeometry, DirectionalLight, HemisphereLight, Mesh, MeshPhongMaterial, SphereGeometry, TextureLoader } from "three";
import{FBXLoader}from "three/examples/jsm/loaders/FBXLoader"
import{MTLLoader} from "three/examples/jsm/loaders/MTLLoader"
import{OBJLoader}from "three/examples/jsm/loaders/OBJLoader"
import{GLTFLoader}from "three/examples/jsm/loaders/GLTFLoader"

var renderer = new THREE.WebGLRenderer({ antialias: true });
// renderer.domElement;//是一个canvas 可以从参数传入
document.body.appendChild(renderer.domElement);

renderer.setSize(window.innerWidth, window.innerHeight);//设置画布高宽
renderer.setClearColor(0xffffff);//设置背景清空颜色

window.addEventListener("resize", () => {//窗口大小变化事件
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    //设置了aspect  必须更新相机的投影矩阵
    camera.updateProjectionMatrix();
})

var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 100)
var control = new OrbitControls(camera, renderer.domElement);
var scene = new THREE.Scene();

scene.background = new THREE.CubeTextureLoader()
    .setPath( "../assets/textures/cubeMaps/")
    .load( [
        'posx.jpg',
        'negx.jpg',
        'posy.jpg',
        'negy.jpg',
        'posz.jpg',   
        'negz.jpg'
    ] );


var dirLight=new DirectionalLight(0xffffff);
dirLight.intensity=5;

var light = new HemisphereLight(0xffffff, 0x444444);
scene.add(light);
scene.add(dirLight);

//-----------------------随机生成1000个立方体-----------------------------
var cubeGrometry=new BoxBufferGeometry(2,2,2);
for (let i = 0; i < 1000; i++) {
    //Math.random()生成一个0-1之间的随机数
    var mesh=new Mesh(cubeGrometry,new MeshPhongMaterial({color:0xffffff*Math.random()}))
    scene.add(mesh);
    mesh.position.set(300*Math.random()-50,300*Math.random()-50,300*Math.random()-50);
    mesh.scale.set(2*Math.random()+1,2*Math.random()+1,2*Math.random()+1);
    mesh.rotation.set(7*Math.random(),7*Math.random(),7*Math.random());
}
//---------------------------点击选中---------------------------------------
/*表示一条射线
Raycaster(origin?:THREE.vector3,direction?:THREE.Vector3,near?:number,far?:number)
*/
var raycaster=new THREE.Raycaster();
var coords=new THREE.Vector2(0,0);
var selectedMaterial=new MeshPhongMaterial({color:0xff0000});
var lastSelectModel=null;
window.addEventListener("pointerdown",(ev)=>{

    coords.x=(ev.clientX/window.innerWidth)*2-1;
    coords.y=-(ev.clientY/window.innerHeight)*2+1;
    // raycaster.setFromCamera({x:0,y:0},camera);
    raycaster.setFromCamera(coords,camera);
    var intersectObjects= raycaster.intersectObject(scene,true);
    if (intersectObjects.length>0) {
        //说明模型被选中
        var interObj=intersectObjects[0];
        var selectedmodel= interObj.object;
        selectedmodel.orgMaterial=selectedmodel.material;
        selectedmodel.material=selectedMaterial;
        // selectedmodel.material.emissive.set(0xff0000);
        if (lastSelectModel!==null&& lastSelectModel!==selectedMaterial) {
            lastSelectModel.material=lastSelectModel.orgMaterial;
        }
        lastSelectModel=selectedmodel;
    }
})
//-----------------------------------------------------------------------------------------------------
update()

function update() {
    console.log('刷新')
    renderer.render(scene, camera);
    requestAnimationFrame(update);//不会卡塞,专门针对图形渲染刷新的方法
}
//----------------------------------------模型加载------------------------------------------------------
var gltfLoader=new GLTFLoader();
gltfLoader.load("../assets/models/glTF/wuren.glb",(glb)=>{
glb.scene.x=-10;
// glb.scale.set(10,10,10);
    scene.add(glb.scene);
});
/**
 *练习一下点选
 */

import * as THREE from "three"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
import { AmbientLight, AxesHelper, BoxBufferGeometry, Color, DirectionalLight, HemisphereLight, 
    Mesh, MeshPhongMaterial, Raycaster, SphereGeometry, TextureLoader } from "three";


var renderer = new THREE.WebGLRenderer({ antialias: true });
document.body.appendChild(renderer.domElement);

renderer.setSize(window.innerWidth, window.innerHeight);//设置画布高宽
renderer.setClearColor(0xffffff);//设置背景清空颜色

window.addEventListener("resize", () => {//窗口大小变化事件
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
})

var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 100)
var control = new OrbitControls(camera, renderer.domElement);
var scene = new THREE.Scene();

scene.background = new THREE.CubeTextureLoader()
    .setPath( "../assets/textures/cubeMaps/")
    .load( [
        'posx.jpg',
        'negx.jpg',
        'posy.jpg',
        'negy.jpg',
        'posz.jpg',   
        'negz.jpg'
    ] );


var dirLight=new DirectionalLight(0xffffff);
dirLight.intensity=5;

var light = new HemisphereLight(0xffffff, 0x444444);
scene.add(light);
scene.add(dirLight);

//------------------------生成1000个随机立方体----------------------------------

var cubeGrometry=new BoxBufferGeometry(2,2,2);
for (let i = 0; index < 100; i++) 
{

    var mesh =new Mesh(cubeGrometry,new MeshPhongMaterial({color:0xffffff*Math.random()}));
    scene.add(mesh);

    mesh.position.set(300*Math.random()-50,300*Math.random()-50,300*Math.random()-50);
    mesh.scale.set(2*Math.random()+1,2*Math.random()+1,2*Math.random()+1);
    mesh.rotation.set(7*Math.random(),7*Math.random(),7*Math.random());  
}

//---------------------------点击选中START---------------------------------------

var raycaster = new THREE.Raycaster()
var mouse = new THREE.Vector2()

function onMouseClick(event){

    //将鼠标点击位置的屏幕坐标转换成threejs中的标准坐标

    mouse.x = (event.clientX / window.innerWidth) * 2 - 1
    mouse.y = (event.clientY/window.innerHeight) *2 + 1
 
    // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
    raycaster.setFromCamera( mouse, camera );

    // 获取raycaster直线和所有模型相交的数组集合
    var intersects = raycaster.intersectObjects( scene.children );
    console.log(intersects);

     //将所有的相交的模型的颜色设置为红色
     for ( var i = 0; i < intersects.length; i++ ) {

            intersects[ i ].object.material.color.set( 0xff0000 );

        }
    }

window.addEventListener( 'click', onMouseClick, false );

//---------------------------选中部分END-----------------------------------------

update()

function update() {
    console.log('刷新')
    renderer.render(scene, camera);
    requestAnimationFrame(update);//不会卡塞,专门针对图形渲染刷新的方法
}
//-------------------------------------------------------------------------------

效果图:

以上是关于threejs 8随机生成千个cube和点击选中模型的主要内容,如果未能解决你的问题,请参考以下文章

threejs加载3d模型 怎样控制鼠标点击选中某个模型

threejs设置物体位置

html文本框选中日期后发生事件

js怎么产生一个3位数随机数?

threejs 怎么显示坐标轴

ThreeJs 选中物体事件