0

I'm trying to reproduce this animation (see below) with react-three-fiber. I'm still very new to this package and to three-js.

http://makesportmakebook.com/livres/.

I've been able to do create book shapes with meshLambertMaterial, as such:

function Book(props) {

  const mesh = useRef();
  useFrame(() => {
    mesh.current.rotation.x = mesh.current.rotation.y += 0.01
  })

  const bookCover = useLoader(TextureLoader, bookCoverImg)
  const bookSpine = useLoader(TextureLoader, bookSpineImg)
  const bookBack = useLoader(TextureLoader, bookBackImg)
  const bookPages = useLoader(TextureLoader, bookPagesImg)
  const bookPagesTexture = useLoader(TextureLoader, bookPagesTextureImg)
  const bookPagesTopBottomTexture = useLoader(TextureLoader, bookPagesTopBottomTextureImg)

  return (
    <mesh
    position={props.position}
    ref={mesh}>
      <boxBufferGeometry attach="geometry" args={
        [
          7, 10, 1.2, 4, 4, 1
        ]
      } />
        <meshLambertMaterial color={"0xffffff"} map={bookCover}  />
        <meshLambertMaterial map={bookSpine}  />
        <meshLambertMaterial map={bookBack}  />
        <meshLambertMaterial map={bookPages}  />
        <meshLambertMaterial map={texture_5}  />
        <meshLambertMaterial map={texture_6}  />
    </mesh>
  )
};

Here's a code sandbox of my code so far: https://codesandbox.io/s/cocky-fast-61ndj

My question is: how can I avoid the overlap of these you can see here (below) but still keep the same parallel position we can see in the first example?

enter image description here

1
  • 1
    First question: In the example you are trying to mimic, it's not the books that are rotating, but rather the camera is rotating around them. Try to rotate the camera instead of the books? Commented Jan 24, 2021 at 13:03

1 Answer 1

1

There are two ways that you could handle this. The first is to move the camera instead of the books. The second is that instead of moving the books separately, move them as a group. I suspect that this second method is what you want to do.

This was quick and dirty, but it works.

Create a function to house the two books. Put the two books in a group and rotate the group.

import React, { useRef, Suspense } from "react";
import { Canvas, useFrame, extend, useLoader } from "react-three-fiber";
import { OrbitControls, StandardEffects, draco } from "drei";
import { TextureLoader } from "three/src/loaders/TextureLoader.js";

extend({ OrbitControls });

function Bookshelf(props) {
  const mesh = useRef();
  useFrame(() => {
    mesh.current.rotation.x = mesh.current.rotation.y += 0.01;
  });

  return (
    <group ref={mesh} position={[0, 0, 0]}>
    <Suspense fallback={null}><Book position={[3, 0, 3]} /></Suspense>
    <Suspense fallback={null}><Book position={[-3, 0, 0]} /></Suspense>
    </group>
  )
}


function Book(props) {

  const bookCover = useLoader(
    TextureLoader,
    "https://res.cloudinary.com/www-c-t-l-k-com/image/upload/v1607732427/HEAD_PUBLISHING/book-cover.jpg"
  );
  const bookSpine = useLoader(
    TextureLoader,
    "https://res.cloudinary.com/www-c-t-l-k-com/image/upload/v1607732420/HEAD_PUBLISHING/book-back.jpg"
);
  const bookBack = useLoader(
    TextureLoader,
    "https://res.cloudinary.com/www-c-t-l-k-com/image/upload/v1607732421/HEAD_PUBLISHING/book-side.jpg"
);
  const bookPages = useLoader(
    TextureLoader,
    "https://res.cloudinary.com/www-c-t-l-k-com/image/upload/v1607732421/HEAD_PUBLISHING/book-side.jpg"
);
  const texture_5 = useLoader(
    TextureLoader,
    "https://res.cloudinary.com/www-c-t-l-k-com/image/upload/v1607732427/HEAD_PUBLISHING/book-cover.jpg"
);
  const texture_6 = useLoader(
    TextureLoader,
    "https://res.cloudinary.com/www-c-t-l-k-com/image/upload/v1607732421/HEAD_PUBLISHING/book-spine.jpg"
);

  return (
    <mesh position={props.position} >
      <boxBufferGeometry attach="geometry" args={[7, 10, 1.2, 4, 4, 1]} />
      <meshLambertMaterial color={"0xffffff"} map={bookCover} />
      <meshLambertMaterial map={bookSpine} />
      <meshLambertMaterial map={bookBack} />
      <meshLambertMaterial map={bookPages} />
      <meshLambertMaterial map={texture_5} />
      <meshLambertMaterial map={texture_6} />
    </mesh>
  );
}

export default function App() {
  let styling = {
    width: "100vw",
    height: "100vh",
    position: "relative"
  };

return (
  <div style={{ position: "relative" }}>
    <Canvas camera={{ position: [0, 0, 20] }} style={styling}>
      <ambientLight intensity={0.3} />
      <directionalLight intensity={1} />
      <Suspense fallback={null}>
        <Bookshelf>
        </Bookshelf>
      </Suspense>
      <OrbitControls enableZoom={false} />
    </Canvas>
  </div>
);

}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.