124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
|
|
import { Injectable } from '@angular/core';
|
||
|
|
import * as THREE from 'three';
|
||
|
|
import { RendererService } from './renderer.service';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Service responsible for managing the intersection plane
|
||
|
|
*/
|
||
|
|
@Injectable({
|
||
|
|
providedIn: 'root'
|
||
|
|
})
|
||
|
|
export class IntersectionPlaneService {
|
||
|
|
private intersectionPlane!: THREE.Mesh;
|
||
|
|
private planePosition: number = 8; // Position in 1/16th of a block
|
||
|
|
|
||
|
|
constructor(private rendererService: RendererService) {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates the intersection plane and adds it to the scene
|
||
|
|
*/
|
||
|
|
createIntersectionPlane(): THREE.Mesh {
|
||
|
|
const planeGeometry = new THREE.PlaneGeometry(3, 3);
|
||
|
|
const planeMaterial = new THREE.MeshBasicMaterial({
|
||
|
|
color: 0x00AA00,
|
||
|
|
transparent: true,
|
||
|
|
opacity: 0.05,
|
||
|
|
side: THREE.DoubleSide
|
||
|
|
});
|
||
|
|
|
||
|
|
this.intersectionPlane = new THREE.Mesh(planeGeometry, planeMaterial);
|
||
|
|
this.intersectionPlane.position.z = 0;
|
||
|
|
// Center the plane vertically with the player (player is about 2 blocks tall)
|
||
|
|
this.intersectionPlane.position.y = 1;
|
||
|
|
this.rendererService.scene.add(this.intersectionPlane);
|
||
|
|
|
||
|
|
return this.intersectionPlane;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Updates the plane position based on slider value
|
||
|
|
*/
|
||
|
|
updatePlanePosition(value: number): void {
|
||
|
|
this.planePosition = value;
|
||
|
|
// Convert from 1/16th block to Three.js units
|
||
|
|
const position = (this.planePosition / 16) - 0.5; // Center at 0
|
||
|
|
|
||
|
|
// Apply position based on the plane's current rotation
|
||
|
|
const rotation = this.intersectionPlane.rotation.y;
|
||
|
|
|
||
|
|
if (Math.abs(rotation) < 0.1 || Math.abs(rotation - Math.PI) < 0.1) {
|
||
|
|
// Camera in front (0) or behind (PI)
|
||
|
|
const direction = Math.abs(rotation) < 0.1 ? 1 : -1;
|
||
|
|
this.intersectionPlane.position.z = position * direction;
|
||
|
|
// Reset x position to avoid cumulative changes
|
||
|
|
this.intersectionPlane.position.x = 0;
|
||
|
|
} else {
|
||
|
|
// Camera on right (PI/2) or left (-PI/2)
|
||
|
|
const direction = rotation > 0 ? 1 : -1;
|
||
|
|
this.intersectionPlane.position.x = position * direction;
|
||
|
|
// Reset z position to avoid cumulative changes
|
||
|
|
this.intersectionPlane.position.z = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Updates the plane orientation based on camera position
|
||
|
|
*/
|
||
|
|
updatePlaneOrientation(camera: THREE.Camera): void {
|
||
|
|
if (!this.intersectionPlane) return;
|
||
|
|
|
||
|
|
// Calculate the angle between camera and player (in the XZ plane)
|
||
|
|
const cameraAngle = Math.atan2(
|
||
|
|
camera.position.x,
|
||
|
|
camera.position.z
|
||
|
|
);
|
||
|
|
|
||
|
|
// Determine which quadrant the camera is in with a 45-degree offset
|
||
|
|
const quadrant = Math.floor((cameraAngle + Math.PI + Math.PI / 4) / (Math.PI / 2)) % 4;
|
||
|
|
|
||
|
|
// Rotate the plane to face the camera
|
||
|
|
if (quadrant === 0) {
|
||
|
|
this.intersectionPlane.rotation.y = 0; // Camera in front
|
||
|
|
this.updatePlaneMaterial(0x00AA00);
|
||
|
|
} else if (quadrant === 1) {
|
||
|
|
this.intersectionPlane.rotation.y = Math.PI / 2; // Camera on right
|
||
|
|
this.updatePlaneMaterial(0x0000AA);
|
||
|
|
} else if (quadrant === 2) {
|
||
|
|
this.intersectionPlane.rotation.y = Math.PI; // Camera behind
|
||
|
|
this.updatePlaneMaterial(0x00AA00);
|
||
|
|
} else {
|
||
|
|
this.intersectionPlane.rotation.y = -Math.PI / 2; // Camera on left
|
||
|
|
this.updatePlaneMaterial(0x0000AA);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update position after rotation change
|
||
|
|
this.updatePlanePosition(this.planePosition);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Updates the plane material color
|
||
|
|
*/
|
||
|
|
private updatePlaneMaterial(color: number): void {
|
||
|
|
this.intersectionPlane.material = new THREE.MeshBasicMaterial({
|
||
|
|
color: color,
|
||
|
|
transparent: true,
|
||
|
|
opacity: 0.05,
|
||
|
|
side: THREE.DoubleSide
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Gets the intersection plane
|
||
|
|
*/
|
||
|
|
getIntersectionPlane(): THREE.Mesh {
|
||
|
|
return this.intersectionPlane;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Gets the current plane position
|
||
|
|
*/
|
||
|
|
getPlanePosition(): number {
|
||
|
|
return this.planePosition;
|
||
|
|
}
|
||
|
|
}
|