# Carga de Archivos IFC en FulcrumViewer

Este proyecto ahora soporta la visualización de archivos IFC (Industry Foundation Classes) junto con nubes de puntos.

## 📁 Archivos Creados

### 1. IFCLoader (`libs/three.js/extra/IFCLoader.js`)
Loader personalizado para cargar archivos IFC usando la librería web-ifc.

### 2. Ejemplo (`examples/ifc_viewer.html`)
Ejemplo funcional que muestra cómo integrar archivos IFC con Potree.

## 🚀 Uso Rápido

### Opción 1: Usar el Ejemplo HTML

1. Abre `examples/ifc_viewer.html` en tu navegador
2. Usa el botón "Examinar" para seleccionar un archivo `.ifc` de tu computadora
3. El modelo se cargará automáticamente en la escena

### Opción 2: Integrar en tu Código

```html
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="../build/potree/potree.css">
    <!-- ... otros estilos ... -->
</head>
<body>
    <div id="potree_render_area"></div>

    <!-- Scripts de Potree -->
    <script src="../build/potree/potree.js"></script>
    
    <!-- Web-IFC desde CDN -->
    <script src="https://cdn.jsdelivr.net/npm/web-ifc@0.0.44/web-ifc-api.js"></script>

    <script type="module">
        import * as THREE from '../libs/three.js/build/three.module.js';
        import { IFCLoader } from '../libs/three.js/extra/IFCLoader.js';

        // Inicializar Potree
        window.viewer = new Potree.Viewer(document.getElementById("potree_render_area"));
        
        viewer.setEDLEnabled(false);
        viewer.setFOV(60);
        viewer.setPointBudget(1_000_000);

        const scene = viewer.scene.scene;

        // Agregar luces para el modelo IFC
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
        scene.add(ambientLight);

        const directionalLight = new THREE.DirectionalLight(0xffeeff, 0.8);
        directionalLight.position.set(1, 1, 1);
        scene.add(directionalLight);

        // Cargar archivo IFC
        async function loadIFC(url) {
            const ifcLoader = new IFCLoader();
            
            ifcLoader.load(
                url,
                function (model) {
                    // Ajustar escala/rotación si es necesario
                    // model.mesh.rotation.x = Math.PI * 0.5; 
                    // model.mesh.scale.multiplyScalar(0.3048);
                    
                    scene.add(model.mesh);
                    viewer.fitToScreen();
                },
                function (progress) {
                    console.log('Cargando IFC:', progress);
                },
                function (error) {
                    console.error('Error:', error);
                }
            );
        }

        // Cargar tu archivo IFC
        loadIFC('../pointclouds/tu-modelo.ifc');
    </script>
</body>
</html>
```

## 🔧 Cargar Nubes de Puntos + IFC

Puedes cargar ambos en la misma escena:

```javascript
// Cargar nube de puntos
Potree.loadPointCloud("../pointclouds/tu-nube/cloud.js", "MiNube", e => {
    viewer.scene.addPointCloud(e.pointcloud);
    viewer.fitToScreen();
});

// Cargar modelo IFC
const ifcLoader = new IFCLoader();
ifcLoader.load('../pointclouds/tu-modelo.ifc', function (model) {
    // Ajustes de escala y rotación si es necesario
    model.mesh.rotation.x = Math.PI * 0.5; // 90 grados
    model.mesh.scale.multiplyScalar(0.3048); // pies a metros
    
    scene.add(model.mesh);
});
```

## ⚙️ Configuraciones Comunes

### Rotación y Escala

```javascript
// Rotar 90 grados en X (común cuando IFC está en orientación diferente)
model.mesh.rotation.x = Math.PI * 0.5;

// Convertir de pies a metros
model.mesh.scale.multiplyScalar(0.3048);

// Escala general
model.mesh.scale.set(1, 1, 1);
```

### Materiales

```javascript
// Cambiar material después de cargar
model.mesh.traverse(function(child) {
    if (child.isMesh) {
        child.material = new THREE.MeshPhongMaterial({
            color: 0x0088ff,
            side: THREE.DoubleSide
        });
    }
});
```

## 📦 Dependencias

La implementación utiliza **web-ifc** desde CDN (incluido automáticamente):
```html
<script src="https://cdn.jsdelivr.net/npm/web-ifc@0.0.44/web-ifc-api.js"></script>
```

## 🔍 Depuración

Abrir la consola del navegador para ver mensajes de log:

```javascript
// Desde la consola del navegador:
window.loadIFC('ruta/a/tu/archivo.ifc');
```

## ⚠️ Notas Importantes

1. **CORS**: Si cargas archivos desde el servidor, asegúrate de que CORS esté habilitado
2. **Tamaño**: Archivos IFC grandes pueden tardar en cargar
3. **Compatibilidad**: Funciona mejor con navegadores modernos (Chrome, Firefox, Edge)
4. **Formato**: Soporta archivos `.ifc` estándar (IFC2x3, IFC4)

## 🛠️ Solución de Problemas

### Error: "web-ifc is not loaded"
Asegúrate de incluir el script de web-ifc **antes** de cargar el IFCLoader:
```html
<script src="https://cdn.jsdelivr.net/npm/web-ifc@0.0.44/web-ifc-api.js"></script>
```

### El modelo no se ve
1. Verifica las luces en la escena
2. Ajusta la rotación: `model.mesh.rotation.x = Math.PI * 0.5`
3. Ajusta la escala si está muy grande/pequeño
4. Usa `viewer.fitToScreen()` para centrar la cámara

### Modelo en posición incorrecta
Ajusta la posición:
```javascript
model.mesh.position.set(x, y, z);
```

## 📚 Recursos Adicionales

- [Web-IFC Documentation](https://ifcjs.github.io/info/)
- [IFC.js Components](https://github.com/ifcjs/components)
- [Potree Documentation](https://github.com/potree/potree)

## 🎯 Ejemplo Completo

Ver `examples/ifc_viewer.html` para un ejemplo funcional completo.

## 📄 Licencia

MIT - Compatible con las licencias de Potree y web-ifc
