mns-mini-zabor/components/model/fence.vue

162 lines
6.2 KiB
Vue

<script setup lang="ts">
import { BufferGeometry, Matrix4, Mesh, Object3D, Vector2, Vector3 } from 'three';
import { getColorHexFromRal } from '../ral';
import { getFilename } from '../pattern';
const props = defineProps(['index', 'models', 'last_element', 'first_element'])
const lamelle_height = use_lamelle_height()
const lamelles_count = use_lamelles_count()
const fence_section = use_fence_section()
const section_count = use_section_count()
const extra_section = use_extra_section()
const remove_pillar = use_remove_pillar()
const pillar_color = use_pillar_color()
const pillar_pattern = use_pattern()
const lamelle_color = use_lamelle_color()
const lSize = lamelle_height.value
const bSize = 0.0235
const pillar_size = 104 * 0.001
const pillar_one_pos = ref(fence_section.value * -0.5 - 0.015)
const pillar_two_pos = ref(fence_section.value * 0.5 + pillar_size + bSize - 0.01)
const scale_koef = 1
const show_pillar_one = ref(props.first_element)
const show_pillar_two = ref(true)
const getExtraValue = () => (extra_section.value && props.last_element) ? extra_section.value * 0.001 : false
const extra = ref(getExtraValue())
if (extra.value) {
pillar_one_pos.value = (extra.value as number) * -0.5 - 0.015
pillar_two_pos.value = (extra.value as number) * 0.5 + pillar_size + bSize - 0.01
}
const make_translate_to_section = (source = fence_section.value) => {
const one_s = (source + pillar_size + bSize) * scale_koef
let r = (props.index - 1) * one_s
if (typeof extra.value == 'number') {
r -= (fence_section.value - extra.value) * scale_koef * 0.5
}
return r
}
const translate_to_section = ref(make_translate_to_section())
watch([fence_section, extra], () => {
translate_to_section.value = make_translate_to_section()
})
const instanced_lamelle = shallowRef();
const instanced_lamelle_geometry = Object.assign(new BufferGeometry, props.models.lamelle.children[0].geometry)
const instanced_lamelle_material = props.models.lamelle.children[0].material
const instanced_lamelle_count = 24
const instanced_v = [instanced_lamelle_geometry, instanced_lamelle_material, instanced_lamelle_count]
watch([instanced_lamelle, fence_section, extra_section, lamelles_count, extra], () => {
for (let i = 0; i < instanced_lamelle_count; i++) {
if (instanced_lamelle.value) {
const scale_x = (((extra.value as number) || fence_section.value) * 10)
const pos_x = pillar_size * 0.5
const pos_y = (lSize * i)
const pos_z = 0.02
const newmatrix = new Matrix4().fromArray([
scale_x, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
pos_x, pos_y, pos_z, 1
])
instanced_lamelle.value.setMatrixAt(i, newmatrix);
if (i >= lamelles_count.value) {
instanced_lamelle.value.setMatrixAt(i, new Matrix4().makeTranslation(new Vector3(0, 20, 20)));
}
instanced_lamelle.value.instanceMatrix.needsUpdate = true
}
}
});
watch([section_count, fence_section, extra_section], () => {
extra.value = getExtraValue()
if (extra_section.value && props.last_element) {
pillar_one_pos.value = (extra.value as number) * -0.5 - 0.015
pillar_two_pos.value = (extra.value as number) * 0.5 + pillar_size + bSize - 0.01
} else {
pillar_one_pos.value = fence_section.value * -0.5 - 0.015
pillar_two_pos.value = fence_section.value * 0.5 + pillar_size + bSize - 0.01
}
})
const pillar = ref<Mesh[]>([])
const setPillar = () => {
const top = props.models.fence_top.children[0];
top.position.setComponent(1, lSize * lamelles_count.value)
const pillar_outer = props.models.fence.children[0];
pillar_outer.scale.setComponent(1, lamelles_count.value);
const pillar_inner = props.models.fence_inner.children[0];
pillar_inner.scale.setComponent(1, lamelles_count.value);
const bottom = props.models.fence_bottom.children[0];
bottom.position.setComponent(1, lSize * -1)
let arr = [top.clone(), pillar_outer.clone(), pillar_inner.clone(), bottom.clone(),]
arr.map(el => {
set_material({ children: [el] }, getColorHexFromRal(pillar_color.value))
})
set_material(
{ children: [arr[2]] },
getColorHexFromRal(pillar_color.value),
{ pattern: pillar_pattern.value, count: lamelles_count.value },
)
pillar.value = arr
}
setPillar()
watch([pillar_pattern, pillar_color, fence_section, lamelles_count], setPillar)
const fastening = ref<Object3D[]>([])
const setFastening = () => {
const one = props.models.fastening.children[0].clone();
one.position.setComponent(0, pillar_one_pos.value);
one.scale.set(1, lamelles_count.value, 1);
const two = props.models.fastening.children[0].clone();
two.position.setComponent(0, pillar_two_pos.value);
two.scale.set(-1, lamelles_count.value, 1);
const top = props.models.top.children[0].clone();
top.scale.setComponent(0, ((extra.value as number) || fence_section.value));
top.position.set(pillar_size * 0.5, lamelles_count.value * lSize, 0)
let arr = [one.clone(), two.clone(), top.clone(),]
arr.map(el => {
set_material({ children: [el] }, getColorHexFromRal(pillar_color.value))
})
fastening.value = arr
}
setFastening()
watch([pillar_color, fence_section, lamelles_count], setFastening)
</script>
<template>
<TresGroup :scale="scale_koef" :position-x="translate_to_section" :name="`fence ${index}`" :position-y="0">
<TresGroup name="pillar_one" v-if="!remove_pillar && show_pillar_one" :position-x="pillar_one_pos">
<template v-for="item in pillar">
<TresMesh v-bind="item.clone()" />
</template>
</TresGroup>
<TresGroup name="pillar_two" v-if="!remove_pillar && show_pillar_two" :position-x="pillar_two_pos">
<template v-for="item in pillar">
<TresObject3D v-bind="item.clone()" />
</template>
</TresGroup>
<TresGroup name="lamelles">
<TresInstancedMesh ref="instanced_lamelle" :args="instanced_v" />
</TresGroup>
<template v-for="item in fastening">
<TresObject3D v-bind="item.clone()" />
</template>
</TresGroup>
</template>