190 lines
5.4 KiB
JavaScript
190 lines
5.4 KiB
JavaScript
/**
|
|
* Railtrack Pro - Track Piece System
|
|
* Defines track geometries and placement logic
|
|
* @author Railtrack Pro Development Team
|
|
*/
|
|
|
|
class TrackPiece {
|
|
constructor(type, position, rotation) {
|
|
this.type = type; // 'straight', 'curved', 'junction', 'signal'
|
|
this.id = position ? Math.floor(Math.random() * 10000) : null;
|
|
this.position = position || new THREE.Vector3(0, 0, 0);
|
|
this.rotation = rotation || new THREE.Vector3(0, Math.PI / 2, 0);
|
|
this.connections = [];
|
|
this.geometry = null;
|
|
this.material = null;
|
|
this.mesh = null;
|
|
}
|
|
|
|
/**
|
|
* Create track piece in scene
|
|
*/
|
|
create(scene) {
|
|
this.geometry = this.getGeometry();
|
|
this.material = new THREE.MeshStandardMaterial({
|
|
color: 0x888888,
|
|
roughness: 0.6,
|
|
metalness: 0.4
|
|
});
|
|
|
|
this.mesh = new THREE.Mesh(this.geometry, this.material);
|
|
this.mesh.position.copy(this.position);
|
|
this.mesh.rotation.copy(this.rotation);
|
|
this.mesh.castShadow = true;
|
|
this.mesh.receiveShadow = true;
|
|
this.mesh.userData = { type: 'track', id: this.id, piece: this };
|
|
|
|
scene.add(this.mesh);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Get geometry based on track type
|
|
*/
|
|
getGeometry() {
|
|
switch (this.type) {
|
|
case 'straight':
|
|
return new THREE.BoxGeometry(1, 0.3, 2);
|
|
case 'curved':
|
|
return this.createCurvedGeometry();
|
|
case 'junction':
|
|
return this.createJunctionGeometry();
|
|
case 'signal':
|
|
return this.createSignalGeometry();
|
|
default:
|
|
return new THREE.BoxGeometry(1, 0.3, 2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create curved track geometry
|
|
*/
|
|
createCurvedGeometry() {
|
|
const points = [];
|
|
const segments = 20;
|
|
const radius = 2;
|
|
|
|
for (let i = 0; i <= segments; i++) {
|
|
const angle = (i / segments) * Math.PI;
|
|
const x = Math.sin(angle) * radius;
|
|
const z = -Math.cos(angle) * radius + radius;
|
|
points.push(new THREE.Vector3(x, 0, z));
|
|
}
|
|
|
|
const curve = new THREE.CatmullRomCurve3(points);
|
|
const geometry = new THREE.TubeGeometry(curve, segments, 0.5, 8, false);
|
|
return geometry;
|
|
}
|
|
|
|
/**
|
|
* Create junction track geometry (T-junction)
|
|
*/
|
|
createJunctionGeometry() {
|
|
const group = new THREE.Group();
|
|
|
|
// Main stem
|
|
const stem = new THREE.Mesh(
|
|
new THREE.BoxGeometry(1, 0.3, 2),
|
|
this.material
|
|
);
|
|
stem.position.set(0, 0, 1);
|
|
|
|
// Top branch
|
|
const top = new THREE.Mesh(
|
|
new THREE.BoxGeometry(1, 0.3, 2),
|
|
this.material
|
|
);
|
|
top.position.set(0, 0, -1);
|
|
|
|
// Side branch
|
|
const side = new THREE.Mesh(
|
|
new THREE.BoxGeometry(2, 0.3, 1),
|
|
this.material
|
|
);
|
|
side.position.set(0, 0, 0);
|
|
|
|
group.add(stem, top, side);
|
|
|
|
const geometry = new THREE.Group(group);
|
|
return geometry;
|
|
}
|
|
|
|
/**
|
|
* Create signal track piece
|
|
*/
|
|
createSignalGeometry() {
|
|
const group = new THREE.Group();
|
|
|
|
// Signal pole
|
|
const pole = new THREE.Mesh(
|
|
new THREE.CylinderGeometry(0.1, 0.1, 1.5),
|
|
new THREE.MeshStandardMaterial({ color: 0x333333 })
|
|
);
|
|
pole.position.set(0, 0.75, 0);
|
|
|
|
// Signal lights
|
|
const lightBox = new THREE.Mesh(
|
|
new THREE.BoxGeometry(0.3, 0.2, 0.1),
|
|
new THREE.MeshStandardMaterial({ color: 0xff0000 })
|
|
);
|
|
lightBox.position.set(0, 1.5, 0);
|
|
|
|
// Track base
|
|
const base = new THREE.Mesh(
|
|
new THREE.BoxGeometry(1, 0.3, 1),
|
|
this.material
|
|
);
|
|
base.position.set(0, 0, 0);
|
|
|
|
group.add(base, pole, lightBox);
|
|
|
|
const geometry = new THREE.Group(group);
|
|
return geometry;
|
|
}
|
|
|
|
/**
|
|
* Get connection points for track joining
|
|
*/
|
|
getConnectionPoints() {
|
|
const points = [];
|
|
switch (this.type) {
|
|
case 'straight':
|
|
points.push(new THREE.Vector3(0, 0, -1));
|
|
points.push(new THREE.Vector3(0, 0, 1));
|
|
break;
|
|
case 'curved':
|
|
points.push(new THREE.Vector3(0, 0, -2));
|
|
points.push(new THREE.Vector3(2, 0, 0));
|
|
break;
|
|
case 'junction':
|
|
points.push(new THREE.Vector3(0, 0, -2));
|
|
points.push(new THREE.Vector3(0, 0, 2));
|
|
points.push(new THREE.Vector3(-2, 0, 0));
|
|
points.push(new THREE.Vector3(2, 0, 0));
|
|
break;
|
|
}
|
|
return points;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Track type configuration
|
|
*/
|
|
const TrackConfig = {
|
|
types: {
|
|
straight: { name: 'Straight Track', color: 0x888888, cost: 10 },
|
|
curved: { name: 'Curved Track', color: 0x888888, cost: 15 },
|
|
junction: { name: 'Junction', color: 0x888888, cost: 25 },
|
|
signal: { name: 'Signal', color: 0xff0000, cost: 30 }
|
|
},
|
|
placement: {
|
|
snapDistance: 0.1,
|
|
maxConnections: 4
|
|
}
|
|
};
|
|
|
|
// Export for module usage
|
|
if (typeof module !== 'undefined' && module.exports) {
|
|
module.exports = { TrackPiece, TrackConfig };
|
|
}
|