Loading 3D models has been well-considered by the 3D libraries utilized in this thesis, as evidenced by their implementation in other projects. This process is generally straightforward, thanks to the built-in loaders or helper functions provided by these libraries.
What is usually done is to have the model in a public route, such as https://yoursite.com/model.gltf. This model serves a specific function, and it is known at build time know what shape it has: The materials it uses, the nodes, the animations, etc. This allows us to write the models in JSX declaratively with the gltfJSX library:
But one might wonder, what if the model’s information is asynchronous and one doesn’t know it’s shape beforehand? What if wemust evaluate the model at run-time? This is the case when loading models from the cloud.
TriArt revolves around cloud integration, which enables users to store and retrieve their 3D models securely. However, a key challenge arises when interacting with these models without prior knowledge of their specific details. Let’s delve into the process of retrieving and interacting with 3D files in such scenarios.
In this documentation, we will briefly discuss the structure of the Supabase instance that has been set up for TriArt. While we won’t delve into excessive detail, it is important to understand the key components. The Supabase instance utilizes PostgreSQL and includes a table named “ArtWorks,” which resembles the following structure:
id | user_id | visibility | url |
---|---|---|---|
1 | 292e4ad19628-9513 | public | https://supabase.com/storage/model.glb |
The id
column serves as the unique identifier for each row, and the user_id
column acts as a foreign key referencing the corresponding user. The visibility
column determines whether the URL generated by TriArt has an authentication bypass or not. Lastly, the url column represents a straightforward URL generated by Supabase’s storagefeature.
If you visit https://tfg-triart.vercel.app/artwork/32, for example, you’ll notice that the URL structure takes the parameter id
(in this case, 32) to select and display the chosen artwork.
This, in combination with React Server Components of Next13, allows us to load the chosen artwork and handle the visibility status validation, without any line running on the client:
type Props = {
params: { id: string };
};
export default async function Artwork({ params: { id } }: Props) {
const {
data: { session },
} = await supabase.auth.getSession();
const { data, error } = await supabase.from("artwork").select().eq("id", id);
if (data[0].visiblity === "private" && data[0].user_id !== session?.user.id) {
throw Error("You don't have permission to see this artwork");
}
return <Scene url={data[0].url} />;
}
As previously discussed, knowing what model will you be working on has a lot of benefits. But what if the model comes from a third-party API? R3F has a way of loading models just by the use of a link (either local or public), with the useLoader
hook:
import { useLoader } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
export default function Scene() {
const gltf = useLoader(GLTFLoader, "/Poimandres.gltf");
return <primitive object={gltf.scene} />;
}