bx-865-apps #1

Merged
ksenia_mikhailova merged 140 commits from bx-865-apps into main 2024-06-27 15:03:27 +03:00
4 changed files with 56 additions and 21 deletions
Showing only changes of commit 96282a8078 - Show all commits

View File

@ -18,14 +18,10 @@ class Element3D(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
description = models.TextField() description = models.TextField()
min_distance = models.IntegerField( min_distance = models.IntegerField(
validators=[MinValueValidator(1), MaxValueValidator(200)], validators=[MinValueValidator(1), MaxValueValidator(200)], blank=True, null=True
blank=True,
null=True
) )
max_distance = models.IntegerField( max_distance = models.IntegerField(
validators=[MinValueValidator(2), MaxValueValidator(200)], validators=[MinValueValidator(2), MaxValueValidator(200)], blank=True, null=True
blank=True,
null=True
) )
def __str__(self): def __str__(self):
@ -37,7 +33,15 @@ class ClickableArea(models.Model):
description = models.TextField() description = models.TextField()
object_name = models.CharField(max_length=255) object_name = models.CharField(max_length=255)
target = models.ForeignKey( target = models.ForeignKey(
Element3D, on_delete=models.CASCADE, related_name="clickable_areas" Element3D,
on_delete=models.PROTECT,
related_name="clickable_areas",
blank=True,
null=True,
)
source = models.ForeignKey(
Element3D,
on_delete=models.PROTECT,
) )
def __str__(self): def __str__(self):

View File

@ -12,7 +12,10 @@ class NumberInFilter(django_filters.BaseInFilter, django_filters.NumberFilter):
class ClickableAreaViewSet(viewsets.ModelViewSet): class ClickableAreaViewSet(viewsets.ModelViewSet):
queryset = ClickableArea.objects.all() queryset = ClickableArea.objects.all()
serializer_class = ClickableAreaSerializer serializer_class = ClickableAreaSerializer
filterset_fields = ("target",) filterset_fields = (
"target",
"object_name",
)
class Element3DFilter(django_filters.rest_framework.FilterSet): class Element3DFilter(django_filters.rest_framework.FilterSet):

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { IMAGE_URL, SERVER_URL, } from '../../constants' import { IMAGE_URL, SERVER_URL, } from '../../constants'
import { onMounted, reactive, ref } from 'vue'; import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { Box3, Vector3 } from 'three'; import { Box3, Vector2, Vector3 } from 'three';
import { useTresContext } from '@tresjs/core'; import { useTresContext } from '@tresjs/core';
import { useGLTF } from '@tresjs/cientos' import { useGLTF } from '@tresjs/cientos'
@ -23,8 +23,17 @@ interface model3DType {
modelUrl?: string, modelUrl?: string,
modelFile?: any modelFile?: any
} }
function shadows_and_pos(scene: any) {
scene.children.forEach((el: any) => {
el.receiveShadow = true
el.castShadow = true
shadows_and_pos(el)
})
}
const models = ref<model3DType[]>([]) const models = ref<model3DType[]>([])
const { camera, controls } = useTresContext() const { controls, raycaster, camera, scene } = useTresContext()
const loadModels = async () => { const loadModels = async () => {
const res = await fetch(`${SERVER_URL}/api/obj/element/?parent__isnull=True`) const res = await fetch(`${SERVER_URL}/api/obj/element/?parent__isnull=True`)
const data = await res.json() as element3DType[] const data = await res.json() as element3DType[]
@ -32,14 +41,13 @@ const loadModels = async () => {
min: controls.value.minDistance, min: controls.value.minDistance,
max: controls.value.maxDistance == Infinity ? 1 : controls.value.maxDistance, max: controls.value.maxDistance == Infinity ? 1 : controls.value.maxDistance,
} }
console.log(camera)
console.log(controls)
for (let index = 0; index < data.length; index++) { for (let index = 0; index < data.length; index++) {
const element = data[index]; const element = data[index];
const item = {} as model3DType const item = {} as model3DType
item.modelUrl = `${IMAGE_URL}/${element.model_file}` item.modelUrl = `${IMAGE_URL}/${element.model_file}`
let { scene: loaded_scene } = await useGLTF(item.modelUrl) let { scene: loaded_scene } = await useGLTF(item.modelUrl)
shadows_and_pos(loaded_scene)
item.modelFile = loaded_scene item.modelFile = loaded_scene
models.value.push(item) models.value.push(item)
@ -59,16 +67,36 @@ const loadModels = async () => {
controls.value.minDistance = distance.min controls.value.minDistance = distance.min
controls.value._needsUpdate = true controls.value._needsUpdate = true
controls.value.update(1) controls.value.update(1)
} }
onMounted(() => { onMounted(() => {
loadModels() loadModels()
document.addEventListener('click', clickEvent)
}) })
onUnmounted(() => {
document.removeEventListener('click', clickEvent)
})
const pointer = reactive({ x: 0, y: 0 })
const clickEvent = (event: MouseEvent) => {
console.time('raycaster')
const x = (event.clientX / window.innerWidth) * 2 - 1
const y = - (event.clientY / window.innerHeight) * 2 + 1
if (x == pointer.x && y == pointer.y) return
if (!camera.value) return
pointer.x = x
pointer.y = y
raycaster.value.setFromCamera(new Vector2(pointer.x, pointer.y), camera.value);
const intersects = raycaster.value.intersectObjects(scene.value.children);
const names = intersects.map(el => el.object.name ?? false).filter(Boolean)
if (names.length) {
console.log({ pointer, names })
}
console.timeEnd('raycaster')
}
</script> </script>
<template> <template>
<TresGroup v-for="item in models"> <TresGroup v-for="item in models">
<Suspense> <TresObject3D v-bind="item.modelFile.clone()" />
<ModelItem v-bind="item" />
</Suspense>
</TresGroup> </TresGroup>
</template> </template>

View File

@ -6,9 +6,9 @@ const props = defineProps(['modelUrl', 'modelFile', 'onClick'])
let scene: any let scene: any
if (props.modelUrl) { if (props.modelUrl) {
let { scene: loaded_scene } = await useGLTF(props.modelUrl) let { scene: loaded_scene } = await useGLTF(props.modelUrl)
scene = loaded_scene scene = loaded_scene.clone()
} else if (props.modelFile) { } else if (props.modelFile) {
scene = props.modelFile scene = props.modelFile.clone()
} }
function shadows_and_pos(scene: any) { function shadows_and_pos(scene: any) {
scene.children.forEach((el: any) => { scene.children.forEach((el: any) => {
@ -21,7 +21,7 @@ function shadows_and_pos(scene: any) {
shadows_and_pos(scene) shadows_and_pos(scene)
</script> </script>
<template> <template>
<TresMesh> <TresMesh v-if="scene.children[0].isObject3D">
<primitive :object="scene" /> <TresObject3D v-bind="scene.children[0].clone()"/>
</TresMesh> </TresMesh>
</template> </template>