How to look at model from outside model not inside

I am new to three.js and all I wanted was to import and display this model here:
https://sketchfab.com/3d-models/pumpkin-cat-82bf19f3981647c48f59d780779aed13

But the problem is that it’s like I’m looking at the model from INSIDE the model (inside the pumpkin) instead of looking AT the model from outside the model…

my App.js:

import { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import "./css/style.css";
import { OrbitControls, Environment } from "@react-three/drei";
import PumpkinCat from "./components/PumpkinCat";

function App() {
  return (
    <div id="canvas-container">
      <Canvas>
        <ambientLight />
        <directionalLight />
        <Environment preset="forest" />
        <OrbitControls enableZoom={false} />
        <Suspense fallback={<div>Loading...</div>}>
          <PumpkinCat />
        </Suspense>
      </Canvas>
    </div>
  );
}

export default App;

I have put my PumpkinCat.jsx inside the components folder, and created the jsx in the first place cd by first downloading the model files in public folder then cd public → npx gltfjsx pumpkinCat.gltf and copy pasting the pubpkinCat.jsx into components folder.

my style.css inside css folder inside src folder:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

#canvas-container {
  height: 100vh !important;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  /* background-color: slateblue; */
}

Please help, thank you so much in advance

Hi,
You need to change the camera postion like try changing it to on z axis 4 or 5

For example when I load the cat from here:

import { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import "./css/style.css";
import { OrbitControls, Environment } from "@react-three/drei";
import Earth from "./components/Earth";
import Cat from "./components/Cat";

function App() {
  return (
    <Canvas camera={{ position: [0, 0, 10] }}>
      <ambientLight />
      <directionalLight />
      <Environment preset="forest" />
      <OrbitControls enableZoom={true} />
      <Suspense fallback={null}>
        {/* <Earth /> */}
        <Cat />
      </Suspense>
    </Canvas>
  );
}

export default App;

If I add position [0,0,10] so z=10, it does nothing:


This is what position [0,0,10] looks like.

And if I remove the camera={{ position: [0, 0, 10] }} it looks like:

so it’s the same…nothing changes… how is this the case? it only worked for the Earth component but for any other component it doesn’t seem to work also the camera setting change doesn’t do anything… please help. As you can see when I load screen it shows the leg/feet of cat first exactly like the photo

Also in the original sketchfab model you can see that the cat moves but when I load it like the code above it is static and just doesn’t move - how do I fix this?

I Guess the model size is too big,try scaling it down in Cat component or maybe put camera on z axis at 100’s

1 Like

Omg thank you so much!! I fixed with adding scale={[0.4, 0.4, 0.4]} to outermost group in Cat.jsx and also setting camera position in app.js to <Canvas camera={{ position: [-120, 120, 400] }}> and now it looks like this:

Do you know by any chance how to move the cat like in the original 3d model?
https://sketchfab.com/3d-models/toon-cat-free-b2bd1ee7858444bda366110a2d960386

As you can see here it moves but mine is just still static. Is there anyway to download the animation from the sketchfab 3d model as well?

 const { actions } = useAnimations(animations, group)

  console.log(actions);
  useEffect(() => {
    const action = actions["Scene"]
    action.play()
  }, [actions])

to run animations you need to log to find the available animations, here i did using console.log(actions); and in log you’ll see an object ,inside it in scopes you’ll find animation clip and its name, in your case its name “Scene”,and just play it.

By the way instead of scaling outer group ,try scaling down Cat group,they’'ll be mostly scale={100} set them to scale={1},and set camera to normal positon [0,0,3] like that…I hope that helps…

2 Likes

Thank you so much!!


just one last question, when I console log actions - it shows up like this in console log - I get the actions[“Scene”] part since there is Scene inside the action returned, but how did you know it was the .play() that made the animation happen? I can’t seem to find the .play() function in the console log…

Also now it looks the same + animation works!:


but I fixed to Cat.jsx:

/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 cat.gltf 
Author: Omabuarts Studio (https://sketchfab.com/omabuarts)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/toon-cat-free-b2bd1ee7858444bda366110a2d960386
Title: Toon Cat FREE
*/

import React, { useRef, useEffect } from "react";
import { useGLTF, useAnimations } from "@react-three/drei";

export default function Cat(props) {
  const group = useRef();
  const { nodes, materials, animations } = useGLTF("/cat.gltf");
  const { actions } = useAnimations(animations, group);
  console.log("actions:", actions);
  useEffect(() => {
    const action = actions["Scene"];
    action.play();
  }, [actions]);
  return (
    <group ref={group} {...props} dispose={null}>
      <group name="Sketchfab_Scene">
        <group name="Sketchfab_model" rotation={[-Math.PI / 2, 0, 0]}>
          <group
            name="0df7f1c552db41979cdb0b8efba99edffbx"
            rotation={[Math.PI / 2, 0, 0]}
          >
            <group name="Object_2">
              <group name="RootNode">
                <group
                  name="Rig"
                  scale={1}
                  rotation={[-Math.PI / 2, 0, 0]}
                  // scale={100}
                >
                  <group name="Object_5">
                    <primitive object={nodes._rootJoint} />
                    <group
                      name="Object_42"
                      rotation={[-Math.PI / 2, 0, 0]}
                      scale={100}
                    />
                    <skinnedMesh
                      name="Object_43"
                      geometry={nodes.Object_43.geometry}
                      material={materials.Mat_Gradient}
                      skeleton={nodes.Object_43.skeleton}
                    />
                  </group>
                </group>
                <group
                  name="Cat"
                  // scale={1}
                  rotation={[-Math.PI / 2, 0, 0]}
                  scale={100}
                />
              </group>
            </group>
          </group>
        </group>
      </group>
    </group>
  );
}

useGLTF.preload("/cat.gltf");

and App.js:

import { Canvas } from "@react-three/fiber";
import { Suspense } from "react";
import "./css/style.css";
import { OrbitControls, Environment } from "@react-three/drei";
// import Earth from "./components/Earth";
import Cat from "./components/Cat";

function App() {
  return (
    // camera={{ position: [-120, 120, 400] }}
    <Canvas camera={{ position: [-4, 4, 10] }}>
      <ambientLight />
      <directionalLight />
      <Environment preset="forest" />
      <OrbitControls enableZoom={true} />
      <Suspense fallback={null}>
        {/* <Earth /> */}
        <Cat />
      </Suspense>
    </Canvas>
  );
}

export default App;

play() is custom method provided by @react-three/drei ,
as you see we use useAnimations from drei to use animations from imported model and destructure as actions and to play those animations we use play() method…

and “Scene” inside actions is name of Animation clip ,as you can see in bottom , it can be anything instead “Scene” something like “Run” or “Walk” or other whatever name set by model creator,we need to use that name to run animations…

1 Like

Thank you!!