About Decal---why does this code need?

import React, { useRef, useState } from “react”;
import { useGLTF, Decal, useTexture } from “@react-three/drei”;
import { useControls } from “leva”;
import { degToRad } from “three/src/math/MathUtils.js”;

export function Mug(props) {
const { nodes, materials } = useGLTF(“/models/mug.glb”);
const texture = useTexture(“textures/david.png”);
const decal = useRef();

useControls({
angle: {
min: degToRad(60),
max: degToRad(300),
step: 0.01,
value: Math.PI / 4,
onChange: (value) => {
//decal.current.rotation.y = value;
const x = Math.cos(value);
const z = Math.sin(value);
const rot = Math.atan2(x, z);
setPos((pos) => [x, pos[1], z]);
setRotation((rotation) => [0, rot, 0]);
},
},
PosY: {
min: 0,
max: 3,
value: 0.4,
step: 0.01,
onChange: (value) => {
setPos((pos) => [pos[0], value, pos[2]]);
},
},
scale: {
min: 0.5,
max: 3,
value: 1,
step: 0.01,
onChange: (value) => {
setScale(() => [value, value, value]);
},
},
});

const [pos, setPos] = useState([0, 0.8, -0.5]);
const [rotation, setRotation] = useState([0, 0, 0]);
const [scale, setScale] = useState([1, 1, 1]);

return (
<group {…props} dispose={null}>




);
}

useGLTF.preload(“/models/mug.glb”);

this is code for sticky.
here I don’t know well about following part.
const rot = Math.atan2(x, z);
setPos((pos) => [x, pos[1], z]);
setRotation((rotation) => [0, rot, 0]);

why does this code need?

It’s basically there to make the sticker move around the mug and face the right way.

Math.cos and Math.sin turn the angle into an x and z position, so the decal moves in a circle around the mug.

Math.atan2(x, z) figures out the correct rotation so the sticker isn’t sideways or facing the wrong direction. Without it, the position would change but the sticker wouldn’t rotate properly.

setPos updates where the decal sits, keeping the same height and just moving it around the mug.

setRotation makes sure it turns to match the surface so it looks naturally placed instead of floating awkwardly.

1 Like

Thanks. But I think if origin of decal equal to origin of mug, can’t it perform only with rotation of decal?

looking forward your advice.

@David4 that’s a sharp observation, but there’s a subtle reason it still needs both position and rotation.

<Decal> from drei uses Three.js’s DecalGeometry internally, which takes a world-space position as a projection point on the mesh surface. It’s not a regular scene-graph transform, so rotating the decal node alone just spins the sticker in place, it doesn’t move the projection point around the mug.

That said, your instinct isn’t wrong. You could achieve orbiting with rotation only if you placed the decal as a child of a pivot object centered at the mug’s origin, then rotated that pivot. The decal’s world-space position would then orbit correctly.

However, you’d still need to update the decal’s facing direction which is exactly what Math.atan2(x, z) is computing. So the logic isn’t eliminated, just reorganized into the scene graph instead of explicit state.

The current approach keeps it all flat and explicit, which is easier to wire up to Leva controls directly.

thanks for answering

I saw your portfolio.
yours is very awesome

Thank you!

I want to learn threejs.
which course can I learn it with?
if you don’t mind, help me.

Try Nik Lever - YouTube & SimonDev - YouTube

Three.js Virtual Experience Engine.pdf (5.0 MB) learn virtual experience engine as well.