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

Add error card when generated model is empty #96

Merged
merged 2 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 28 additions & 15 deletions src/components/ModelViewer.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { T, useThrelte } from '@threlte/core'
import { GLTF, OrbitControls, interactivity, useGltf } from '@threlte/extras'
import { createEventDispatcher } from 'svelte'
import { Box3, Color, Vector3, Scene, Mesh } from 'three'

export let dataUrl: string
Expand All @@ -9,12 +10,14 @@
let readyToRender = false

const { size: threlteSize } = useThrelte()
const dispatch = createEventDispatcher()

interactivity()

let shouldAutoRotate = true
const AUTO_ROTATE_PAUSE = 5000

// This allows autorotate to be paused when the user is interacting with the model
let autorotateTimeout: ReturnType<typeof setTimeout> | undefined
const disableAutoRotate = () => {
if (!pausable) return
Expand All @@ -32,22 +35,32 @@
let maxDistance = 0

$: if (dataUrl && $loadedModel) {
;($loadedModel.scene as Scene).traverse((child) => {
if ('isMesh' in child && child.isMesh) {
const material = (child as Mesh).material
if (material instanceof Array && 'color' in material[0]) {
material[0].color = new Color(0x29ffa4)
} else if ('color' in material) {
material.color = new Color(0x29ffa4)
// If the model is empty, we need to tell the parent component
// to show the empty scene error card
if (Object.values($loadedModel.nodes).length === 0) {
dispatch('emptyscene')
} else {
// Otherwise we'll traverse each mesh and set the color to green
;($loadedModel.scene as Scene).traverse((child) => {
if ('isMesh' in child && child.isMesh) {
const material = (child as Mesh).material
if (material instanceof Array && 'color' in material[0]) {
material[0].color = new Color(0x29ffa4)
} else if ('color' in material) {
material.color = new Color(0x29ffa4)
}
}
}
})
const size = new Vector3()
const boundingBox = new Box3()
boundingBox.setFromObject($loadedModel.scene)
boundingBox.getSize(size)
maxDistance = Math.max(size.x, size.y, size.z)
readyToRender = true
})

// Then we'll calculate the max distance of the bounding box
// and set that as the camera's position
const size = new Vector3()
const boundingBox = new Box3()
boundingBox.setFromObject($loadedModel.scene)
boundingBox.getSize(size)
maxDistance = Math.max(size.x, size.y, size.z)
readyToRender = true
}
}
</script>

Expand Down
28 changes: 22 additions & 6 deletions src/routes/(sidebarLayout)/view/[modelId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
import { browser } from '$app/environment'
import ErrorCard from 'components/ErrorCard.svelte'
import { combinedGenerations, unreadGenerations } from '$lib/stores'
import { invalidateAll } from '$app/navigation'
import { invalidateAll, onNavigate } from '$app/navigation'
import { navigating } from '$app/stores'

export let data: Models['TextToCad_type']
$: status = $combinedGenerations.find((g) => g.id === data.id)?.status ?? data.status
let isSceneEmpty = false

onNavigate(() => {
isSceneEmpty = false
})

$: if (browser && (status === 'completed' || status === 'failed')) {
unreadGenerations.update((g) => g.filter((id) => id !== data.id))
Expand Down Expand Up @@ -66,11 +71,22 @@
{/if}
</div>
{#if data.outputs && data.status === 'completed'}
<div class="relative flex-grow min-h-[500px]">
<Canvas>
<ModelViewer dataUrl={gltfUrl} />
</Canvas>
</div>
{#if !isSceneEmpty}
<div class="relative flex-grow min-h-[500px]">
<Canvas>
<ModelViewer
on:emptyscene={() => {
isSceneEmpty = true
}}
dataUrl={gltfUrl}
/>
</Canvas>
</div>
{:else}
<div class="grid flex-grow place-content-center p-4">
<ErrorCard error={'Model generated an empty scene.'} />
</div>
{/if}
{:else if data.status === 'failed' && data.error}
<div class="grid flex-grow place-content-center p-4">
<ErrorCard error={data.error} />
Expand Down