Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object/Texture Loaders #30

Open
Rigo-m opened this issue Nov 30, 2021 · 3 comments
Open

Object/Texture Loaders #30

Rigo-m opened this issue Nov 30, 2021 · 3 comments

Comments

@Rigo-m
Copy link

Rigo-m commented Nov 30, 2021

Is this already implemented and not documented or is the implementation lacking/won't be implemented by design?

https://threejs.org/docs/#examples/en/loaders/OBJLoader

Another good name for the issue would be: how do I load an external .obj file via Svelte Cubed API?

@tonyketcham
Copy link

tonyketcham commented Dec 1, 2021

I put together a simple working example in a project I'm working on. I converted my .obj file to a .js file, wrapped everything in a template literal, and exported it. To avoid having to do that, there's room to potentially sweeten this up with a custom vite plugin that imports .obj files.

<script lang="ts">
	import * as THREE from 'three';
	import * as SC from 'svelte-cubed';
	import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
	import obj from '$lib/components/models/Lowpoly_tree_sample.js';
</script>

<SC.Canvas antialias background={new THREE.Color('papayawhip')} shadows>
	<SC.Primitive object={new OBJLoader().parse(obj)} />

	<SC.PerspectiveCamera position={[50, 50, 50]} />
	<SC.OrbitControls enableZoom={true} maxPolarAngle={Math.PI * 0.51} />
	<SC.AmbientLight intensity={0.6} />
	<SC.DirectionalLight intensity={0.6} position={[-2, 3, 2]} shadow={{ mapSize: [2048, 2048] }} />
</SC.Canvas>

image

Using SvelteKit, I hypothesize performance may be improved here by parsing the .obj file contents during prerendering (in the load function of <script context="module">) and passing both a BufferGeometry and Material through the props. I attempted that without success but I'm pretty green to three.js, so someone more knowledgeable may know how to extract those from the Object3D that new OBJLoader().parse(obj) returns.

@tonyketcham
Copy link

I just created that vite plugin I mentioned above so you don't have to convert your the .obj files https://github.com/tonyketcham/unplugin-obj

Using that, you just have to do

import obj from '$lib/components/models/Lowpoly_tree_sample.obj';

@tonyketcham
Copy link

tonyketcham commented Dec 3, 2021

Alternatively (and probably more performantly albeit more verbose) you can place your .obj/.mtl files within your static folder and do something like:

<script lang="ts">
	import * as THREE from 'three';
	import * as SC from 'svelte-cubed';
	import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
	import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
        import { assets } from '$app/paths';
	import { browser } from '$app/env';

	let mesh: THREE.Mesh;
	const mtlSrc = `${assets}/Lowpoly_tree_sample.mtl`;

	const mtlLoader = new MTLLoader();
	const objLoader = new OBJLoader();

        if (browser) {
	  // Load the object and material resources
	  mtlLoader.load(mtlSrc, (mtl) => {
                   const objSrc = `${assets}/Lowpoly_tree_sample.obj`;
		  mtl.preload();
		  objLoader.setMaterials(mtl);
  
		  objLoader.load(objSrc, (event) => {
			  mesh = event.children[0] as THREE.Mesh;
			  console.log(mesh);
			  return mesh;
		  });
	  });
        }

	async function loadMesh(mesh) {
		return new Promise((resolve: (value: THREE.Mesh) => any) => {
			if (mesh) {
				resolve(mesh);
			}
		});
	}

	// Wait for the mesh to load before adding it to the scene
	$: meshPromise = loadMesh(mesh);
</script>

<SC.Canvas antialias background={new THREE.Color('papayawhip')} shadows>
	{#await meshPromise then mesh}
		<SC.Mesh geometry={mesh.geometry} material={mesh.material} />
	{/await}
	<SC.PerspectiveCamera position={[50, 50, 50]} />
	<SC.OrbitControls enableZoom={true} maxPolarAngle={Math.PI * 0.51} />
	<SC.AmbientLight intensity={0.6} />
	<SC.DirectionalLight intensity={0.6} position={[-2, 3, 2]} shadow={{ mapSize: [2048, 2048] }} />
</SC.Canvas>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants