3D textile simulation powered by three.js

My current project involves using three.js to develop a cloth simulator similar to the one on the Hermes website. The main difference is that I want to implement top-down waves instead of horizontal waves like the ones on the Hermes site.

I have successfully implemented vertical waves as desired (you can view it live here, and the code snippet is provided below). However, the top side is not fixed and moves slightly; I aim to fix this so that it remains stationary like on the Hermes website. Additionally, I would like to make the wave continuous rather than just occurring once when the webpage loads. Furthermore, I have noticed a strange issue where my modified version shrinks in size (height & width) after being open in the browser for 5-10 minutes. I'm unsure why this happens!

Is there an expert here who can assist me with these three tasks?

  • Fix the top side like on Hermes
  • Make the waves continuous
  • Prevent the size reduction

function Particle( x, y, z, mass, drag, clothFunction ) {

    // Code for particle function goes here

}

// Additional functions and logic go here

productAnimation.play();
<script src="http://maksible.com/cloth/cloth_slower_v2/cloth/three.min.js"></script>
<body>
    <div id="product-container"></div>
    <script type="text/javascript" src="three.min.js"></script>
    <script type="text/javascript" src="logic.js"></script>
</body>

Answer №1

Presenting a solution using three.js, albeit with a different approach from yours. I hope you find it beneficial.

var size = 500;
var img = 'Image.jpg';

window.onload = function() {

      initializeWebGL();
      render();

    }

    // rendering function
    //
    function render() {

      requestAnimationFrame( render );

      if(window.mat)
        mat.uniforms.time.value = getTimeNow();

      ctx.render( scn, cam );

    }

    // creating WebGL renderer
    //
    function initializeWebGL() {

      // checking for desktop/mobile platform
      window.desk = !(/Android|webOS|iPhone|iPad|BlackBerry|Windows Phone|Opera Mini|IEMobile|Mobile/i.test(navigator.userAgent));

      window.ctx = new THREE.WebGLRenderer({antialias:window.desk});
      ctx.setClearColor( 0xffffff );
      ctx.setPixelRatio( window.devicePixelRatio );
      ctx.setSize( size, size );

      // camera setup
      window.cam = new THREE.PerspectiveCamera( 90, 1, 1, 30 );
      cam.position.z = 25;

      // scene initialization
      window.scn = new THREE.Scene();

      // canvas creation
      window.cvs = createCanvas();
      scn.add( cvs );
      loadTextureFromCanvas( img );

      // clear the viewport
      ctx.render( scn, cam );
      document.body.appendChild( ctx.domElement );

    }

    // function to get current time
    //
    function getTimeNow(){

      return performance.now() * 0.001;

    }

    // loading texture from canvas
    //
    function loadTextureFromCanvas( path ) {

      if(window.tex)
        window.tex.dispose();

      cvs.visible = false;

      window.tex = new THREE.TextureLoader().load( path, function(){
        cvs.visible = true;
      });
      window.tex.anisotropy = ctx.getMaxAnisotropy();
      window.mat.uniforms.tex.value = window.tex;

    }

    // creating canvas element
    //
    function createCanvas() {

      window.mat = new THREE.RawShaderMaterial({
        uniforms: {
          time: { value: getTimeNow() },
          tex: { value: null }
        },
        vertexShader: 'precision mediump float;precision mediump int;uniform mat4 modelViewMatrix;'+
          'uniform mat4 projectionMatrix;attribute vec2 pos;uniform float time;varying vec2 uv;varying float amb;'+
          'float d(float y){return cos(sin(time/2.)+time/2.+y/2.14)*sin(time+y/4.17)*(.5-y/40.)*1.5;}'+
          'void main(){vec3 p=vec3( pos.x+sin(time/3.)*(.5-pos.y/40.), pos.y+sin(time)*(.5-pos.y/40.)/2., d(pos.y));amb=(d(pos.y-1.)-d(pos.y+1.))/4.;'+ 
          'uv=vec2(pos.x/40.+.5,pos.y/40.+.5);gl_Position=projectionMatrix*modelViewMatrix*vec4(p,1.);}',
        fragmentShader: 'precision mediump float;precision mediump int;uniform sampler2D tex;varying vec2 uv;varying float amb;'+
          'void main(){vec4 col=texture2D(tex,uv)+amb;gl_FragColor=vec4(col.xyz,1.);}'
      });

      var d = 40,d2=~~(d/2),i,j,k,n,fi,v,m,z1=-1,z2;

      fi = new Uint16Array( d * d * 6 );
      v = new Int8Array( (d+1) * (d+1) * 2 );
      for(j=0;j<=d;j++)
        for(i=0;i<=d;i++) {
          k = i + j*(d+1);
          v[k*2] = i - d2;
          v[k*2+1] = j - d2;
          if(i<d&&j<d) {
            n = (i + j*d) * 6;
            fi[n] = k;
            fi[n+1] = k + 1;
            fi[n+2] = k + d + 1;
            fi[n+3] = k + d + 1;
            fi[n+4] = k + 1;
            fi[n+5] = k + d + 2;
          }
        }

      for(i=0,j=-1;i<fi.length;i++)
        if(j<fi[i])
          j = fi[i];

      m = new THREE.Mesh( new THREE.BufferGeometry(), mat );
      m.geometry.setIndex( new THREE.BufferAttribute( fi, 1 ));
      m.geometry.addAttribute( 'pos', new THREE.BufferAttribute( v, 2 ));

      return m;

    }

Replace your existing logic code with this and execute. Cheers!

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

Is there a way to resolve this issue? (An error occurred: TypeError - res.json is not a valid function)

When attempting to add an object to my MongoDB database const response = await fetch("/api/contact", { method: "POST", body: JSON.stringify(data), headers: { "Content-Type": "application/json", }, }); I encounter the error message ...

What's the best approach: Backbone-Relational discovery or retrieval?

Although the model caching feature in Backbone-Relational is effective, loading a simple model securely requires considerable code. For example: // Attempt to locate a model in the cache this.model = MyModel.find({id:id}); if(this.model){ // Model re ...

Exploring the dynamics of Django, Webpack, and Vue with the added feature of code splitting: A guide to customizing chunk

I am currently using Django in conjunction with Webpack and Vue, as well as implementing Code splitting within Webpack. The issue I am facing is that Webpack splits chunk files from the source code of .vue files, but I am unable to load these chunk files i ...

Optimize Vue code by utilizing constants from methods in computed properties

I don't have an issue, but I'm curious to find out if there is a way to streamline this code: ddd In the canDelete() function, I now require the isOwner parameter as well. I ended up duplicating the code from the canUserApprove() method, which ...

Issue encountered: Inability to implement asynchronous functionality within a forEach loop while making an API request

When making a GET API call, the code looks like this router.get('/review', async (req, res) => { try { const entity = await Entity.find(); const entityId = []; Object.keys(entity).forEach((key) => { entityId.push(entity[ ...

'jQuery' is not recognized as defined, error no-undef

I am currently working on a file that utilizes jQuery for testing purposes: (function($) { "use strict"; // Start of use strict // Configure tooltips for collapsed side navigation $('.navbar-sidenav [data-toggle="tooltip"]').tooltip({ ...

The issue of memory leakage caused by jQuery Ajax requests

A problem has arisen on my website where memory is being leaked in both IE8 and Firefox. The Windows Process Explorer shows a continuous growth in memory usage over time. The issue arises when the page requests the "unplanned.json" URL, which is a static ...

What is the best way to incorporate an ID from a scala template into an AJAX request?

In my application built on the Play Framework 2.3.8, users can input questions and answers. The view class receives a List[Question] which is iterated through using a for each loop to display them: @for(question <- questionList){ <!-- Questions --& ...

Using JavaScript and node.js, make sure to wait for the response from socket.on before proceeding

My task involves retrieving information from the server on the client side. When a client first connects to the server, this is what happens: socket.on('adduser', function(username){ // miscellaneous code to set num_player and other variabl ...

In search of a hover functionality similar to what can be found on Stack Overflow

I am really impressed by the hover effects on StackOverflow. I would love to incorporate a similar feature into my own web application. Can anyone provide me with more information? What is this feature called? Are there any libraries available for it? I h ...

What's preventing my Angular list from appearing?

I am currently developing an Angular project that integrates Web API and entity framework code first. One of the views in my project features a table at the bottom, which is supposed to load data from the database upon view loading. After setting breakpoin ...

Changing the counter using dual buttons in Vue.js

I am facing an issue with updating the counter when using both the add and remove buttons. The add button functions correctly, but unfortunately, the delete button does not update the counter as expected. Below is a picture showcasing the problem at hand: ...

Clicking on the (x) button element will eliminate the DOM node from a list

https://i.stack.imgur.com/GxVYF.png A value is being dynamically added to my page, and here is the code snippet: function favJobs(data){ number_of_jobs_applied = data.total_bookmarked; $('.bookmark-title').append(number_of_jobs_applied, " ...

Error: Encountered an unexpected asterisk symbol while trying to import a Sequelize model from the

Currently, I am developing an application that requires me to connect and run queries on an SQL server using Sequelize. I have set up migrations, seeders, and models by utilizing sequelize init. However, when attempting to generate model objects with const ...

Setting up a personalized JSPM registry configuration

I have chosen to use Verdaccio as the platform for hosting a private package. In my current project, I am looking to incorporate this package locally. The package has been successfully published and is now hosted on Verdaccio running on localhost (http://l ...

Is it a shallow copy or something else when updating state in React JS?

I am currently dealing with a particular state within my application: const [work, setWork] = useState([ { company: "Company", position: "President", website: "example.com", startDate: "2013-01-01", endDate: "2014-01- ...

Retrieving the checkbox's status from the database

I have implemented a basic checkbox that updates its state in the database when clicked or unclicked. Is there a way to retain this state and have it displayed as checked if the page is refreshed? Essentially, I want the checkbox to remember its last state ...

Leveraging Backbone.js without using client-side JavaScript

Exploring the idea of using Backbone.js and node.js to develop a compact web application. The concept of sharing code between the client and server is quite appealing. The challenge arises when considering how users without JavaScript-enabled browsers (in ...

Failure to properly format the correct regular expression match in JSON using JavaScript

Issue with Regular Expressions: I am currently using regex to extract information from a text file and convert it into a JSON document. The data is being extracted from console logs. The problem lies in the condition (regex_1_match && regex_2_mat ...

An error was encountered in the index.js file within the app directory when running the webpack

Recently, I was told to learn react.js even though my knowledge of javascript is limited. Nevertheless, I decided to dive in and start with a simple "Hello World" project. Initially, when I used the index.js file below and ran webpack -p, everything worke ...