-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInteractiveObjects.js
More file actions
386 lines (386 loc) · 22.5 KB
/
InteractiveObjects.js
File metadata and controls
386 lines (386 loc) · 22.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
function _class_call_check(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for(var i = 0; i < props.length; i++){
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _create_class(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
import * as THREE from 'three';
import * as SceneConfig from './SceneConfig.js';
export var InteractiveObjects = /*#__PURE__*/ function() {
"use strict";
function InteractiveObjects() {
_class_call_check(this, InteractiveObjects);
}
_create_class(InteractiveObjects, null, [
{
key: "createInteractiveObjects",
value: function createInteractiveObjects(scene) {
var draggableObjects = [];
var COLORS = SceneConfig.COLORS, MATERIALS = SceneConfig.MATERIALS, SIZES = SceneConfig.SIZES;
// Salt Lamp 1 (on desk)
var saltLamp1 = this.createSaltLamp(COLORS.saltLamp, COLORS.saltLampEmissive);
saltLamp1.name = "Desk Salt Lamp";
saltLamp1.position.set(-SIZES.deskWidth / 2 + 0.15, SIZES.deskHeight + SIZES.saltLampHeight / 2 - 0.025, -1.5 - SIZES.deskDepth / 2 + 0.15);
saltLamp1.userData.isSaltLamp = true;
scene.add(saltLamp1);
draggableObjects.push(saltLamp1);
// Salt Lamp 2 (on side table)
var saltLamp2 = this.createSaltLamp(COLORS.saltLamp, COLORS.saltLampEmissive);
saltLamp2.name = "Side Table Salt Lamp";
saltLamp2.position.set(SIZES.roomWidth / 2 - 0.5, 0.6 + SIZES.saltLampHeight / 2 - 0.02, -1.0);
saltLamp2.userData.isSaltLamp = true;
scene.add(saltLamp2);
draggableObjects.push(saltLamp2);
// Coffee Cup (on desk)
var coffeeCup = this.createCoffeeCup(COLORS.coffeeCup, COLORS.coffeeLiquid);
coffeeCup.name = "Coffee Cup";
coffeeCup.position.set(SIZES.deskWidth / 2 - 0.2, SIZES.deskHeight + 0.05, -1.5);
scene.add(coffeeCup);
draggableObjects.push(coffeeCup);
// Books on desk
var book1 = this.createBook(COLORS.bookCover, COLORS.bookPages, "Book 1");
book1.position.set(0, SIZES.deskHeight + 0.05, -1.5 + SIZES.deskDepth / 3);
book1.rotation.y = 0.2;
scene.add(book1);
draggableObjects.push(book1);
var book2 = this.createBook(0x8B0000, COLORS.bookPages, "Book 2"); // Dark red book
book2.position.set(0.05, SIZES.deskHeight + 0.11, -1.5 + SIZES.deskDepth / 3 - 0.02); // Stacked
book2.rotation.y = 0.25;
scene.add(book2);
draggableObjects.push(book2);
// Small plant on side table
var plant = this.createPottedPlant(COLORS.plantPot, COLORS.plantLeaves);
plant.position.set(SIZES.roomWidth / 2 - 0.5 - 0.1, 0.6 + 0.02 + 0.075, -1.0 + 0.1); // potHeight/2
scene.add(plant);
draggableObjects.push(plant);
// Pen Holder on desk
var penHolder = this.createPenHolderWithPens(COLORS.penHolder, COLORS.penColors);
penHolder.position.set(-SIZES.deskWidth / 2 + 0.35, SIZES.deskHeight + 0.05, -1.5 - SIZES.deskDepth / 2 + 0.25);
scene.add(penHolder);
draggableObjects.push(penHolder);
return draggableObjects;
}
},
{
key: "createSaltLamp",
value: function createSaltLamp(color, emissiveColor) {
var SIZES = SceneConfig.SIZES;
// Irregular rock shape using a sphere with displacement or just a squashed sphere/cylinder
var geometry = new THREE.IcosahedronGeometry(SIZES.saltLampRadius, 1); // More rock-like
geometry.scale(1, 1.3, 0.8); // Make it less uniform
geometry.rotateX(Math.random() * Math.PI);
geometry.rotateY(Math.random() * Math.PI);
var material = SceneConfig.MATERIALS.emissive(color, emissiveColor, 0.7);
var lamp = new THREE.Mesh(geometry, material);
lamp.castShadow = true;
// Add a point light inside the salt lamp
var pointLight = new THREE.PointLight(emissiveColor, 2, 1.5); // color, intensity, distance
pointLight.castShadow = false; // Avoid too many shadow casters
lamp.add(pointLight); // Light is child of lamp, moves with it
return lamp;
}
},
{
key: "createCoffeeCup",
value: function createCoffeeCup(cupColor, liquidColor) {
var group = new THREE.Group();
var cupWallThickness = 0.005;
var cupHeight = 0.1;
var cupRadius = 0.04;
// Outer cup
var cupGeo = new THREE.CylinderGeometry(cupRadius, cupRadius * 0.9, cupHeight, 16);
var cupMat = SceneConfig.MATERIALS.plastic(cupColor);
var cupMesh = new THREE.Mesh(cupGeo, cupMat);
cupMesh.castShadow = true;
group.add(cupMesh);
// Inner liquid
var liquidGeo = new THREE.CylinderGeometry(cupRadius - cupWallThickness, (cupRadius - cupWallThickness) * 0.9, cupHeight * 0.8, 16);
var liquidMat = SceneConfig.MATERIALS.default.clone();
liquidMat.color.set(liquidColor);
liquidMat.roughness = 0.2;
var liquidMesh = new THREE.Mesh(liquidGeo, liquidMat);
liquidMesh.position.y = -0.01; // Slightly lower
group.add(liquidMesh);
// Simple handle
var handleGeo = new THREE.TorusGeometry(cupRadius * 0.6, 0.01, 8, 16, Math.PI);
var handleMat = cupMat;
var handle = new THREE.Mesh(handleGeo, handleMat);
handle.rotation.z = Math.PI / 2;
handle.position.x = cupRadius;
group.add(handle);
return group;
}
},
{
key: "createBook",
value: function createBook(coverColor, pageColor) {
var name = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "Book";
var group = new THREE.Group();
group.name = name;
var bookWidth = 0.15;
var bookHeight = 0.04;
var bookDepth = 0.22;
// Cover
var coverGeo = new THREE.BoxGeometry(bookWidth, bookHeight, bookDepth);
var coverMat = SceneConfig.MATERIALS.plastic(coverColor); // Using plastic for a slightly shiny cover
var coverMesh = new THREE.Mesh(coverGeo, coverMat);
coverMesh.castShadow = true;
group.add(coverMesh);
// Pages (slightly smaller inset)
var pagesGeo = new THREE.BoxGeometry(bookWidth * 0.95, bookHeight * 0.9, bookDepth * 0.98);
var pagesMat = SceneConfig.MATERIALS.default.clone();
pagesMat.color.set(pageColor);
var pagesMesh = new THREE.Mesh(pagesGeo, pagesMat);
pagesMesh.position.x = -bookWidth * 0.02; // Offset to simulate spine
group.add(pagesMesh);
return group;
}
},
{
key: "createPottedPlant",
value: function createPottedPlant(potColor, leafColor) {
var group = new THREE.Group();
group.name = "PottedPlant";
var potHeight = 0.1;
var potRadiusTop = 0.05;
var potRadiusBottom = 0.03;
// Pot
var potGeo = new THREE.CylinderGeometry(potRadiusTop, potRadiusBottom, potHeight, 12);
var potMat = SceneConfig.MATERIALS.plastic(potColor);
var potMesh = new THREE.Mesh(potGeo, potMat);
potMesh.castShadow = true;
group.add(potMesh);
// Simple "leaves" - a few green spheres
var leafMat = SceneConfig.MATERIALS.plastic(leafColor);
var leafPositions = [
{
x: 0,
y: potHeight / 2 + 0.04,
z: 0,
r: 0.04
},
{
x: 0.03,
y: potHeight / 2 + 0.03,
z: 0.01,
r: 0.03
},
{
x: -0.02,
y: potHeight / 2 + 0.035,
z: -0.015,
r: 0.035
},
{
x: 0.01,
y: potHeight / 2 + 0.05,
z: -0.02,
r: 0.025
}
];
leafPositions.forEach(function(pos) {
var leafGeo = new THREE.SphereGeometry(pos.r, 8, 6);
var leafMesh = new THREE.Mesh(leafGeo, leafMat);
leafMesh.position.set(pos.x, pos.y, pos.z);
leafMesh.castShadow = true;
group.add(leafMesh);
});
// Move the group so the base of the pot is at y=0 for easier positioning
group.position.y = potHeight / 2;
return group;
}
},
{
key: "createPenHolderWithPens",
value: function createPenHolderWithPens(holderColor, penColorsArray) {
var group = new THREE.Group();
group.name = "PenHolder";
var holderHeight = 0.08;
var holderRadius = 0.03;
// Holder
var holderGeo = new THREE.CylinderGeometry(holderRadius, holderRadius * 0.9, holderHeight, 16);
var holderMat = SceneConfig.MATERIALS.plastic(holderColor);
var holderMesh = new THREE.Mesh(holderGeo, holderMat);
holderMesh.castShadow = true;
group.add(holderMesh);
// Pens
var penHeight = 0.1;
var penRadius = 0.005;
var numPens = penColorsArray.length;
for(var i = 0; i < numPens; i++){
var penGeo = new THREE.CylinderGeometry(penRadius, penRadius * 0.8, penHeight, 8);
var penMat = SceneConfig.MATERIALS.plastic(penColorsArray[i]);
var penMesh = new THREE.Mesh(penGeo, penMat);
penMesh.castShadow = true;
// Position pens inside holder with slight variation
var angle = i / numPens * Math.PI * 2;
var randomOffset = holderRadius * 0.4;
penMesh.position.set(Math.cos(angle) * randomOffset, holderHeight / 2 - penHeight / 3, Math.sin(angle) * randomOffset);
penMesh.rotation.x = (Math.random() - 0.5) * 0.2; // Slight tilt
penMesh.rotation.z = (Math.random() - 0.5) * 0.2; // Slight tilt
group.add(penMesh);
}
// Move the group so the base of the holder is at y=0 for easier positioning
group.position.y = holderHeight / 2;
return group;
}
},
{
key: "createHangingVinePlant",
value: function createHangingVinePlant(potColor, leafColor) {
var vineColor = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 0x38761D;
var group = new THREE.Group();
group.name = "HangingVinePlant";
var MATERIALS = SceneConfig.MATERIALS;
// Pot
var potHeight = 0.08;
var potRadiusTop = 0.04;
var potRadiusBottom = 0.03;
var potGeo = new THREE.CylinderGeometry(potRadiusTop, potRadiusBottom, potHeight, 10);
var potMat = MATERIALS.plastic(potColor);
var potMesh = new THREE.Mesh(potGeo, potMat);
potMesh.castShadow = true;
group.add(potMesh);
// Simple "soil"
var soilGeo = new THREE.CylinderGeometry(potRadiusTop * 0.9, potRadiusBottom * 0.9, potHeight * 0.2, 10);
var soilMat = MATERIALS.default.clone();
soilMat.color.set(0x5D4037); // Dark brown
var soilMesh = new THREE.Mesh(soilGeo, soilMat);
soilMesh.position.y = potHeight / 2 - potHeight * 0.2 / 2; // Top of pot
group.add(soilMesh);
// Vines
var baseLeafMat = MATERIALS.plastic(leafColor).clone(); // Clone to modify locally
baseLeafMat.side = THREE.DoubleSide; // Make leaves visible from both sides
// baseLeafMat.roughness = 0.4; // Optional: Adjust for more sheen if desired
var leafMat = baseLeafMat;
var vineSegmentMat = MATERIALS.plastic(vineColor); // For vine segments
var numVines = 6; // Adjusted for balance with larger leaves
var vineSegments = 18; // Increased segments for more length/fullness
var segmentLength = 0.15; // Increased segment length
var segmentRadius = 0.008; // Slightly thicker vines
for(var i = 0; i < numVines; i++){
var vineGroup = new THREE.Group();
var currentY = potHeight / 2 - 0.01; // Start just below soil top
var currentX = (Math.random() - 0.5) * potRadiusTop * 0.8; // Increased spread for wider plant
var currentZ = (Math.random() - 0.5) * potRadiusTop * 0.8; // Increased spread for wider plant
// Initial leaf cluster on top
// Initial leaf cluster on top - using new leaf shape
var numTopLeaves = 3 + Math.floor(Math.random() * 3); // 3 to 5 top leaves
for(var k = 0; k < numTopLeaves; k++){
// Define a more Pothos-like leaf shape
var leafShape = new THREE.Shape();
var topLeafW = 0.045; // Increased width for top leaves
var topLeafH = 0.075; // Increased height for top leaves
leafShape.moveTo(0, -topLeafH * 0.05); // Start at base with slight indent
leafShape.bezierCurveTo(-topLeafW * 0.4, topLeafH * 0.1, -topLeafW * 0.5, topLeafH * 0.5, -topLeafW * 0.3, topLeafH * 0.7);
leafShape.bezierCurveTo(-topLeafW * 0.1, topLeafH * 0.95, 0, topLeafH, 0, topLeafH); // Tip
leafShape.bezierCurveTo(topLeafW * 0.1, topLeafH * 0.95, topLeafW * 0.3, topLeafH * 0.7, topLeafW * 0.5, topLeafH * 0.5);
leafShape.bezierCurveTo(topLeafW * 0.4, topLeafH * 0.1, 0, -topLeafH * 0.05, 0, -topLeafH * 0.05);
leafShape.closePath();
var topLeafGeo = new THREE.ShapeGeometry(leafShape, 6); // 6 curve segments for a balance of detail and performance
// Apply a bend to top leaves
var topPositions = topLeafGeo.attributes.position;
var topBendFactor = 0.012; // Increased bend for larger leaves
for(var l = 0; l < topPositions.count; l++){
var yPos = topPositions.getY(l);
var normalizedY = (yPos + topLeafH * 0.05) / (topLeafH * 1.05); // Normalize from approx 0 to 1
var zOffset = Math.sin(normalizedY * Math.PI) * topBendFactor;
topPositions.setZ(l, topPositions.getZ(l) + zOffset);
}
topLeafGeo.attributes.position.needsUpdate = true;
topLeafGeo.computeVertexNormals();
var topLeaf = new THREE.Mesh(topLeafGeo, leafMat);
topLeaf.castShadow = true;
topLeaf.position.set(currentX + (Math.random() - 0.5) * 0.02, currentY + 0.01, currentZ + (Math.random() - 0.5) * 0.02);
topLeaf.rotation.x = Math.PI / 2 + (Math.random() - 0.5) * 0.8;
topLeaf.rotation.y = Math.random() * Math.PI * 2;
topLeaf.rotation.z = (Math.random() - 0.5) * 0.5;
vineGroup.add(topLeaf);
}
for(var j = 0; j < vineSegments; j++){
var segmentGeo = new THREE.CapsuleGeometry(segmentRadius, segmentLength, 4, 8);
var segmentMesh = new THREE.Mesh(segmentGeo, vineSegmentMat);
segmentMesh.castShadow = true;
segmentMesh.position.set(currentX + (Math.random() - 0.5) * 0.02, currentY - segmentLength / 2, currentZ + (Math.random() - 0.5) * 0.02 // Slight horizontal drift
);
segmentMesh.rotation.x = (Math.random() - 0.5) * 0.4;
segmentMesh.rotation.z = (Math.random() - 0.5) * 0.4;
vineGroup.add(segmentMesh);
currentY -= segmentLength * 0.9; // Move down for next segment (slight overlap)
currentX = segmentMesh.position.x;
currentZ = segmentMesh.position.z;
// Add a small leaf to some segments
// Add a small leaf to some segments, making it more intermittent
// j > 0 && j < vineSegments -1 ensures leaves are not on the very first or last segment for a cleaner look
if (j > 0 && j < vineSegments - 2 && Math.random() > 0.65) {
// Define a more Pothos-like leaf shape for vine leaves
var vineLeafShape = new THREE.Shape();
var leafW = 0.042; // Increased width for vine leaves
var leafH = 0.06; // Increased height for vine leaves
vineLeafShape.moveTo(0, -leafH * 0.05); // Start at base with slight indent
// Left side
vineLeafShape.bezierCurveTo(-leafW * 0.4, leafH * 0.1, -leafW * 0.5, leafH * 0.5, -leafW * 0.3, leafH * 0.7);
vineLeafShape.bezierCurveTo(-leafW * 0.1, leafH * 0.95, 0, leafH, 0, leafH); // Tip
// Right side (mirroring)
vineLeafShape.bezierCurveTo(leafW * 0.1, leafH * 0.95, leafW * 0.3, leafH * 0.7, leafW * 0.5, leafH * 0.5);
vineLeafShape.bezierCurveTo(leafW * 0.4, leafH * 0.1, 0, -leafH * 0.05, 0, -leafH * 0.05);
vineLeafShape.closePath();
var leafGeo = new THREE.ShapeGeometry(vineLeafShape, 6); // 6 curve segments for balance
// Apply a bend to the leaf
var positions = leafGeo.attributes.position;
var bendFactor = 0.009; // Increased bend for larger leaves
for(var k1 = 0; k1 < positions.count; k1++){
var y = positions.getY(k1);
// Apply a curve along the length of the leaf (Y-axis of the shape)
var normalizedY1 = (y + leafH * 0.05) / (leafH * 1.05); // Normalize y from approx 0 to 1 along leaf length
var zOffset1 = Math.sin(normalizedY1 * Math.PI) * bendFactor;
positions.setZ(k1, positions.getZ(k1) + zOffset1);
}
leafGeo.attributes.position.needsUpdate = true;
leafGeo.computeVertexNormals(); // Crucial after modifying vertices
var leafMesh = new THREE.Mesh(leafGeo, leafMat);
leafMesh.castShadow = true;
// Position and rotate leaf for a more natural look
leafMesh.position.set((Math.random() - 0.5) * 0.015, segmentLength * 0.2 * (Math.random() > 0.5 ? 1 : -1) - leafH / 2 * 0.3, segmentRadius + leafH * 0.1 // Attach to the side of the vine
);
// Random rotations for natural variation
leafMesh.rotation.x = Math.PI / 2 + (Math.random() - 0.5) * 0.5; // Point downwards more
leafMesh.rotation.y = (Math.random() - 0.5) * Math.PI * 0.8; // Twist
leafMesh.rotation.z = (Math.random() - 0.5) * 0.3; // Slight sideways tilt
// Add a second leaf for a fuller look sometimes
var addSecondLeaf = Math.random() > 0.5;
segmentMesh.add(leafMesh); // Add as child of segment
if (addSecondLeaf) {
var leafMesh2 = leafMesh.clone();
leafMesh2.position.set((Math.random() - 0.5) * 0.015, segmentLength * 0.2 * (Math.random() > 0.5 ? 1 : -1) - leafH / 2 * 0.3, -(segmentRadius + leafH * 0.1 // Opposite side
));
leafMesh2.rotation.x = Math.PI / 2 + (Math.random() - 0.5) * 0.5;
leafMesh2.rotation.y = (Math.random() - 0.5) * Math.PI * 0.8;
leafMesh2.rotation.z = (Math.random() - 0.5) * 0.3;
segmentMesh.add(leafMesh2);
}
}
}
group.add(vineGroup);
}
// Move the group so the base of the pot is at y=0 for easier positioning
group.position.y = potHeight / 2;
return group;
}
}
]);
return InteractiveObjects;
}();