new model
This commit is contained in:
BIN
src/assets/myself/terminalretro.jpg
Normal file
BIN
src/assets/myself/terminalretro.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
263
src/components/big/PcBooks.vue
Normal file
263
src/components/big/PcBooks.vue
Normal file
@@ -0,0 +1,263 @@
|
||||
<script setup lang="js">
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
import * as THREE from "three";
|
||||
import gsap from "gsap";
|
||||
import ScrollTrigger from "gsap/ScrollTrigger";
|
||||
|
||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
|
||||
import ski_video from "/vids/th.mp4";
|
||||
|
||||
import normal_texture from "../../assets/myself/terminalretro.jpg";
|
||||
|
||||
const canvasRef = ref(null);
|
||||
let renderer, scene, camera, model, controls, gsapCtx;
|
||||
let raycaster;
|
||||
let mouse;
|
||||
let screens;
|
||||
|
||||
const video_ski = document.createElement("video");
|
||||
|
||||
video_ski.src = ski_video;
|
||||
video_ski.loop = true;
|
||||
video_ski.muted = true;
|
||||
|
||||
function initThree(canvas) {
|
||||
renderer = new THREE.WebGLRenderer({
|
||||
canvas,
|
||||
antialias: true,
|
||||
alpha: true,
|
||||
});
|
||||
|
||||
renderer.setPixelRatio(1); //TODO
|
||||
|
||||
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
||||
scene = new THREE.Scene();
|
||||
camera = new THREE.PerspectiveCamera(23, 1, 0.1, 140);
|
||||
|
||||
// const light = new THREE.DirectionalLight(0xffe0b0, 0.9);
|
||||
// light.position.set(-1, 4, 5);
|
||||
// scene.add(light);
|
||||
|
||||
controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true;
|
||||
// controls.enabled = false;
|
||||
|
||||
raycaster = new THREE.Raycaster();
|
||||
mouse = new THREE.Vector2();
|
||||
|
||||
// controls.minDistance = 5;
|
||||
// controls.maxDistance = 5;
|
||||
controls.maxPolarAngle = Math.PI / 2;
|
||||
controls.minAzimuthAngle = -Math.PI / 2;
|
||||
controls.maxAzimuthAngle = Math.PI / 2;
|
||||
|
||||
scene.add(new THREE.AmbientLight(0xffffff, 0.02));
|
||||
|
||||
loadModel();
|
||||
|
||||
gsap.ticker.add(render);
|
||||
}
|
||||
|
||||
function loadModel() {
|
||||
const modelUrl = "/models/book_shelf_pc_draco-v1.glb";
|
||||
|
||||
const dracoLoader = new DRACOLoader();
|
||||
dracoLoader.setDecoderPath("/draco/");
|
||||
|
||||
const loader = new GLTFLoader();
|
||||
loader.setDRACOLoader(dracoLoader);
|
||||
|
||||
loader.load(
|
||||
modelUrl,
|
||||
(gltf) => {
|
||||
model = gltf.scene;
|
||||
|
||||
scene.add(model);
|
||||
|
||||
// Bounding Box nach dem Hinzufügen bestimmen
|
||||
const box = new THREE.Box3().setFromObject(model);
|
||||
const center = box.getCenter(new THREE.Vector3());
|
||||
const size = box.getSize(new THREE.Vector3());
|
||||
|
||||
const maxSize = Math.max(size.x, size.y, size.z);
|
||||
|
||||
// Kamera passend zum Objekt positionieren
|
||||
const distance = maxSize * 2;
|
||||
|
||||
screen = model.getObjectByName("fernseher1Bild");
|
||||
|
||||
// camera.position.set(center.x, center.y, center.z + distance);
|
||||
|
||||
// camera.lookAt(center);
|
||||
camera.position.set(
|
||||
center.x,
|
||||
center.y + distance * 0.35, // etwas von oben
|
||||
center.z + distance,
|
||||
);
|
||||
|
||||
camera.lookAt(center);
|
||||
|
||||
controls.target.copy(center);
|
||||
controls.update();
|
||||
|
||||
// OrbitControls auf das Objekt ausrichten
|
||||
controls.target.copy(center);
|
||||
controls.update();
|
||||
|
||||
console.log("Model geladen:", model);
|
||||
console.log("Center:", center);
|
||||
console.log("Size:", size);
|
||||
|
||||
const bulb = model.getObjectByName("light");
|
||||
|
||||
if (bulb) {
|
||||
console.log("Glühbirne gefunden:", bulb);
|
||||
|
||||
const pointLight = new THREE.PointLight(
|
||||
0xffd6a3, // Farbe
|
||||
5, // Intensität
|
||||
10, // Reichweite
|
||||
);
|
||||
|
||||
bulb.add(pointLight);
|
||||
}
|
||||
|
||||
document.title = "Model geladen";
|
||||
},
|
||||
(progress) => {
|
||||
if (progress.total) {
|
||||
const percent = ((progress.loaded / progress.total) * 100).toFixed(1);
|
||||
console.log(`Loading: ${percent}%`);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error("Fehler beim Laden des Modells:", error);
|
||||
document.title = "Fehler beim Laden!";
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const screen_on = ref(false);
|
||||
|
||||
function onCanvasClick(event) {
|
||||
const rect = canvasRef.value.getBoundingClientRect();
|
||||
|
||||
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
|
||||
const screen = model?.getObjectByName("screen");
|
||||
|
||||
if (!screen) return;
|
||||
|
||||
const intersects = raycaster.intersectObject(screen, true);
|
||||
|
||||
const texure_ski = new THREE.VideoTexture(video_ski);
|
||||
texure_ski.flipY = false;
|
||||
// texure_ski.offset.set(0.3, 2);
|
||||
// texure_ski.center.set(0.5, 0.5);
|
||||
texure_ski.repeat.set(4.3, 4.3);
|
||||
texure_ski.offset.set(-0.3, -0.33);
|
||||
|
||||
const normalTexture = new THREE.TextureLoader().load(normal_texture);
|
||||
normalTexture.flipY = false;
|
||||
|
||||
normalTexture.repeat.set(5.6, 5.6);
|
||||
normalTexture.offset.set(-0.54, -0.5);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
if (screen_on.value) {
|
||||
screen.material = new THREE.MeshBasicMaterial({
|
||||
map: normalTexture,
|
||||
});
|
||||
video_ski.pause();
|
||||
} else {
|
||||
screen.material = new THREE.MeshBasicMaterial({
|
||||
map: texure_ski,
|
||||
});
|
||||
video_ski.play();
|
||||
}
|
||||
screen_on.value = !screen_on.value;
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
if (!renderer) return;
|
||||
|
||||
controls.update();
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
function onResize() {
|
||||
if (!renderer || !canvasRef.value) return;
|
||||
const r = canvasRef.value.getBoundingClientRect();
|
||||
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
||||
|
||||
const width = canvasRef.value.clientWidth;
|
||||
const height = canvasRef.value.clientHeight;
|
||||
|
||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
||||
renderer.setSize(width, height, false);
|
||||
|
||||
camera.aspect = (r.width || 1) / (r.height || 1);
|
||||
camera.updateProjectionMatrix();
|
||||
}
|
||||
|
||||
const resizeObserver = new ResizeObserver(onResize);
|
||||
|
||||
onMounted(() => {
|
||||
initThree(canvasRef.value);
|
||||
onResize();
|
||||
canvasRef.value.addEventListener("click", onCanvasClick);
|
||||
|
||||
resizeObserver.observe(canvasRef.value);
|
||||
window.addEventListener("resize", onResize);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
gsap.ticker.remove(render);
|
||||
window.removeEventListener("resize", onResize);
|
||||
canvasRef.value?.removeEventListener("click", onCanvasClick);
|
||||
|
||||
resizeObserver.disconnect();
|
||||
renderer?.dispose();
|
||||
gsapCtx?.revert();
|
||||
// ScrollTrigger.getAll().forEach((t) => t.kill());
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<!-- <div class="spacer"></div> -->
|
||||
|
||||
<canvas class="canvas" ref="canvasRef"></canvas>
|
||||
</div>
|
||||
<div class="scroll-buffer"></div>
|
||||
<div class="spacer"></div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.spacer {
|
||||
width: 100%;
|
||||
height: 200vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.scroll-buffer {
|
||||
height: 100vh;
|
||||
}
|
||||
</style>
|
||||
@@ -9,6 +9,7 @@ import ScrollTrigger from "gsap/ScrollTrigger";
|
||||
import ScrollSmoother from "gsap/ScrollSmoother";
|
||||
import MonitorModel from "../components/big/MonitorModel.vue";
|
||||
import IntroductionSection from "../components/big/IntroductionSection.vue";
|
||||
import PcBooks from "../components/big/PcBooks.vue";
|
||||
// import NewTextSection from "../components/sections/NewTextSection.vue";
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
|
||||
@@ -42,6 +43,7 @@ onUnmounted(() => {
|
||||
|
||||
<IntroductionSection />
|
||||
<MonitorModel id="model" />
|
||||
<PcBooks id="model_pc" />
|
||||
<!-- <HeroSection id="hero" /> -->
|
||||
<!-- <ImageSection id="image" /> -->
|
||||
<TextSection id="text" />
|
||||
|
||||
@@ -146,7 +146,7 @@ onUnmounted(() => {
|
||||
|
||||
<style scoped>
|
||||
.component-wrapper {
|
||||
position: relative
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user