1

Here is the demo but it always says that I am missing the modules whereas I have all the dependancies : https://tympanus.net/codrops/2020/02/11/how-to-create-a-physics-based-3d-cloth-with-cannon-js-and-three-js/

Would anyone know how to code it on your computer from the sandbox example?

In all my js files calling 'three'; i get "Uncaught SyntaxError: Cannot use import statement outside a module".

<!DOCTYPE html>
<html>
  <head>
    <title>Physics Slideshow - 03</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app">
      <section class="container">
        <article class="tile">
          <figure class="tile__figure">
            <img
              src="https://images.unsplash.com/photo-1541737923-4dc81f2d1d41?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3334&q=80"
              class="tile__image"
              alt="My image"
              width="400"
            />
          </figure>
        </article>
      </section>

      <canvas id="stage"></canvas>
    </div>

    <script src="src/index.js"></script>
  </body>
</html>

<—— figure.js——>

import * as THREE from "three";
import C from "cannon";

const size = 8;
const mass = 1;

export default class Figure {
  constructor(scene, world) {
    this.$image = document.querySelector(".tile__image");
    this.$image.style.opacity = 0;

    this.scene = scene;
    this.world = world;

    this.loader = new THREE.TextureLoader();

    this.image = this.loader.load(this.$image.src);

    this.sizes = new THREE.Vector2(0, 0);
    this.offset = new THREE.Vector2(0, 0);
    this.bufferV = new THREE.Vector3();
    this.bufferV2 = new C.Vec3();

    this.getSizes();

    this.createMesh();
    this.createStitches();
  }

  getSizes() {
    const { width, height, top, left } = this.$image.getBoundingClientRect();

    this.sizes.set(width, height);
    this.offset.set(
      left - window.innerWidth / 2 + width / 2,
      -top + window.innerHeight / 2 - height / 2
    );
  }

  createMesh() {
    this.geometry = new THREE.PlaneBufferGeometry(1, 1, size, size);
    this.material = new THREE.MeshBasicMaterial({
      map: this.image
    });

    this.mesh = new THREE.Mesh(this.geometry, this.material);

    this.mesh.position.set(this.offset.x, this.offset.y, 0);
    this.mesh.scale.set(this.sizes.x, this.sizes.y, 1);

    this.scene.add(this.mesh);
  }

  createStitches() {
    const particleShape = new C.Particle();
    const { position } = this.geometry.attributes;
    const { x: width, y: height } = this.sizes;

    this.stitches = [];

    for (let i = 0; i < position.count; i++) {
      const row = Math.floor(i / (size + 1));

      const pos = new C.Vec3(
        position.getX(i) * width,
        position.getY(i) * height,
        position.getZ(i)
      );

      const stitch = new C.Body({
        mass: row === 0 ? 0 : mass / position.count,
        linearDamping: 0.8,
        position: pos,
        shape: particleShape
      });

      this.stitches.push(stitch);
      this.world.addBody(stitch);
    }

    for (let i = 0; i < position.count; i++) {
      const col = i % (size + 1);
      const row = Math.floor(i / (size + 1));

      if (col < size) this.connect(i, i + 1);
      if (row < size) this.connect(i, i + size + 1);
    }
  }

  connect(i, j) {
    const c = new C.DistanceConstraint(this.stitches[i], this.stitches[j]);

    this.world.addConstraint(c);
  }

  applyWind(wind) {
    const { position } = this.geometry.attributes;

    for (let i = 0; i < position.count; i++) {
      const stitch = this.stitches[i];

      const windNoise = wind.flowfield[i];
      const tempPosPhysic = this.bufferV2.set(
        windNoise.x,
        windNoise.y,
        windNoise.z
      );

      stitch.applyForce(tempPosPhysic, C.Vec3.ZERO);
    }
  }

  update() {
    const { position } = this.geometry.attributes;
    const { x: width, y: height } = this.sizes;

    for (let i = 0; i < position.count; i++) {
      const p = this.bufferV.copy(this.stitches[i].position);

      position.setXYZ(i, p.x / width, p.y / height, p.z);
    }

    position.needsUpdate = true;
  }
}

<—— scene.js——>

import * as THREE from "three";
import Figure from "./Figure";
import Wind from "./Wind";
import C from "cannon";

const perspective = 800;

export default class Scene {
  constructor() {
    this.container = document.getElementById("stage");

    this.scene = new THREE.Scene();
    this.world = new C.World();
    this.world.gravity.set(0, -1000, 0);

    this.renderer = new THREE.WebGLRenderer({
      canvas: this.container,
      alpha: true
    });

    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.renderer.setPixelRatio(window.devicePixelRatio);

    this.initLights();
    this.initCamera();

    this.figure = new Figure(this.scene, this.world);
    this.wind = new Wind(this.figure.mesh);

    this.update();
  }

  initLights() {
    const ambientlight = new THREE.AmbientLight(0xffffff, 2);
    this.scene.add(ambientlight);
  }

  initCamera() {
    const fov =
      (180 * (2 * Math.atan(window.innerHeight / 2 / perspective))) / Math.PI;

    this.camera = new THREE.PerspectiveCamera(
      fov,
      window.innerWidth / window.innerHeight,
      1,
      5000
    );
    this.camera.position.set(0, 0, perspective);
  }

  update() {
    if (
      this.renderer === undefined ||
      this.scene === undefined ||
      this.camera === undefined
    )
      return;
    requestAnimationFrame(this.update.bind(this));

    this.wind.update();
    this.figure.update();
    this.figure.applyWind(this.wind);
    this.world.step(1 / 60);
    this.renderer.render(this.scene, this.camera);
  }
}

<—— wind.js——>

import SimplexNoise from "simplex-noise";
import { Clock, Vector3 } from "three";
import gsap from "gsap";

const noise = new SimplexNoise();
const baseForce = 2000;
const off = 0.05;

export default class Wind {
  constructor(figure) {
    const { count } = figure.geometry.attributes.position;
    this.figure = figure;

    this.force = baseForce / count;

    this.clock = new Clock();
    this.direction = new Vector3(0.5, 0, -1);
    this.flowfield = new Array(count);

    this.update();

    this.bindEvents();
  }

  bindEvents() {
    window.addEventListener("mousemove", this.onMouseMove.bind(this));
  }

  onMouseMove({ clientX: x, clientY: y }) {
    const { innerWidth: W, innerHeight: H } = window;

    gsap.to(this.direction, {
      duration: 0.8,
      x: x / W - 0.5,
      y: -(y / H) + 0.5
    });
  }

  update() {
    const time = this.clock.getElapsedTime();

    const { position } = this.figure.geometry.attributes;
    const size = this.figure.geometry.parameters.widthSegments;

    for (let i = 0; i < position.count; i++) {
      const col = i % (size + 1);
      const row = Math.floor(i / (size + 1));

      const force =
        (noise.noise3D(row * off, col * off, time) * 0.5 + 0.5) * this.force;

      this.flowfield[i] = this.direction.clone().multiplyScalar(force);
    }
  }
}

<—— index.js——>

import "./styles.css";
import Scene from "./Scene";

const initApp = () => {
  window.scene = new Scene();
};

if (
  document.readyState === "complete" ||
  (document.readyState !== "loading" && !document.documentElement.doScroll)
) {
  initApp();
} else {
  document.addEventListener("DOMContentLoaded", initApp);
}

<—— styles.css ——>

body {
  margin: 0;
  background-color: #e4e0dd;
}

.container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100vh;
  z-index: 10;
}

.tile {
  width: 50vmin;
  flex: 0 0 auto;
}

.tile__figure {
  margin: 0;
  padding: 0;
}

.tile__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

canvas {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100vh;
  z-index: 9;
}
ambaamba
  • 71
  • 6
  • Please share more details, like the code involved, the error message you are facing, and your attempts to resolve the error – Nico Haase Mar 22 '22 at 13:43
  • Well it's lots of js files, it always says "Uncaught SyntaxError: Cannot use import statement outside a module" for all my js files calling 'three'; – ambaamba Mar 22 '22 at 13:47
  • `"Uncaught SyntaxError: Cannot use import statement outside a module"` Any reason you don't say that in your question?, as that's not saying there are missing modules. – Keith Mar 22 '22 at 13:49
  • Without more details, were you have included your script .. `` you have forgot to say it's a module.. `` – Keith Mar 22 '22 at 13:51
  • unfortunately i tried, but it dosen't resolve the issue, I followed the tutorial from a-z but nothing changes, I am surely missing something. – ambaamba Mar 22 '22 at 14:03
  • Now it says "Failed to load resource: the server responded with a status of 404 (Not Found)" – ambaamba Mar 23 '22 at 05:52
  • I added all the code from the tutorial so you can understand it better. I tried integrating everything with the dependancies but nothing seems to work. – ambaamba Apr 01 '22 at 13:22

1 Answers1

0

I think this is more a question about technique than any one error, because there could be a tree of errors that aren't being rendered after your current error crashes the program. I'm not sure what steps you've taken exactly to do get this project running, but what I would do is piece it out step by step. fist, make sure scene.js is running properly on your computer, then build the parts of the project piece by piece. Maybe you could start with piecing it together from this line in the scene.js file and look up every piece from there while using debugging techniques:

 this.renderer = new THREE.WebGLRenderer({
      canvas: this.container,
      alpha: true
    });

I'm guessing that you copy and pasted lot of that code into your project file, and you're usually going to run into big problems by doing that. good luck!

seems
  • 92
  • 1
  • 11