genesis
This commit is contained in:
27
cube.mtl
Normal file
27
cube.mtl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
## Alias OBJ Material File
|
||||||
|
# Exported from SketchUp, (c) 2000-2012 Trimble Navigation Limited
|
||||||
|
|
||||||
|
newmtl FrontColor
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 1.000000 1.000000 1.000000
|
||||||
|
Ks 0.330000 0.330000 0.330000
|
||||||
|
|
||||||
|
newmtl Glass_Basic_01
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.631373 0.678431 0.729412
|
||||||
|
Ks 0.330000 0.330000 0.330000
|
||||||
|
d 0.250000
|
||||||
|
|
||||||
|
newmtl Glass_Mirror_01
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.725490 0.725490 0.725490
|
||||||
|
Ks 0.330000 0.330000 0.330000
|
||||||
|
map_Kd cube/Glass_Mirror_01.jpg
|
||||||
|
|
||||||
|
newmtl Wood_Veneer_15_1K
|
||||||
|
Ka 0.000000 0.000000 0.000000
|
||||||
|
Kd 0.403922 0.270588 0.176471
|
||||||
|
Ks 0.330000 0.330000 0.330000
|
||||||
|
map_Kd cube/Wood_Veneer_15_1K.png
|
||||||
|
|
||||||
159
cube.obj
Normal file
159
cube.obj
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
# Alias OBJ Model File
|
||||||
|
# Exported from SketchUp, (c) 2000-2012 Trimble Navigation Limited
|
||||||
|
# File units = centimeters
|
||||||
|
|
||||||
|
mtllib cube.mtl
|
||||||
|
|
||||||
|
g Mesh1 Model
|
||||||
|
|
||||||
|
usemtl FrontColor
|
||||||
|
v 10 0 -15
|
||||||
|
vt -3.93701 5.90551
|
||||||
|
vn 0 -1 -0
|
||||||
|
v 0 0 -0
|
||||||
|
vt 0 0
|
||||||
|
v 0 0 -15
|
||||||
|
vt 0 5.90551
|
||||||
|
f 1/1/1 2/2/1 3/3/1
|
||||||
|
|
||||||
|
v 10 0 -0
|
||||||
|
vt -3.93701 0
|
||||||
|
f 2/2/1 1/1/1 4/4/1
|
||||||
|
|
||||||
|
vt 3.93701 0
|
||||||
|
vn 0 0 1
|
||||||
|
v 6.62348 5.82656 -0
|
||||||
|
vt 2.60767 2.29392
|
||||||
|
f 4/5/2 5/6/2 2/2/2
|
||||||
|
|
||||||
|
v 10 30 -0
|
||||||
|
vt 3.93701 11.811
|
||||||
|
f 5/6/2 4/5/2 6/7/2
|
||||||
|
|
||||||
|
v 6.62348 14.1266 -0
|
||||||
|
vt 2.60767 5.56164
|
||||||
|
f 5/6/2 6/7/2 7/8/2
|
||||||
|
|
||||||
|
v 6.62348 19.9196 -0
|
||||||
|
vt 2.60767 7.84236
|
||||||
|
f 7/8/2 6/7/2 8/9/2
|
||||||
|
|
||||||
|
v 6.62348 27.4225 -0
|
||||||
|
vt 2.60767 10.7963
|
||||||
|
f 8/9/2 6/7/2 9/10/2
|
||||||
|
|
||||||
|
v 2.22348 27.4225 -0
|
||||||
|
vt 0.875388 10.7963
|
||||||
|
f 9/10/2 6/7/2 10/11/2
|
||||||
|
|
||||||
|
v 0 30 -0
|
||||||
|
vt 0 11.811
|
||||||
|
f 11/12/2 10/11/2 6/7/2
|
||||||
|
|
||||||
|
v 2.22348 19.9196 -0
|
||||||
|
vt 0.875388 7.84236
|
||||||
|
f 11/12/2 12/13/2 10/11/2
|
||||||
|
|
||||||
|
v 2.22348 14.1266 -0
|
||||||
|
vt 0.875388 5.56164
|
||||||
|
f 11/12/2 13/14/2 12/13/2
|
||||||
|
|
||||||
|
v 2.22348 5.82656 -0
|
||||||
|
vt 0.875388 2.29392
|
||||||
|
f 11/12/2 14/15/2 13/14/2
|
||||||
|
|
||||||
|
f 2/2/2 14/15/2 11/12/2
|
||||||
|
|
||||||
|
f 14/15/2 2/2/2 5/6/2
|
||||||
|
|
||||||
|
usemtl Wood_Veneer_15_1K
|
||||||
|
vt 0.0883131 0.188354
|
||||||
|
vt 0.0296465 0.0776875
|
||||||
|
vt 0.0883131 0.0776875
|
||||||
|
f 7/16/2 14/17/2 5/18/2
|
||||||
|
|
||||||
|
vt 0.0296465 0.188354
|
||||||
|
f 14/17/2 7/16/2 13/19/2
|
||||||
|
|
||||||
|
usemtl FrontColor
|
||||||
|
f 7/8/2 8/9/2 13/14/2
|
||||||
|
|
||||||
|
f 12/13/2 13/14/2 8/9/2
|
||||||
|
|
||||||
|
usemtl Glass_Mirror_01
|
||||||
|
vt 0.0217306 0.089969
|
||||||
|
vt 0.0072949 0.065353
|
||||||
|
vt 0.0217306 0.065353
|
||||||
|
f 9/20/2 12/21/2 8/22/2
|
||||||
|
|
||||||
|
vt 0.0072949 0.089969
|
||||||
|
f 12/21/2 9/20/2 10/23/2
|
||||||
|
|
||||||
|
usemtl FrontColor
|
||||||
|
vn -1 0 -0
|
||||||
|
v 0 23.83 -4.67367
|
||||||
|
vt -1.84003 9.3819
|
||||||
|
f 11/12/3 15/24/3 2/2/3
|
||||||
|
|
||||||
|
v 0 30 -15
|
||||||
|
vt -5.90551 11.811
|
||||||
|
f 15/24/3 11/12/3 16/25/3
|
||||||
|
|
||||||
|
vn 0 1 -0
|
||||||
|
f 6/5/4 16/3/4 11/2/4
|
||||||
|
|
||||||
|
v 10 30 -15
|
||||||
|
vt 3.93701 5.90551
|
||||||
|
f 16/3/4 6/5/4 17/26/4
|
||||||
|
|
||||||
|
vt -3.93701 11.811
|
||||||
|
vn 0 0 -1
|
||||||
|
v 7.50938 19.9196 -15
|
||||||
|
vt -2.95645 7.84236
|
||||||
|
f 17/27/5 18/28/5 16/12/5
|
||||||
|
|
||||||
|
v 7.50938 13.8196 -15
|
||||||
|
vt -2.95645 5.44079
|
||||||
|
f 17/27/5 19/29/5 18/28/5
|
||||||
|
|
||||||
|
f 1/4/5 19/29/5 17/27/5
|
||||||
|
|
||||||
|
v 3.50938 13.8196 -15
|
||||||
|
vt -1.38165 5.44079
|
||||||
|
f 19/29/5 1/4/5 20/30/5
|
||||||
|
|
||||||
|
f 3/2/5 20/30/5 1/4/5
|
||||||
|
|
||||||
|
f 20/30/5 3/2/5 16/12/5
|
||||||
|
|
||||||
|
vt -5.90551 0
|
||||||
|
v 0 13.8196 -11.0737
|
||||||
|
vt -4.35971 5.44079
|
||||||
|
f 3/31/3 21/32/3 16/25/3
|
||||||
|
|
||||||
|
v 0 13.8196 -4.67367
|
||||||
|
vt -1.84003 5.44079
|
||||||
|
f 3/31/3 22/33/3 21/32/3
|
||||||
|
|
||||||
|
f 2/2/3 22/33/3 3/31/3
|
||||||
|
|
||||||
|
f 22/33/3 2/2/3 15/24/3
|
||||||
|
|
||||||
|
usemtl Glass_Basic_01
|
||||||
|
v 0 23.83 -11.0737
|
||||||
|
vt -4.35971 9.3819
|
||||||
|
f 23/34/3 22/33/3 15/24/3
|
||||||
|
|
||||||
|
f 22/33/3 23/34/3 21/32/3
|
||||||
|
|
||||||
|
usemtl FrontColor
|
||||||
|
f 23/34/3 16/25/3 21/32/3
|
||||||
|
|
||||||
|
f 15/24/3 16/25/3 23/34/3
|
||||||
|
|
||||||
|
v 3.50938 19.9196 -15
|
||||||
|
vt -1.38165 7.84236
|
||||||
|
f 20/30/5 16/12/5 24/35/5
|
||||||
|
|
||||||
|
f 24/35/5 16/12/5 18/28/5
|
||||||
|
|
||||||
BIN
cube/Glass_Mirror_01.jpg
Normal file
BIN
cube/Glass_Mirror_01.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
cube/Wood_Veneer_15_1K.png
Normal file
BIN
cube/Wood_Veneer_15_1K.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
525
index.html
Normal file
525
index.html
Normal file
@@ -0,0 +1,525 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>3D Cube Viewer</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#info {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
left: 20px;
|
||||||
|
color: white;
|
||||||
|
z-index: 100;
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 10px;
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#loading {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
color: white;
|
||||||
|
font-size: 24px;
|
||||||
|
z-index: 200;
|
||||||
|
background: rgba(0,0,0,0.7);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
border: 3px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top: 3px solid #ffffff;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
margin: 0 auto 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<div id="loading">
|
||||||
|
<div class="loading-spinner"></div>
|
||||||
|
Loading 3D Model...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="info">
|
||||||
|
<h2>3D Cube Viewer</h2>
|
||||||
|
<p>🖱️ Left click + drag: Rotate around model</p>
|
||||||
|
<p>🖱️ Right click + drag: Pan</p>
|
||||||
|
<p>⚙️ Mouse wheel: Zoom in/out</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Three.js Core -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||||
|
<!-- OBJ Loader -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/OBJLoader.js"></script>
|
||||||
|
<!-- MTL Loader -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/MTLLoader.js"></script>
|
||||||
|
<!-- Orbit Controls -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Global variables
|
||||||
|
let scene, camera, renderer, controls;
|
||||||
|
let cube;
|
||||||
|
|
||||||
|
// Initialize the 3D scene
|
||||||
|
function init() {
|
||||||
|
// Create container
|
||||||
|
const container = document.getElementById('container');
|
||||||
|
|
||||||
|
// Create scene
|
||||||
|
scene = new THREE.Scene();
|
||||||
|
scene.background = new THREE.Color(0x2c3e50);
|
||||||
|
|
||||||
|
// Create camera
|
||||||
|
camera = new THREE.PerspectiveCamera(
|
||||||
|
75, // Field of view
|
||||||
|
window.innerWidth / window.innerHeight, // Aspect ratio
|
||||||
|
0.1, // Near clipping plane
|
||||||
|
1000 // Far clipping plane
|
||||||
|
);
|
||||||
|
camera.position.set(20, 20, 20);
|
||||||
|
camera.lookAt(0, 0, 0);
|
||||||
|
|
||||||
|
// Create renderer
|
||||||
|
renderer = new THREE.WebGLRenderer({
|
||||||
|
antialias: true,
|
||||||
|
alpha: true
|
||||||
|
});
|
||||||
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||||
|
renderer.shadowMap.enabled = true;
|
||||||
|
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||||
|
renderer.outputEncoding = THREE.sRGBEncoding;
|
||||||
|
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||||
|
renderer.toneMappingExposure = 1;
|
||||||
|
|
||||||
|
// Enable proper transparency rendering
|
||||||
|
renderer.sortObjects = true;
|
||||||
|
renderer.autoClear = false;
|
||||||
|
|
||||||
|
container.appendChild(renderer.domElement);
|
||||||
|
|
||||||
|
// Add orbit controls
|
||||||
|
controls = new THREE.OrbitControls(camera, renderer.domElement);
|
||||||
|
controls.enableDamping = true;
|
||||||
|
controls.dampingFactor = 0.05;
|
||||||
|
controls.enableZoom = true;
|
||||||
|
controls.enablePan = true;
|
||||||
|
controls.enableRotate = true;
|
||||||
|
|
||||||
|
// Add lighting
|
||||||
|
setupLighting();
|
||||||
|
|
||||||
|
// Load the cube model
|
||||||
|
loadCubeModel();
|
||||||
|
|
||||||
|
// Handle window resize
|
||||||
|
window.addEventListener('resize', onWindowResize, false);
|
||||||
|
|
||||||
|
// Start render loop
|
||||||
|
animate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupLighting() {
|
||||||
|
// Ambient light for overall illumination
|
||||||
|
const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
|
||||||
|
scene.add(ambientLight);
|
||||||
|
|
||||||
|
// Directional light (like sunlight)
|
||||||
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
|
||||||
|
directionalLight.position.set(10, 10, 5);
|
||||||
|
directionalLight.castShadow = true;
|
||||||
|
directionalLight.shadow.mapSize.width = 2048;
|
||||||
|
directionalLight.shadow.mapSize.height = 2048;
|
||||||
|
scene.add(directionalLight);
|
||||||
|
|
||||||
|
// Point light for additional illumination
|
||||||
|
const pointLight = new THREE.PointLight(0xffffff, 0.6, 100);
|
||||||
|
pointLight.position.set(-10, 10, 10);
|
||||||
|
scene.add(pointLight);
|
||||||
|
|
||||||
|
// Interior point lights (will be repositioned when model loads)
|
||||||
|
window.interiorLight = new THREE.PointLight(0xffffff, 0.5, 50);
|
||||||
|
window.interiorLight.position.set(0, 0, 0); // Will be moved to model center
|
||||||
|
scene.add(window.interiorLight);
|
||||||
|
|
||||||
|
// Additional interior light for better coverage
|
||||||
|
window.interiorLight2 = new THREE.PointLight(0xffffff, 0.3, 30);
|
||||||
|
window.interiorLight2.position.set(5, 5, -5); // Will be adjusted relative to model
|
||||||
|
scene.add(window.interiorLight2);
|
||||||
|
|
||||||
|
// Hemisphere light for natural lighting
|
||||||
|
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.5);
|
||||||
|
scene.add(hemiLight);
|
||||||
|
|
||||||
|
// Create environment map for glass reflections
|
||||||
|
setupEnvironmentMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupEnvironmentMap() {
|
||||||
|
// Create a high-contrast environment map for more visible reflections
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = 512;
|
||||||
|
canvas.height = 512;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
// Create a more dramatic pattern for better visibility
|
||||||
|
|
||||||
|
// Background gradient
|
||||||
|
const backgroundGradient = ctx.createRadialGradient(256, 256, 0, 256, 256, 300);
|
||||||
|
backgroundGradient.addColorStop(0, '#ffffff'); // White center
|
||||||
|
backgroundGradient.addColorStop(0.3, '#87CEEB'); // Sky blue
|
||||||
|
backgroundGradient.addColorStop(0.6, '#4682B4'); // Steel blue
|
||||||
|
backgroundGradient.addColorStop(1, '#191970'); // Midnight blue
|
||||||
|
|
||||||
|
ctx.fillStyle = backgroundGradient;
|
||||||
|
ctx.fillRect(0, 0, 512, 512);
|
||||||
|
|
||||||
|
// Add high-contrast elements for visible reflections
|
||||||
|
ctx.fillStyle = '#ffffff';
|
||||||
|
ctx.fillRect(0, 0, 512, 100); // White stripe top
|
||||||
|
ctx.fillRect(0, 412, 512, 100); // White stripe bottom
|
||||||
|
ctx.fillRect(0, 0, 100, 512); // White stripe left
|
||||||
|
ctx.fillRect(412, 0, 100, 512); // White stripe right
|
||||||
|
|
||||||
|
// Add some geometric patterns
|
||||||
|
ctx.fillStyle = '#ffff00'; // Yellow accents
|
||||||
|
ctx.fillRect(200, 200, 112, 112); // Yellow square
|
||||||
|
|
||||||
|
ctx.fillStyle = '#ff4444'; // Red accents
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(356, 156, 50, 0, 2 * Math.PI);
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// Convert to texture with enhanced settings
|
||||||
|
const texture = new THREE.CanvasTexture(canvas);
|
||||||
|
texture.mapping = THREE.EquirectangularReflectionMapping;
|
||||||
|
texture.magFilter = THREE.LinearFilter;
|
||||||
|
texture.minFilter = THREE.LinearMipmapLinearFilter;
|
||||||
|
texture.generateMipmaps = true;
|
||||||
|
texture.flipY = false;
|
||||||
|
|
||||||
|
// Store for glass materials
|
||||||
|
window.environmentMap = texture;
|
||||||
|
|
||||||
|
console.log('High-contrast environment map created for glass reflections');
|
||||||
|
|
||||||
|
// Debug: Show environment map in console
|
||||||
|
console.log('Environment map texture:', texture);
|
||||||
|
console.log('Environment map size:', texture.image.width, 'x', texture.image.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadCubeModel() {
|
||||||
|
// Create loaders
|
||||||
|
const mtlLoader = new THREE.MTLLoader();
|
||||||
|
const objLoader = new THREE.OBJLoader();
|
||||||
|
|
||||||
|
// Load material file first
|
||||||
|
mtlLoader.load('cube.mtl', function(materials) {
|
||||||
|
materials.preload();
|
||||||
|
|
||||||
|
// Configure materials for double-sided rendering with proper transparency
|
||||||
|
Object.keys(materials.materials).forEach(function(key) {
|
||||||
|
const material = materials.materials[key];
|
||||||
|
material.side = THREE.DoubleSide;
|
||||||
|
|
||||||
|
// Handle glass materials specially
|
||||||
|
if (key.toLowerCase().includes('glass')) {
|
||||||
|
material.transparent = true;
|
||||||
|
|
||||||
|
// Preserve original opacity from MTL file (d value) - don't override
|
||||||
|
|
||||||
|
// Simple glass properties for visibility
|
||||||
|
material.shininess = 100;
|
||||||
|
material.reflectivity = 0.8;
|
||||||
|
|
||||||
|
// Apply environment map for reflections
|
||||||
|
if (window.environmentMap) {
|
||||||
|
material.envMap = window.environmentMap;
|
||||||
|
material.envMapIntensity = 1.5; // Moderate reflection intensity
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Glass material '${key}' - MTL opacity: ${material.opacity}`);
|
||||||
|
} else {
|
||||||
|
// Non-glass materials
|
||||||
|
material.transparent = false;
|
||||||
|
material.opacity = 1.0;
|
||||||
|
|
||||||
|
// Add slight emissive for interior visibility on solid materials
|
||||||
|
if (material.emissive) {
|
||||||
|
material.emissive.setHex(0x111111);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force material to update and recompile
|
||||||
|
material.needsUpdate = true;
|
||||||
|
|
||||||
|
// Double-check environment map application
|
||||||
|
if (!material.envMap && window.environmentMap) {
|
||||||
|
material.envMap = window.environmentMap;
|
||||||
|
console.log(`Fallback: Applied environment map to ${key}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set materials to OBJ loader
|
||||||
|
objLoader.setMaterials(materials);
|
||||||
|
|
||||||
|
// Load the OBJ file
|
||||||
|
objLoader.load('cube.obj', function(object) {
|
||||||
|
// Scale and position the model
|
||||||
|
object.scale.set(0.5, 0.5, 0.5);
|
||||||
|
object.position.set(0, 0, 0);
|
||||||
|
|
||||||
|
// Enable shadows and fix materials for interior faces
|
||||||
|
object.traverse(function(child) {
|
||||||
|
if (child instanceof THREE.Mesh) {
|
||||||
|
child.castShadow = true;
|
||||||
|
child.receiveShadow = true;
|
||||||
|
|
||||||
|
// Special handling for glass materials to improve visibility
|
||||||
|
if (child.material && child.material.name && child.material.name.toLowerCase().includes('glass')) {
|
||||||
|
// Glass-specific settings
|
||||||
|
child.material.side = THREE.DoubleSide;
|
||||||
|
child.material.transparent = true;
|
||||||
|
// Preserve original opacity from MTL file - don't override
|
||||||
|
child.material.alphaTest = 0.1;
|
||||||
|
|
||||||
|
// Enhanced reflective properties for maximum visibility
|
||||||
|
child.material.envMapIntensity = 2.0; // Maximum reflection intensity
|
||||||
|
child.material.reflectivity = 1.0; // Maximum reflectivity
|
||||||
|
child.material.shininess = 200; // Very high shininess
|
||||||
|
|
||||||
|
// Apply environment map for reflections
|
||||||
|
if (window.environmentMap) {
|
||||||
|
child.material.envMap = window.environmentMap;
|
||||||
|
child.material.combine = THREE.MixOperation;
|
||||||
|
child.material.refractionRatio = 0.98;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enhance specular for better visibility
|
||||||
|
child.material.specular = new THREE.Color(1.0, 1.0, 1.0);
|
||||||
|
child.material.color = new THREE.Color(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
// Disable shadow casting for glass (more realistic)
|
||||||
|
child.castShadow = false;
|
||||||
|
child.receiveShadow = true;
|
||||||
|
|
||||||
|
console.log(`=== Applied Glass Settings to Mesh ===`);
|
||||||
|
console.log(` Final Opacity: ${child.material.opacity}`);
|
||||||
|
console.log(` Environment Map Intensity: ${child.material.envMapIntensity}`);
|
||||||
|
console.log(` Material Type: ${child.material.type}`);
|
||||||
|
console.log(` Has Environment Map: ${child.material.envMap ? 'YES' : 'NO'}`);
|
||||||
|
console.log('=====================================');
|
||||||
|
|
||||||
|
// Add prominent wireframe to glass edges for better visibility
|
||||||
|
if (child.geometry) {
|
||||||
|
const wireframe = new THREE.EdgesGeometry(child.geometry);
|
||||||
|
const wireframeMaterial = new THREE.LineBasicMaterial({
|
||||||
|
color: 0x66bbff, // Brighter blue
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.8, // More visible
|
||||||
|
linewidth: 3 // Thicker lines
|
||||||
|
});
|
||||||
|
const wireframeLines = new THREE.LineSegments(wireframe, wireframeMaterial);
|
||||||
|
child.add(wireframeLines);
|
||||||
|
|
||||||
|
console.log('Added prominent wireframe edges to glass surface');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Non-glass materials
|
||||||
|
child.material.side = THREE.DoubleSide;
|
||||||
|
child.material.transparent = false;
|
||||||
|
child.material.opacity = 1.0;
|
||||||
|
|
||||||
|
// Ensure proper lighting on both sides
|
||||||
|
if (child.material.type === 'MeshLambertMaterial' || child.material.type === 'MeshPhongMaterial') {
|
||||||
|
child.material.emissive = new THREE.Color(0x111111); // Slight self-illumination
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force complete material update
|
||||||
|
child.material.needsUpdate = true;
|
||||||
|
|
||||||
|
// Force immediate shader recompilation
|
||||||
|
if (child.material.envMap) {
|
||||||
|
child.material.envMap.needsUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Store reference and add to scene
|
||||||
|
cube = object;
|
||||||
|
scene.add(cube);
|
||||||
|
|
||||||
|
// Calculate model center and adjust controls
|
||||||
|
centerModelAndControls(cube);
|
||||||
|
|
||||||
|
// Hide loading indicator
|
||||||
|
document.getElementById('loading').style.display = 'none';
|
||||||
|
|
||||||
|
console.log('Cube loaded successfully!');
|
||||||
|
},
|
||||||
|
function(progress) {
|
||||||
|
console.log('Loading progress:', (progress.loaded / progress.total * 100) + '%');
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.error('Error loading OBJ file:', error);
|
||||||
|
document.getElementById('loading').innerHTML =
|
||||||
|
'<div style="color: #ff6b6b;">Error loading model. Please check console for details.</div>';
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(progress) {
|
||||||
|
console.log('Loading MTL progress:', (progress.loaded / progress.total * 100) + '%');
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.error('Error loading MTL file:', error);
|
||||||
|
// Try to load OBJ without materials
|
||||||
|
loadObjWithoutMaterials();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadObjWithoutMaterials() {
|
||||||
|
const objLoader = new THREE.OBJLoader();
|
||||||
|
|
||||||
|
objLoader.load('cube.obj', function(object) {
|
||||||
|
// Apply default material with better interior visibility
|
||||||
|
const defaultMaterial = new THREE.MeshPhongMaterial({
|
||||||
|
color: 0xffffff,
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
transparent: false,
|
||||||
|
opacity: 1.0,
|
||||||
|
emissive: new THREE.Color(0x111111), // Slight self-illumination for interior visibility
|
||||||
|
shininess: 30
|
||||||
|
});
|
||||||
|
|
||||||
|
object.traverse(function(child) {
|
||||||
|
if (child instanceof THREE.Mesh) {
|
||||||
|
child.material = defaultMaterial.clone(); // Clone to avoid sharing
|
||||||
|
child.castShadow = true;
|
||||||
|
child.receiveShadow = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Scale and position
|
||||||
|
object.scale.set(0.5, 0.5, 0.5);
|
||||||
|
object.position.set(0, 0, 0);
|
||||||
|
|
||||||
|
cube = object;
|
||||||
|
scene.add(cube);
|
||||||
|
|
||||||
|
// Calculate model center and adjust controls
|
||||||
|
centerModelAndControls(cube);
|
||||||
|
|
||||||
|
document.getElementById('loading').style.display = 'none';
|
||||||
|
console.log('Cube loaded without materials!');
|
||||||
|
},
|
||||||
|
function(progress) {
|
||||||
|
console.log('Loading progress:', (progress.loaded / progress.total * 100) + '%');
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.error('Error loading OBJ file:', error);
|
||||||
|
document.getElementById('loading').innerHTML =
|
||||||
|
'<div style="color: #ff6b6b;">Failed to load model. Check if cube.obj exists.</div>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function centerModelAndControls(object) {
|
||||||
|
// Calculate the bounding box of the model
|
||||||
|
const boundingBox = new THREE.Box3().setFromObject(object);
|
||||||
|
|
||||||
|
// Get the center point of the bounding box
|
||||||
|
const center = boundingBox.getCenter(new THREE.Vector3());
|
||||||
|
|
||||||
|
// Get the size of the bounding box
|
||||||
|
const size = boundingBox.getSize(new THREE.Vector3());
|
||||||
|
|
||||||
|
// Set the orbit controls target to the model's center
|
||||||
|
controls.target.copy(center);
|
||||||
|
|
||||||
|
// Calculate optimal camera distance based on model size
|
||||||
|
const maxDimension = Math.max(size.x, size.y, size.z);
|
||||||
|
const fov = camera.fov * (Math.PI / 180);
|
||||||
|
const distance = Math.abs(maxDimension / Math.sin(fov / 2)) * 1.2; // 1.2 for some padding
|
||||||
|
|
||||||
|
// Position camera at optimal distance from model center
|
||||||
|
const direction = camera.position.clone().sub(center).normalize();
|
||||||
|
camera.position.copy(center).add(direction.multiplyScalar(distance));
|
||||||
|
|
||||||
|
// Update camera to look at the model center
|
||||||
|
camera.lookAt(center);
|
||||||
|
|
||||||
|
// Reposition interior lights relative to model center
|
||||||
|
if (window.interiorLight) {
|
||||||
|
window.interiorLight.position.copy(center);
|
||||||
|
|
||||||
|
// Adjust light range based on model size
|
||||||
|
window.interiorLight.distance = maxDimension * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.interiorLight2) {
|
||||||
|
window.interiorLight2.position.copy(center).add(new THREE.Vector3(
|
||||||
|
size.x * 0.3,
|
||||||
|
size.y * 0.3,
|
||||||
|
-size.z * 0.3
|
||||||
|
));
|
||||||
|
window.interiorLight2.distance = maxDimension * 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update controls
|
||||||
|
controls.update();
|
||||||
|
|
||||||
|
console.log('Model centered at:', center);
|
||||||
|
console.log('Model size:', size);
|
||||||
|
console.log('Camera positioned at:', camera.position);
|
||||||
|
}
|
||||||
|
|
||||||
|
function animate() {
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
|
||||||
|
// Update controls
|
||||||
|
controls.update();
|
||||||
|
|
||||||
|
// Clear and render with proper transparency sorting
|
||||||
|
renderer.clear();
|
||||||
|
renderer.render(scene, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWindowResize() {
|
||||||
|
camera.aspect = window.innerWidth / window.innerHeight;
|
||||||
|
camera.updateProjectionMatrix();
|
||||||
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize when page loads
|
||||||
|
window.addEventListener('load', init);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user