Hello.
I’ve created a Joomla module to display 3D GLB/GLTF models.
The module works correctly.
Now, I’d like this module to display compressed GLB/GLTF models, but I’m having trouble doing so (my JavaScript and three.js knowledge is probably insufficient). Could someone help me modify my default.php file to load the necessary DRACO and possibly KTX2 scripts?
<?php
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
$document = Factory::getDocument();
$modelUrl = $params->get('model_url', '');
$backgroundImage = $params->get('background_image', '');
$backgroundColor = $params->get('background_color', 'rgba(0,0,0,0)');
$width = $params->get('width', '100%');
$height = $params->get('height', '70vh');
// Paramètres pour le titre et commentaire
$title = $params->get('title', 'Titre par défaut');
$comment = $params->get('comment', 'Commentaire par défaut');
$titleColor = $params->get('title_color', 'rgba(255,255,255,1)');
$commentColor = $params->get('comment_color', 'rgba(255,255,255,1)');
$titleFontSize = $params->get('title_font_size', '24px');
$commentFontSize = $params->get('comment_font_size', '16px');
$cameraX = (float) $params->get('camera_x', 0);
$cameraY = (float) $params->get('camera_y', 0);
$cameraZ = (float) $params->get('camera_z', 2);
$rotationX = (float) $params->get('rotation_x', 0);
$rotationY = (float) $params->get('rotation_y', 0);
$rotationZ = (float) $params->get('rotation_z', 0);
$lightIntensity = (float) $params->get('light_intensity', 1.0);
$exposure = (float) $params->get('exposure', 1.0);
$document->addCustomTag("
<script type='module'>
import * as THREE from '../../modules/mod_anwynn_3d/assets/three.module.js';
import { GLTFLoader } from '../../modules/mod_anwynn_3d/assets/GLTFLoader.js';
import { DRACOLoader } from '../../modules/mod_anwynn_3d/assets/DRACOLoader.js';
import { OrbitControls } from '../../modules/mod_anwynn_3d/assets/OrbitControls.js';
console.log('Début du script 3D');
// Initialisation de la scène et de la caméra
const container = document.getElementById('anwynn-3d-container');
const scene = new THREE.Scene();
console.log('Scène créée');
const camera = new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000);
camera.position.set({$cameraX}, {$cameraY}, {$cameraZ});
console.log('Caméra positionnée');
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.toneMappingExposure = {$exposure};
container.appendChild(renderer.domElement);
console.log('Rendu initialisé');
" . (strpos($backgroundColor, '0)') !== false ? 'scene.background = null;' : "scene.background = new THREE.Color('{$backgroundColor}');") . "
const light = new THREE.HemisphereLight(0xffffff, 0x444444, {$lightIntensity});
scene.add(light);
console.log('Lumière ajoutée');
// Initialisation du DRACOLoader avec décodeur local
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/modules/mod_anwynn_3d/assets/draco/');
loader.setDRACOLoader(dracoLoader);
console.log('DRACOLoader configuré');
// Contrôles de la caméra
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableZoom = true;
controls.enablePan = true;
controls.enableRotate = false;
console.log('Contrôles de caméra ajoutés');
let model;
const modelGroup = new THREE.Group();
scene.add(modelGroup);
console.log('Groupe de modèles ajouté à la scène');
let isDragging = false;
let previousMousePosition = { x: 0, y: 0 };
// Gestion de l'erreur de chargement et du modèle
let isModelLoaded = false;
function loadModel(url) {
if (isModelLoaded) {
console.log('Le modèle a déjà été chargé.');
return;
}
console.log('Début du chargement du modèle GLTF');
loader.load(url, function (gltf) {
console.log('Modèle GLTF chargé');
model = gltf.scene;
const box = new THREE.Box3().setFromObject(model);
const center = box.getCenter(new THREE.Vector3());
model.position.sub(center);
model.rotation.set(
THREE.MathUtils.degToRad({$rotationX}),
THREE.MathUtils.degToRad({$rotationY}),
THREE.MathUtils.degToRad({$rotationZ})
);
modelGroup.add(model);
console.log('Modèle ajouté à la scène');
animate();
isModelLoaded = true;
}, undefined, function (error) {
console.error('Erreur de chargement du modèle :', error);
alert('Erreur de chargement du modèle : ' + error.message);
});
}
loadModel('{$modelUrl}');
renderer.domElement.addEventListener('pointerdown', (event) => {
isDragging = true;
previousMousePosition = {
x: event.clientX,
y: event.clientY
};
});
renderer.domElement.addEventListener('pointerup', () => {
isDragging = false;
});
renderer.domElement.addEventListener('pointermove', (event) => {
if (!isDragging) return;
const deltaMove = {
x: event.clientX - previousMousePosition.x,
y: event.clientY - previousMousePosition.y
};
modelGroup.rotation.y += deltaMove.x * 0.01;
modelGroup.rotation.x += deltaMove.y * 0.01;
previousMousePosition = {
x: event.clientX,
y: event.clientY
};
});
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
console.log('Scène rendue');
}
</script>
");
?>
<div style="margin:auto; text-align: center; color: <?php echo $titleColor; ?>; font-size: <?php echo $titleFontSize; ?>;">
<p><?php echo $title; ?></p>
</div>
<div id="anwynn-3d-container"
style="position: relative; width: <?php echo $width; ?>; height: <?php echo $height; ?>;
<?php echo $backgroundImage ? 'background-image: url(' . $backgroundImage . '); background-size: cover;' : ''; ?>">
</div>
<div style="margin:auto; text-align: center; color: <?php echo $commentColor; ?>; font-size: <?php echo $commentFontSize; ?>;">
<p><?php echo $comment; ?></p>
</div>