remove raycaster

This commit is contained in:
Kseninia Mikhaylova 2024-06-28 16:34:29 +03:00
parent 2768ee9877
commit e88b91476b
6 changed files with 91 additions and 88 deletions

View File

@ -1100,7 +1100,7 @@
"kind": 6,
"importPath": "back.object.models",
"description": "back.object.models",
"peekOfCode": "class Scene3D(models.Model):\n name = models.CharField(\n max_length=120,\n )\n elements = models.ManyToManyField(Element3D)\n min_distance = models.IntegerField(\n validators=[MinValueValidator(1), MaxValueValidator(200)], blank=True, null=True\n )\n max_distance = models.IntegerField(\n validators=[MinValueValidator(2), MaxValueValidator(200)], blank=True, null=True",
"peekOfCode": "class Scene3D(models.Model):\n name = models.CharField(\n max_length=120,\n )\n elements = models.ManyToManyField(Element3D)\n min_distance = models.IntegerField(\n validators=[MinValueValidator(1), MaxValueValidator(400)], blank=True, null=True\n )\n max_distance = models.IntegerField(\n validators=[MinValueValidator(2), MaxValueValidator(500)], blank=True, null=True",
"detail": "back.object.models",
"documentation": {}
},

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue';
import { Box3, Vector2, Vector3 } from 'three';
import { useTresContext, useSeek, useRenderLoop } from '@tresjs/core';
import { ref, watch } from 'vue';
import { Box3, Color, Group, Mesh, MeshStandardMaterial, PointLight, SphereGeometry, Vector3 } from 'three';
import { useTresContext, useSeek } from '@tresjs/core';
import { useGLTF } from '@tresjs/cientos'
import { IMAGE_URL, SERVER_URL, } from '../../constants'
@ -20,8 +20,9 @@ function shadows_and_pos(scene: any) {
const models = ref<model3DType[]>([])
const clickable = ref<clickableAreaType[]>([])
const clickable_objects = ref<any[]>([])
const clickable_items = ref<any[]>([])
const sidebar = usePromoSidebar();
const { controls, raycaster, camera, scene } = useTresContext()
const { controls, camera, scene } = useTresContext()
const { seekByName } = useSeek()
const loadModels = async () => {
@ -46,7 +47,6 @@ const loadModels = async () => {
let { scene: loaded_scene } = await useGLTF(item.modelUrl)
shadows_and_pos(loaded_scene)
item.modelFile = loaded_scene
item.name = element.name
models.value.push(item)
@ -60,7 +60,34 @@ const loadModels = async () => {
const element = clickable.value[index];
const find_element = seekByName(scene.value, element.object_name)
if (!find_element) continue
const res_array = find_element.isGroup ? find_element?.children : [find_element]
const res_array = (find_element as Group).isGroup ? find_element?.children : [find_element]
if (find_element && !(find_element as Group).isGroup) {
const world_position = new Vector3();
(find_element as Mesh).geometry.boundingBox.getCenter(world_position);
(find_element as Mesh).localToWorld(world_position);
const light = new PointLight()
light.position.set(world_position.x, world_position.y * 5, world_position.z)
light.color = index % 2 ? new Color('red') : new Color('green');
light.power = 10000;
const point = new Mesh(new SphereGeometry(2, 16, 16), new MeshStandardMaterial({
color: light.color,
emissive: light.color,
emissiveIntensity: 100
}))
point.position.set(light.position.x, light.position.y, light.position.z)
point.name = `${element.id}_clickable`
// light.add(point)
clickable_items.value.push(light)
clickable_items.value.push(point)
clickable_objects.value.push({
name: point.name,
target: element.id,
object: point,
})
}
for (let index = 0; index < res_array.length; index++) {
const r = res_array[index];
let res = {
@ -82,38 +109,14 @@ const loadModels = async () => {
new Vector3(box_size.x * 0.5, box_size.y * 0.5, box_size.z * 0.5),
new Vector3(box_size.x * -0.5, box_size.y * -0.5, box_size.z * -0.5),
)
console.log(box_size)
}
controls.value.enabled = true;
props.loaded()
}
loadModels()
onMounted(() => {
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(clickable_objects.value.map(el => el.object));
const names = intersects.map(el => el.object.name ?? false).filter(Boolean)
if (names.length) {
const clicks = clickable_objects.value.find(el => names.includes(el.name))
if (!clicks) return
const target = clickable.value.find(el => el.id == clicks.target)
const openSidebar = (id: number) => {
const target = clickable.value.find(el => el.id == id)
if (!target) return
const sidebar_data = {
title: target.name,
@ -123,11 +126,11 @@ const clickEvent = (event: MouseEvent) => {
sidebar_data.target = target.target.toString()
sidebar_data.target_name = target.target_name
}
sidebar.open()
sidebar.setData(sidebar_data)
}
console.timeEnd('raycaster')
sidebar.open()
}
loadModels()
watch(() => props.source, () => {
const loaded = seekByName(scene.value, 'loaded')
if (loaded) {
@ -143,5 +146,9 @@ watch(() => props.source, () => {
<TresObject3D v-bind="item.modelFile.clone()" />
</TresGroup>
</template>
<template v-for="item in clickable_items">
<TresObject3D v-if="item.type == 'PointLight'" v-bind="item.clone()" />
<TresMesh v-else @click="() => openSidebar(item.name.replace('_clickable', ''))" v-bind="item" />
</template>
</TresGroup>
</template>

View File

@ -3,9 +3,9 @@ import { reactive, ref, watch } from 'vue';
import type { Ref } from 'vue'
import { useRoute } from 'vue-router';
import { PointLight, Vector3 } from 'three';
import { Vector3 } from 'three';
import { TresCanvas } from '@tresjs/core';
import { CameraControls, useProgress, StatsGl, OrbitControls, MapControls } from '@tresjs/cientos'
import { StatsGl, OrbitControls } from '@tresjs/cientos'
import Env from './env.vue'
import LoadModels from './load_models.vue'
@ -33,7 +33,7 @@ const camera = ref()
const cameraPosition = ref([1, 1, 1]) as unknown as Ref<Vector3>
const controlsState = reactive({
maxPolarAngle: (Math.PI / 2) - 0.02,
maxPolarAngle: (Math.PI / 2) - 0.05,
minAzimuthAngle: (Math.PI / 2) - 0.02,
})
const models_loading = ref(false)
@ -41,14 +41,6 @@ const set_model_load_status = () => {
models_loading.value = !models_loading.value
}
const point_light = new PointLight('#00d', 1000, 200)
point_light.intensity = 10000
point_light.position.set(-100, 100, 5)
point_light.castShadow = true
point_light.shadow.bias = -0.01
point_light.shadow.mapSize.width = 512 * 10
point_light.shadow.mapSize.height = 512 * 10
const route = useRoute()
const source = ref(route.params.target ? (route.params.target.toString() + '/') : '1/')
watch(() => route.params.target, () => {

View File

@ -7,7 +7,7 @@ import { usePromoSidebar } from '../../stores/promo_sidebar';
const sidebar = usePromoSidebar()
const sidebar_obj = ref()
onClickOutside(sidebar_obj, () => sidebar.close())
// onClickOutside(sidebar_obj, () => sidebar.close())
</script>
<template>
<div class="sidebar" :class="[{ 'open': sidebar.is_open }]" ref="sidebar_obj">
@ -60,6 +60,7 @@ onClickOutside(sidebar_obj, () => sidebar.close())
margin: 1rem 0;
font-size: 1.25rem;
}
.btn {
color: white;
transition: .2s linear;
@ -81,13 +82,13 @@ onClickOutside(sidebar_obj, () => sidebar.close())
font-weight: 700;
color: #313133;
background: #4FD1C5;
background: linear-gradient(90deg, rgba(129,230,217,1) 0%, rgba(79,209,197,1) 100%);
background: linear-gradient(90deg, rgba(129, 230, 217, 1) 0%, rgba(79, 209, 197, 1) 100%);
border-radius: 1000px;
box-shadow: 12px 12px 24px rgba(79,209,197,.64);
}
box-shadow: 12px 12px 24px rgba(79, 209, 197, .64);
}
.btn:hover {
.btn:hover {
box-shadow: 0 0 0 2px white, 0 0 0 4px #3C82F8;
}
}
}
</style>

View File

@ -37,6 +37,7 @@ interface clickableAreaType {
object_name: string;
source: number;
target: number;
target_name?: string
}
interface PromoSidebarData {
title: string

View File

@ -20,8 +20,10 @@ export const usePromoSidebar = defineStore('promo_sidebar', {
this.$state = Object.assign(this.$state, data)
},
close() {
if (this.is_open) {
this.$reset()
this.is_open = false
}
}
}
})