Remove or making instanced mesh invisible

Hello,

I’ve recently started working with instanced mesh and I’m having a little trouble seeing how it works. I would like to remove cubes after their “hp” reaches 0. i.e. make invisible remove all their characteristics like hitbox etc…
I have tested remove and invisible but neither function seems to work.

import * as THREE from "three"

import React, { useRef, useMemo, useState, useEffect } from "react"

import { Canvas, useFrame } from "@react-three/fiber"

import niceColors from "nice-color-palettes"

const squareLen = 3

const size = squareLen * squareLen * squareLen

const tempObject = new THREE.Object3D()

const tempColor = new THREE.Color()

const data = Array.from({ length: size }, () => ({ color: niceColors[17][Math.floor(Math.random() * 5)], hp: 5 }))

export const TheCube = (props) => {

  const [hovered, set] = useState()

  const colorArray = useMemo(() => Float32Array.from(new Array(size).fill().flatMap((_, i) => tempColor.set(data[i].color).toArray())), [])

  const meshRef = useRef()

  const prevRef = useRef()

  useFrame((state) => {

    let i = 0

    for (let x = 0; x < squareLen; x++)

      for (let y = 0; y < squareLen; y++)

        for (let z = 0; z < squareLen; z++) {

          const id = i++

          if (data[id].hp <= 0) {

            tempObject.visible = false

            continue

          }

          if (id === hovered) {

            data[id].hp = data[id].hp - 1

            console.log(data[id].hp)

            set(undefined)

          }

          tempObject.position.set(10 + x * 10, 5 + y * 10, 10 + z * 10)

          tempColor.set(id === hovered ? "white" : data[id].color).toArray(colorArray, id * 3)

          meshRef.current.geometry.attributes.color.needsUpdate = true

          tempObject.updateMatrix()

          meshRef.current.setMatrixAt(id, tempObject.matrix)

        }

    meshRef.current.instanceMatrix.needsUpdate = true

  })

  return (

    <instancedMesh ref={meshRef} args={[null, null, size]} onClick={(e) => set(e.instanceId)} onPointerUp={(e) => set(undefined)}>

      <boxGeometry args={[10, 10, 10]}>

        <instancedBufferAttribute attachObject={["attributes", "color"]} args={[colorArray, 3]} />

      </boxGeometry>

      <meshPhongMaterial vertexColors={THREE.VertexColors} />

    </instancedMesh>

  )

}

see How to show and hide an instance in instance mesh

2 Likes

What you’re doing there has no effect, it’s not how instancing works. These are not real objects but a bunch of data that’s sent to the shader. You can either change “updateRange” on the buffers, or you scale it to 0 (tempObject.scale.setScalar(0)), both work.

THREE.InstancedMesh is a bit tough to work with and if you don’t have hundreds of thousands of objects you can use dreis declarative abstraction, it couldn’t be easier than this: GitHub - pmndrs/drei: 🌭 useful helpers for react-three-fiber And now you can mount/unmount instances just like that.

Flying shoes and changing number: Floating, instanced shoes. - CodeSandbox

Bubbles: Hi-key bubbles - CodeSandbox

Converting GLTF contents to instances w/ GLTFJSX: Merged Instance - CodeSandbox

2 Likes

Thanks a lot, things seem clearer.
But I still have a question, let’s imagine that we have a game like Minecraft and that we have several hundred million cubes on a map, but that with the display distance, we render only a small area.
Would instanced meshes be usable or would we have to use standard meshes for this kind of case?
Because if all these millions of cubes are one instanced mesh, it would mean that if we want to change the state of a cube and remove it for example, we would have to go through all the cubes of the instanced mesh again? And if I understand, for a standard mesh, we will render only those that are in the render distance ( by reducing the “far” propriety of the camera) and therefore we could theoretically have and manipulate as many cubes as we want if the render distance is small enough?
From the code example I had put in my first post, I don’t see how I could browse only the cubes in the display distance area with instanced mesh.

i believe that instanced meshes do not occlude, that is one of the downsides. maybe it would make sense to instance regions or batches, and also use a lot of level-of-detail.

1 Like