学习threejs,场景世界坐标和平面二维坐标互转

发布于:2024-12-06 ⋅ 阅读:(140) ⋅ 点赞:(0)

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师



一、🍀前言

本文详细介绍如何基于threejs在三维场景中实现场景世界坐标和平面二维坐标互转,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.Vector3 三维向量

该类表示的是一个三维向量(3D vector)。 一个三维向量表示的是一个有顺序的、三个为一组的数字组合(标记为x、y和z), 可被用来表示很多事物、
构造函数:
Vector3( x : Float, y : Float, z : Float )
x - 向量的x值,默认为0。
y - 向量的y值,默认为0。
z - 向量的z值,默认为0。
常用属性:
在这里插入图片描述
全部方法可以参考:THREE.Vector3 API
部分方法:
在这里插入图片描述

二、🍀场景世界坐标和平面二维坐标互转

1. ☘️实现思路

  • 1、初始化renderer渲染器
  • 2、初始化Scene三维场景scene,创建THREE.CubeTextureLoader立方体纹理加载器cubeTextureLoader,加载cubeTextureLoader的六个方位的图片获取纹理对象cubeTexture,scene背景background设置为cubeTexture。
  • 3、初始化camera相机,定义相机位置 camera.position.set
  • 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.DirectionalLight平行光源,设置平行光源位置,设置平行光源投影,scene添加平行光源。
  • 5、加载几何模型:创建THREE.AxesHelper坐标辅助工具helper,scene场景中加入helper。创建THREE.BoxGeometry立方体几何体geomerty。创建THREE.MeshStandardMaterial标准网格材质material。传入geomerty和material作为参数,创建三个立方体网格对象cube、cube1、cube2,cube使用默认位置,cube1和cube2设置不同位置,scene场景中加入cube、cube1、cube2。
  • 6、创建render方法,实现cube、cube1、cube2立方体的title位置渲染(通过THREE.Vector3的project()方法,实现场景世界坐标和平面二维坐标互转),具体实现参考下面代码样例。
  • 7、加入controls控制,加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learn61(场景世界坐标和平面二维坐标互转)</title>
    <script src="lib/threejs/127/three.js-master/build/three.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/controls/OrbitControls.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/stats.min.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script>
    <script src="lib/js/Detector.js"></script>
</head>
<style type="text/css">
    html, body {
        margin: 0;
        height: 100%;
    }

    canvas {
        display: block;
    }

    .title {
        position: absolute;
        padding: 10px;
        background: rgba(255, 255, 255, 0.5);
        line-height: 1;
        border-radius: 5px;
    }

</style>
<body onload="draw()">
<div class="title one">第一个盒子</div>
<div class="title two">第二个盒子</div>
<div class="title three">第三个盒子</div>
</body>
<script>
  var renderer, camera, scene, gui, light, stats, controls
  var cube, cube2, cube3
  var initRender = () => {
    renderer = new THREE.WebGLRenderer({antialias: true})
    renderer.setClearColor(0xeeeeee)
    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.shadowMap.enabled = true
    renderer.setPixelRatio(window.devicePixelRatio)
    document.body.appendChild(renderer.domElement)
  }
  var initCamera = () => {
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, window.innerHeight, 0.1, 1000)
    camera.position.set(0, 0, 15)
  }
  var initScene = () => {
    var cubeTextureLoader = new THREE.CubeTextureLoader()
    cubeTextureLoader.setPath('data/texture/skybox/space/')
    var cubeTexture = cubeTextureLoader.load([
      'right.jpg', 'left.jpg',
      'top.jpg', 'bottom.jpg',
      'front.jpg', 'back.jpg'
    ])
    scene = new THREE.Scene()
    scene.background = cubeTexture
  }
  var initGui = () => {
  }
  var initLight = () => {
    scene.add(new THREE.AmbientLight(0x444444))

    light = new THREE.DirectionalLight(0xffffff)
    light.position.set(0, 20, 20)
    light.castShadow = true
    scene.add(light)
  }
  var initModel = () => {
    var helper = new THREE.AxesHelper(50)
    scene.add(helper)
    var material = new THREE.MeshStandardMaterial({color: 0x00ffff})
    var geomerty = new THREE.BoxGeometry(1, 1, 1)

    cube = new THREE.Mesh(geomerty, material)
    scene.add(cube)

    cube2 = new THREE.Mesh(geomerty, material)
    cube2.position.set(3, 3, -2)
    scene.add(cube2)

    cube3 = new THREE.Mesh(geomerty, material)
    cube3.position.set(-3, 3, 2)
    scene.add(cube3)
  }

  var initStats = () => {
    stats = new Stats()
    document.body.appendChild(stats.dom)
  }

  var initControls = () => {
    controls = new THREE.OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
  }

  var render = () => {
    let halfWidth = window.innerWidth / 2
    let halfHeight = window.innerHeight / 2
    let vector1 = cube.position.clone().project(camera)
    let vector2 = cube2.position.clone().project(camera)
    let vector3 = cube3.position.clone().project(camera)
    //修改第一个的div的位置
    $(".one").css({
      left: vector1.x * halfWidth + halfWidth,
      top: -vector1.y * halfHeight + halfHeight
    });


    $(".two").css({
      left: vector2.x * halfWidth + halfWidth,
      top: -vector2.y * halfHeight + halfHeight
    });


    $(".three").css({
      left: vector3.x * halfWidth + halfWidth,
      top: -vector3.y * halfHeight + halfHeight
    })
  }

  var onWindowResize = () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window, innerHeight)
  }

  var animate = () => {
    render()
    stats.update()
    controls.update()
    renderer.render(scene, camera)
    requestAnimationFrame(animate)
  }

  var draw = () => {
    if (!Detector.webgl) Detector.addGetWebGLMessage()
    initRender()
    initScene()
    initCamera()
    initLight()
    initModel()
    initStats()
    initControls()
    animate()
    window.onresize = onWindowResize
  }
</script>
</html>

效果如下:
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到