(集成 P5.js 和 Three.js) --- 使用 P5.js 库中的动画创建 ThreeJS 场景? [英] (Intergrate P5.js and Three.js) --- Create a ThreeJS scene with animations from P5.js library?

查看:29
本文介绍了(集成 P5.js 和 Three.js) --- 使用 P5.js 库中的动画创建 ThreeJS 场景?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<头><title>周转圈</title><风格>正文{边距:0;}画布{宽度:100%;高度:100% }</风格><身体><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><脚本>//设置基本场景、相机和灯光.var scene = new THREE.Scene();场景背景=新三色(0xf0f0f0);var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );场景.添加(相机)var light = new THREE.PointLight(0xffffff, 0.8);相机.添加(光);相机.位置.z = 50;var renderer = new THREE.WebGLRenderer();renderer.setSize( window.innerWidth, window.innerHeight );document.body.appendChild(renderer.domElement);//添加轨道控件以允许通过鼠标从不同角度查看场景.控件 = 新的 THREE.OrbitControls(camera, renderer.domElement);control.enableDamping = true;//启用阻尼或自动旋转时需要动画循环control.dampingFactor = 0.25;control.screenSpacePanning = false;控制.minDistance = 0;控制.maxDistance = 500;//创建中心圆和行星圆,挤压它们以赋予它们一定的深度.var plane = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 );var helper = new THREE.PlaneHelper(plane, 50, 0x696969);场景添加(助手);var plane2 = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), 0 );var helper2 = new THREE.PlaneHelper(plane2, 50, 0xE06666);场景.添加( helper2 );var plane3 = new THREE.Plane( new THREE.Vector3( 0, 0, 1 ), 0 );var helper3 = new THREE.PlaneHelper(plane3, 50, 0xD85C6);场景.添加( helper3 );变量大小 = 10;var 划分 = 10;var gridHelper = new THREE.GridHelper( size, Divisions );场景.添加( gridHelper );var animate = 函数 () {requestAnimationFrame( 动画 );//在每个动画帧中,让我们围绕它们的中心轴旋转对象,//并设置行星轮的位置.renderer.render(场景,相机);};动画();

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

回顾:

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

解决方案

对我认为的基本概念进行了更多的探讨.信不信由你,超过 50% 的工作涉及解决与运动中重叠透明对象相关的抖动问题,这是three.js 有点弱的领域.但是,经过一些搜索,您可以通过调整对象的 Z 对齐和渲染顺序来缓解抖动问题.

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

<头><title>周转圈</title><风格>正文{边距:0;}画布{宽度:100%;高度:100% }</风格><身体><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><脚本>//设置基本场景、相机和灯光.var scene = new THREE.Scene();场景背景=新三色(0xf0f0f0);var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );场景.添加(相机)var light = new THREE.PointLight(0xffffff, 0.8);相机.添加(光);相机.位置.z = 200;var renderer = new THREE.WebGLRenderer();renderer.setSize( window.innerWidth, window.innerHeight );document.body.appendChild(renderer.domElement);//添加轨道控件以允许通过鼠标从不同角度查看场景.控件 = 新的 THREE.OrbitControls(camera, renderer.domElement);control.enableDamping = true;//启用阻尼或自动旋转时需要动画循环control.dampingFactor = 0.25;control.screenSpacePanning = false;控制.minDistance = 0;控制.maxDistance = 500;函数 createCircleMesh(平面,半径,深度,meshColor,meshOpacity){让 extrudeSettings = { depth: depth, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: .25, bevelThickness: .25 };让 arcShape = new THREE.Shape();arcShape.moveTo( 0, 0 );arcShape.absarc( 0, 0, radius, 0, Math.PI * 2, false );让holePath = new THREE.Path();孔路径.moveTo(0,半径* 0.75);holePath.absarc( 0, 半径 * 0.75, 半径 * 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({颜色:meshColor,粗糙度:1,金属度:0,透明:meshOpacity!== 1,不透明度:meshOpacity}));场景添加(网格);如果(平面 ===XZ"){mesh.rotateX(Math.PI/2);} else if (plane === "YZ") {mesh.rotateY(Math.PI/2);}返回网格;}//创建一组圆及其网格.圈 = [];for (让 i = 0; i <5; i++) {让 r = 5 - i;圈[i] = {半径:r*10 + Math.random() * r * 10,旋转率:(Math.random() * 2 * Math.PI - Math.PI)/100};//RenderOrder 被步进以减少抖动.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);如果(我 === 0){circle[i].centerX = circle[i].radius;circle[i].centerY = circle[i].radius;圆[i].centerZ = i;//偏移网格以减少抖动.} 别的 {circle[i].centerX = circle[i-1].centerX + circle[i-1].radius;circle[i].centerY = circle[i-1].centerY;圆[i].centerZ = i;//偏移网格以减少抖动.}圈[i].rotated = 0;}//设置查看"平面.var plane = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 );var helper = new THREE.PlaneHelper(plane, 500, 0x696969);场景添加(助手);var plane2 = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), 0 );var helper2 = new THREE.PlaneHelper(plane2, 500, 0xE06666);场景.添加( helper2 );var plane3 = new THREE.Plane( new THREE.Vector3( 0, 0, 1 ), 0 );var helper3 = new THREE.PlaneHelper(plane3, 500, 0xD85C6);场景.添加( helper3 );变量大小 = 250;var 划分 = 10;var gridHelper = new THREE.GridHelper( size, Divisions );场景.添加( gridHelper );var animate = 函数 () {requestAnimationFrame( 动画 );//在每个动画帧中,让我们旋转对象.for (让 i = 0; i <5; i++) {让 c = circle[i];c.rotated += c.rotationRate;如果 (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);}//请注意,由于网格的步进以减少抖动,因此有必要//如果我们从背面看,则更改步骤(通过 Math.sign(camera.position.z)).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(场景,相机);};动画();</html>

这可能看起来更好全屏,而不是在 Stackoverflow 中的小视口中.

希望这对您有所帮助.

Before we begin, you may want to read my previous post which lead to the creation of this question:

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

Context:

Using the P5.js library and following a tutorial from The Coding Train (Coding Challenge #130.1 --> #130.3) i was able to animate and recreate any parametric drawing using epicycles and fourier transforms. (Read the Previous Post, trust me, it will help)

I am now looking to expand this to three Dimensions!

A helpful community member suggested breaking the 3D drawing into two planes. This way, i dont have to write new code, and could use my preexisting 2D code! cool right!

Another User suggested using the Three.JS library to create a 3D scene for this process.

So Far i have created 3 planes. I would like to essentially use these planes as TV Screens. TV screens where i can then display my 2D version from written in P5js and project a new point in 3D space to generate/draw a new 3D drawing.

<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>

Any other suggestions/Methods are welcomed too! :D

Recap:

  • How do i display P5js animations in my ThreeJs screen
  • How can i make them use the same coordinate system (p5 is using X and Y pixels)

解决方案

Dabbled a bit more with what I think is your basic concept. Believe it or not, more than 50% of the effort involved working around dithering issues associated with overlapping transparent objects in motion, an area where three.js is a bit weak. But, after a bit of searching, one can mitigate the dithering issues with adjustments to the Z alignment of the objects and the renderOrder.

In any event, take a look at the code below, which extends your effort, introducing 5 randomly sized and rotating transparent circles. For drawing lines, take a look at the following link 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>

This might look better full screen rather than in the small viewport within Stackoverflow.

Hope this helps you along your way.

这篇关于(集成 P5.js 和 Three.js) --- 使用 P5.js 库中的动画创建 ThreeJS 场景?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆