Creating dynamic movement in Three.js using lineTo and curveTo techniques

As a newcomer to three.js and transitioning from Processing/p5.js, I am accustomed to animating loops. My goal is to create a simple stretching pill shape like the one shown in this GIF:

Stretching pill shape

I've managed to put together a basic 'O' shape using various online resources. My challenge now is to make the variable oHeight control the back and forth movement using Math.sin.

Should I be updating the path, bufferGeometry, or the THREE.path in order to achieve this effect?

Apologies for the messy code. I'm still getting the hang of things!

        var camera, scene, renderer;
        var curve;
        var path;
        var oHeight = 0;
        var delta = 0;

        init();
        animate();

        function init() {
            camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
            camera.position.z = 600;
            scene = new THREE.Scene();

            path = new THREE.Path();

            path.lineTo( 0, 0 );
            path.quadraticCurveTo( 0, 20, 20, 20 );
            path.lineTo( 40, 20 );
            path.quadraticCurveTo( 60,20, 60,0);
            path.lineTo(60,-40-oHeight);
            path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
            path.lineTo(20,-60-oHeight);
            path.quadraticCurveTo(0,-60,0,-40-oHeight);
            path.lineTo(0,0);

            var points = path.getPoints();

            var geometry = new THREE.BufferGeometry().setFromPoints( points );
            var material = new THREE.LineBasicMaterial( { color: 0xffffff } );

            curve = new THREE.Line( geometry, material );

            scene.add( curve );

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.body.appendChild( renderer.domElement );
        }

        function animate() {
            requestAnimationFrame( animate );

            delta +=.1;
            oHeight = Math.sin(delta)*20;
            line.needUpdate = true; //is this where I went wrong?

            renderer.render( scene, camera );
        }

Answer №1

Your code is missing an object named line and there is no connection from the object geometry to oHeight. The THREE.Path serves as a temporary object for the necessary information to create the BufferGeoemtry. Keep in mind that the vertices of the geometry end up being stored in an array buffer on the GPU.

To resolve this issue, you must create the path within the animate function and assign it to the BufferGeoemtry. This way, the geometry is regenerated in each frame:

function animate() {
    requestAnimationFrame( animate );

    delta +=.1;
    oHeight = Math.sin(delta)*20;

    path = new THREE.Path();
    path.lineTo( 0, 0 );
    path.quadraticCurveTo( 0, 20, 20, 20 );
    path.lineTo( 40, 20 );
    path.quadraticCurveTo( 60,20, 60,0);
    path.lineTo(60,-40-oHeight);
    path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
    path.lineTo(20,-60-oHeight);
    path.quadraticCurveTo(0,-60-oHeight,0,-40-oHeight);
    path.lineTo(0,0);

    geometry.dispose();
    geometry.setFromPoints( path.getPoints() );

    renderer.render( scene, camera );
}

var camera, scene, renderer;
var curve;
var path;
var oHeight = 0;
var delta = 0;
var geometry;

init();
animate();

function init() {
    camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.z = 600;
    scene = new THREE.Scene();

    geometry = new THREE.BufferGeometry();
    var material = new THREE.LineBasicMaterial( { color: 0xffffff } );

    curve = new THREE.Line( geometry, material );

    scene.add( curve );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    window.onresize = resize;
}

function animate() {
    requestAnimationFrame( animate );

    delta +=.1;
    oHeight = Math.sin(delta)*20;

    path = new THREE.Path();
    path.lineTo( 0, 0 );
    path.quadraticCurveTo( 0, 20, 20, 20 );
    path.lineTo( 40, 20 );
    path.quadraticCurveTo( 60,20, 60,0);
    path.lineTo(60,-40-oHeight);
    path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
    path.lineTo(20,-60-oHeight);
    path.quadraticCurveTo(0,-60-oHeight,0,-40-oHeight);
    path.lineTo(0,0);
    
    geometry.dispose();
    geometry.setFromPoints( path.getPoints() );
    
    renderer.render( scene, camera );
}

function resize() {   
    var aspect = window.innerWidth / window.innerHeight;
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = aspect;
    camera.updateProjectionMatrix();
}
<script src="https://threejs.org/build/three.min.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Understanding how to monitor a Boolean value that fluctuates in real-time within a three.js

Currently, I am working on developing a 3D 4x4x4 tic tac toe game using three.js. In order to determine the win condition for combinations, I have created a boolean array. With a total of 64 blocks (16*4), I have initialized a boolean array of size 64 with ...

Tips for toggling the appearance of like and add to cart icons

I am attempting to create a simple functionality for liking and adding items to a cart by clicking on the icons, which should immediately change the icon's color when clicked. However, I am facing an issue where the parent div's link is also bein ...

What is the best way to retain AJAX data even when navigating back without losing it?

After receiving an Ajax response, I display a set of data on my home page. When I click on any of the data, it takes me to another page. However, when I click the back button on the browser, it just navigates me back to the homepage without showing the A ...

The webpage becomes unresponsive and gets stuck when sending a stream of requests to the web server via ajax

I am currently working on creating a signal on the webpage that displays either a green or red color based on values retrieved from a database. However, when I send a request after 10 seconds, the page appears to freeze and becomes unresponsive. I am strug ...

Upon its second use, Ajax is loaded with cached data

Imagine a table with multiple rows, each row containing a SHOW button that reveals hidden content when clicked. The hidden div (with the classname "Content") loads the content of a second page using ajax and the id of the corresponding table row. However, ...

Converting a 'div' element into a dropdown menu with CSS and Jquery

I am facing a challenge where I have a collection of buttons enclosed in a div that I want to resemble a dropdown: <div id = "group"> <label> Group: </ label> <div value =" 1hour "> 1h < / div> <div value =" 2hou ...

Can pins be added or removed from a location plan (image or vector) using either Javascript or the DevExpress library?

At the factory where I am employed, there are close to 1000 cameras in operation. I have requested to have the locations of these cameras marked on a non-geographical map of the factory. By simply clicking on one of the camera icons, it should be possible ...

React and Material-UI issue: Unable to remove component as reference from (...)

My React components are built using Material-UI: Everything is running smoothly MainView.js import React, { Component } from 'react'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import { List, ListItem } from ...

Ways to trigger a function when the body is loaded

In this snippet, I am attempting to execute the oauth2_login() function when the body loads, which is intended to log in the user. Currently, I have hardcoded values from the database into the username and password fields. <!DOCTYPE html> <html&g ...

The conditional statement for ajax is malfunctioning

I am encountering an issue with some ajax coding. The if condition is not working as expected - whenever the program runs, only the else statement gets executed even when the if statement should be satisfied. <script type="text/javascript> funct ...

Verify whether the input from ng-model is numeric

When utilizing ng-model binding in an input field, data is usually stored as a string. Is there a way to verify if the user has entered a number? ...

Trouble with jQuery addClass function when trying to add to a specific object variable

I'm attempting to give an error class to an input textbox to inform the user that their input is invalid. Within the change event, I am referencing what seems to be the input field and storing it in a variable. However, calling addClass on the var ...

Assigning numerical ratings to a web-based questionnaire in HTML

In my questionnaire, I have radio buttons and checkboxes that need to be graded. The format of the input elements looks like this: <input type="radio" name="1" value="Yes" onclick="document.getElementById('pls').setAttribute('requi ...

The error message "Element is not defined (Object.<anonymous>)" is occurring in the context of Intro.js-react, React, Next.js, and Tailwind

Here is a code snippet: import { useState } from 'react'; import { Steps } from 'intro.js-react'; export default function Dashboard() { const [stepEnabled, setStepEnabled] = useState(true); const steps = [ { intro: &apos ...

Ensure that a string contains only one instance of a specific substring

I need a function that removes all instances of a specific substring from a string, except for the first one. For example: function keepFirst(str, substr) { ... } keepFirst("This $ is some text $.", "$"); The expected result should be: This $ is some tex ...

What could be the reason why my useRouter function isn't working as expected?

I'm currently working on developing an App using nextjs 13 and the new App router feature (https://nextjs.org/blog/next-13-4) : I've encountered a navigation issue despite following the documentation diligently. To illustrate, here's a bas ...

Here's a way to programmatically append the same icon to multiple li elements generated using document.createElement:

I am new to creating a to-do app and need some guidance. When a user enters a task, I successfully create a list item for that task. However, I am unsure how to add a delete icon next to the newly created li element. Can someone please help me out? Below ...

Conceal the href element within a designated UL using JavaScript

Is there a way to only hide the href element in a specific UL element, rather than hiding all href elements with the same class name? Let's consider an example HTML code: <ul class="UL_tag"> <li>Text 1</li> <li>Text 2< ...

The dialog encountered an error due to an invalid function

I am currently encountering a TypeError: $("").html("This dialog will show every time!").dialog is not a function. This error occurs when the page is loaded using load() in a div on the index page. I have made sure to include the necessary jQuery scripts o ...

Tips for creating a dynamic route with NextJs 14 API

Looking to start a blog with Next.js 14 and I'm working on defining a function in api/posts/[postSlug]/route.js. How do I access the postSlug parameter within this function? Here's my current function code: // api/posts/[postSlug]/route.js impor ...