【问题标题】:(Intergrate P5.js and Three.js) --- Create a ThreeJS scene with animations from P5.js library?(集成 P5.js 和 Three.js)--- 使用 P5.js 库中的动画创建 ThreeJS 场景?
【发布时间】:2019-11-29 20:35:21
【问题描述】:

在我们开始之前,您可能想阅读我之前的帖子,该帖子导致了这个问题的产生:

Drawing/Rendering 3D objects with epicycles and fourier transformations [Animation]

上下文:

使用 P5.js 库并遵循 The Coding Train (Coding Challenge #130.1 --> #130.3) 的教程,我能够使用本轮和傅立叶变换为任何参数绘图设置动画并重新创建。 (阅读上一篇文章,相信我,它会有所帮助)

我现在希望将其扩展到三个维度!

一位乐于助人的社区成员建议将 3D 绘图分成两个平面。这样,我不必编写新代码,并且可以使用我预先存在的 2D 代码!酷吧!

另一位用户建议使用 Three.JS 库为此过程创建 3D 场景。

到目前为止,我已经创建了 3 架飞机。我想基本上将这些飞机用作电视屏幕。然后我可以在电视屏幕上显示我用 P5js 编写的 2D 版本,并在 3D 空间中投影一个新点以生成/绘制新的 3D 绘图。

<html>
  <head>
    <title>Epicyclic Circles</title>
    <style>
      body { margin: 0; }
      canvas { width: 100%; height: 100% }
    </style>
  </head>
  <body>

    <script src="https://rawgit.com/mrdoob/three.js/dev/build/three.js"></script>
    <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>

    <script>

      // Set up the basic scene, camera, and lights.

      var scene = new THREE.Scene();
      scene.background = new THREE.Color( 0xf0f0f0 );

      var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
      scene.add(camera)

      var light = new THREE.PointLight( 0xffffff, 0.8 );
      camera.add( light );

      camera.position.z = 50;

      var renderer = new THREE.WebGLRenderer();
      renderer.setSize( window.innerWidth, window.innerHeight );
      document.body.appendChild( renderer.domElement );

      // Add the orbit controls to permit viewing the scene from different angles via the mouse.

      controls = new THREE.OrbitControls( camera, renderer.domElement );
      controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
      controls.dampingFactor = 0.25;
      controls.screenSpacePanning = false;
      controls.minDistance = 0;
      controls.maxDistance = 500;

      // Create center and epicyclic circles, extruding them to give them some depth.

      var plane = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 );
var helper = new THREE.PlaneHelper( plane, 50, 0x696969 );
scene.add( helper );


var plane2 = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), 0 );
var helper2 = new THREE.PlaneHelper( plane2, 50, 0xE06666 );
scene.add( helper2 );


var plane3 = new THREE.Plane( new THREE.Vector3( 0, 0, 1 ), 0 );
var helper3 = new THREE.PlaneHelper( plane3, 50, 0xD85C6 );
scene.add( helper3 );

var size = 10;
var divisions = 10;

var gridHelper = new THREE.GridHelper( size, divisions );
scene.add( gridHelper );






      var animate = function () {
        requestAnimationFrame( animate );

        // During each animation frame, let's rotate the objects on their center axis,  
        // and also set the position of the epicyclic circle.

        renderer.render( scene, camera );
      };

      animate();
    </script>
  </body>
</html>

也欢迎任何其他建议/方法! :D

回顾:

  • 如何在 ThreeJs 屏幕中显示 P5js 动画
  • 如何让它们使用相同的坐标系(p5 使用 X 和 Y 像素)

【问题讨论】:

  • 您的流程需要执行的一项任务是在进入animate 循环之前创建场景中所需的所有形状/网格。根据您的 P5 代码,您似乎已经计算了幅度和相位。您可以使用振幅来创建圆形/网格,方法与上一篇文章相同(即new THREE.Shape, THREE.extrudeGeometry, and THREE.mesh)。在位置 0,0,0 创建所有这些,并从 X,Y 平面开始以保持简单。然后,在animate 循环中,您将根据时间增量设置所有圈子的位置。
  • 即,您不必像重新使用 P5 计算以应用于 three.js 框架那样集成 P5。另外,请注意,当您开始在其他平面上工作时,您创建的圆形/网格最初需要旋转 90 度以符合 X-Z 和 Y-Z 平面。 (例如,在上一个问题中,将mesh1.rotateX(Math.PI / 2) 添加到animate 循环之前的代码中,您将看到中心圆旋转到Y-Z 平面。)
  • 好的,一旦我这样做了。如何添加从中间不同圆圈相交的线以生成一个点。我怎样才能追踪这个点以最终绘制这个形状?我一直在搞乱threeJS,并慢慢掌握了它的窍门:) 谢谢

标签: javascript html animation three.js p5.js


【解决方案1】:

我认为是您的基本概念。信不信由你,超过 50% 的工作涉及解决与运动中重叠透明对象相关的抖动问题,这是 three.js 有点薄弱的领域。但是,经过一番搜索后,可以通过调整对象的 Z 对齐和 renderOrder 来缓解抖动问题。

无论如何,看看下面的代码,它扩展了你的努力,引入了 5 个随机大小和旋转的透明圆圈。画线请看以下链接https://threejs.org/docs/#manual/en/introduction/How-to-update-things

<html>
  <head>
    <title>Epicyclic Circles</title>
    <style>
      body { margin: 0; }
      canvas { width: 100%; height: 100% }
    </style>
  </head>
  <body>

    <script src="https://rawgit.com/mrdoob/three.js/dev/build/three.js"></script>
    <script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>

    <script>

      // Set up the basic scene, camera, and lights.

      var scene = new THREE.Scene();
      scene.background = new THREE.Color( 0xf0f0f0 );

      var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
      scene.add(camera)

      var light = new THREE.PointLight( 0xffffff, 0.8 );
      camera.add( light );

      camera.position.z = 200;

      var renderer = new THREE.WebGLRenderer();
      renderer.setSize( window.innerWidth, window.innerHeight );
      document.body.appendChild( renderer.domElement );

      // Add the orbit controls to permit viewing the scene from different angles via the mouse.

      controls = new THREE.OrbitControls( camera, renderer.domElement );
      controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
      controls.dampingFactor = 0.25;
      controls.screenSpacePanning = false;
      controls.minDistance = 0;
      controls.maxDistance = 500;

      function createCircleMesh(plane, radius, depth, meshColor, meshOpacity) {
          let extrudeSettings = { depth: depth, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: .25, bevelThickness: .25 };

          let arcShape = new THREE.Shape();
          arcShape.moveTo( 0, 0 );
          arcShape.absarc( 0, 0, radius, 0, Math.PI * 2, false );
          let holePath = new THREE.Path();
          holePath.moveTo( 0, radius * 0.75 );
          holePath.absarc( 0, radius * 0.75, radius * 0.20, 0, Math.PI * 2, true );
          arcShape.holes.push( holePath );
            
          var geometry = new THREE.ExtrudeBufferGeometry( arcShape, extrudeSettings );
          var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial({color: meshColor, roughness: 1, metalness: 0, transparent: meshOpacity !== 1, opacity: meshOpacity}) );
          scene.add( mesh );
          
          if (plane === "XZ") {
            mesh.rotateX(Math.PI / 2);
          } else if (plane === "YZ") {
            mesh.rotateY(Math.PI / 2);
          }
          return mesh;
      }
      
      // Create an array of circles and their meshes.
      circle = [];
      for (let i = 0; i < 5; i++) {
      
          let r = 5 - i;
          
          circle[i] = {
              radius: r*10 + Math.random() * r * 10,
              rotationRate: (Math.random() * 2 * Math.PI - Math.PI) / 100
          };

          // RenderOrder is stepped to reduce dithering.
          circle[i].mesh = createCircleMesh("XY", circle[i].radius, 5, 0xff0000, 0.5);
          circle[i].mesh.renderOrder = i;
          
          circle[i].centerMesh = createCircleMesh("XY", 5, 2, 0xff0000, 1);
          if (i === 0) {
              circle[i].centerX = circle[i].radius;
              circle[i].centerY = circle[i].radius;
              circle[i].centerZ = i;  // Offset the meshes to reduce dithering.
          } else {
              circle[i].centerX = circle[i-1].centerX + circle[i-1].radius;
              circle[i].centerY = circle[i-1].centerY;
              circle[i].centerZ = i;  // Offset the meshes to reduce dithering.
          }
          circle[i].rotated = 0;
      }

      // Set up "viewing" planes.
      
      var plane = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 );
      var helper = new THREE.PlaneHelper( plane, 500, 0x696969 );
      scene.add( helper );

      var plane2 = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), 0 );
      var helper2 = new THREE.PlaneHelper( plane2, 500, 0xE06666 );
      scene.add( helper2 );

      var plane3 = new THREE.Plane( new THREE.Vector3( 0, 0, 1 ), 0 );
      var helper3 = new THREE.PlaneHelper( plane3, 500, 0xD85C6 );
      scene.add( helper3 );

      var size = 250;
      var divisions = 10;

      var gridHelper = new THREE.GridHelper( size, divisions );
      scene.add( gridHelper );

      var animate = function () {
        requestAnimationFrame( animate );

        // During each animation frame, let's rotate the objects.
        
        for (let i = 0; i < 5; i++) {
            let c = circle[i];
            
            c.rotated += c.rotationRate;
            if (0 < i) {
                c.centerX = circle[i-1].centerX + circle[i-1].radius * Math.cos(circle[i-1].rotated);
                c.centerY = circle[i-1].centerY + circle[i-1].radius * Math.sin(circle[i-1].rotated);
            }
            
            // Note that due to the stepping of the meshes to reduce dithering, it is necessary
            // to alter the step (via Math.sign(camera.position.z)) if we're looking via the backside.
            c.mesh.rotateZ(c.rotationRate);
            c.mesh.position.set(c.centerX, c.centerY, c.centerZ * Math.sign(camera.position.z));
            c.centerMesh.position.set(c.centerX, c.centerY, c.centerZ * Math.sign(camera.position.z));            
            
        }

        renderer.render( scene, camera );
      };

      animate();
    </script>
  </body>
</html>

这可能会比在 Stackoverflow 中的小视口中看起来更好。

希望这对您有所帮助。

【讨论】:

  • 当然可以,谢谢。稍后我会就我取得的任何进展与您联系。
【解决方案2】:

在 p5.js 中使用 WEBGL 模式,而不是使用 three.js。 示例:

let t
function setup(){
  createCanvas(400,400,WEBGL)
//w = width of plane
//h = height of plane
  t = createGraphics(w,h)
}

function draw(){
  background(0)
 //To draw to the texture use t. before any drawing function
  texture(t)
  plane(w,h)
}

观看 Coding Train 关于 p5.js 中 WEBGL 的播放列表,

link to the videos.

如果你真的想用 THREE.js,IDK 怎么用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多