Spaces:
Running
Running
Update deplacement_dans_env/viewer_pr_env.js
Browse files
deplacement_dans_env/viewer_pr_env.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
| 1 |
// viewer_pr_env.js
|
| 2 |
// ==============================
|
| 3 |
-
// Version 2.
|
| 4 |
-
// -
|
| 5 |
// - Utilise RigidBody (dynamique) pour le joueur (capsule)
|
| 6 |
// - Utilise RigidBody (statique) pour l'environnement (mesh)
|
| 7 |
// - Gère la gravité, le "vrai" mesh des portes, etc.
|
| 8 |
-
// - L'ancien fichier camera.js n'est plus
|
| 9 |
|
| 10 |
/* -------------------------------------------
|
| 11 |
Utils communs (Inchangés)
|
|
@@ -63,7 +63,7 @@ function traverse(entity, callback) {
|
|
| 63 |
}
|
| 64 |
}
|
| 65 |
|
| 66 |
-
// Helpers math (Inchangés
|
| 67 |
function vAdd(a,b){ return new pc.Vec3(a.x+b.x,a.y+b.y,a.z+b.z); }
|
| 68 |
function vSub(a,b){ return new pc.Vec3(a.x-b.x,a.y-b.y,a.z-b.z); }
|
| 69 |
function vScale(v,s){ return new pc.Vec3(v.x*s,v.y*s,v.z*s); }
|
|
@@ -134,7 +134,7 @@ function registerFirstPersonScripts() {
|
|
| 134 |
this.yaw -= e.dx * this.lookSpeed;
|
| 135 |
this.pitch -= e.dy * this.lookSpeed;
|
| 136 |
this.pitch = pc.math.clamp(this.pitch, this.pitchAngleMin, this.pitchAngleMax);
|
| 137 |
-
|
| 138 |
|
| 139 |
FirstPersonCamera.prototype.update = function (dt) {
|
| 140 |
// --- 1. Rotation (Look) ---
|
|
@@ -148,27 +148,30 @@ function registerFirstPersonScripts() {
|
|
| 148 |
// --- 2. Mouvement (Clavier) ---
|
| 149 |
var fwd = 0;
|
| 150 |
var strf = 0;
|
|
|
|
| 151 |
|
| 152 |
-
if (
|
| 153 |
fwd += 1;
|
| 154 |
}
|
| 155 |
-
if (
|
| 156 |
fwd -= 1;
|
| 157 |
}
|
| 158 |
-
if (
|
| 159 |
strf -= 1;
|
| 160 |
}
|
| 161 |
-
if (
|
| 162 |
strf += 1;
|
| 163 |
}
|
| 164 |
|
|
|
|
|
|
|
|
|
|
| 165 |
if (fwd !== 0 || strf !== 0) {
|
| 166 |
// On utilise les vecteurs de l'entité (qui a le yaw)
|
| 167 |
var forward = this.entity.forward;
|
| 168 |
var right = this.entity.right;
|
| 169 |
|
| 170 |
// Calcule la force de déplacement
|
| 171 |
-
this.force.set(0, 0, 0);
|
| 172 |
this.force.add(forward.mulScalar(fwd));
|
| 173 |
this.force.add(right.mulScalar(strf));
|
| 174 |
|
|
@@ -184,20 +187,18 @@ function registerFirstPersonScripts() {
|
|
| 184 |
this.velocity.copy(this.entity.rigidbody.linearVelocity);
|
| 185 |
|
| 186 |
// Définit la vélocité XZ (mouvement)
|
|
|
|
| 187 |
this.velocity.x = this.force.x * this.moveSpeed;
|
| 188 |
this.velocity.z = this.force.z * this.moveSpeed;
|
| 189 |
|
| 190 |
// Applique la nouvelle vélocité (conserve Y pour la gravité)
|
| 191 |
this.entity.rigidbody.linearVelocity = this.velocity;
|
| 192 |
}
|
| 193 |
-
|
| 194 |
-
// Reset la force pour la prochaine frame
|
| 195 |
-
this.force.set(0, 0, 0);
|
| 196 |
};
|
| 197 |
}
|
| 198 |
|
| 199 |
/* -------------------------------------------
|
| 200 |
-
State (
|
| 201 |
-------------------------------------------- */
|
| 202 |
|
| 203 |
let pc;
|
|
@@ -210,13 +211,15 @@ let viewerInitialized = false;
|
|
| 210 |
let resizeObserver = null;
|
| 211 |
let resizeTimeout = null;
|
| 212 |
|
| 213 |
-
//
|
| 214 |
let chosenCameraX, chosenCameraY, chosenCameraZ;
|
| 215 |
let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minY;
|
| 216 |
let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
|
| 217 |
let presentoirScaleX, presentoirScaleY, presentoirScaleZ;
|
| 218 |
let sogUrl, glbUrl, presentoirUrl;
|
| 219 |
let color_bg_hex, color_bg, espace_expo_bool;
|
|
|
|
|
|
|
| 220 |
let maxDevicePixelRatio = 1.75;
|
| 221 |
let interactDpr = 1.0;
|
| 222 |
let idleRestoreDelay = 350;
|
|
@@ -297,12 +300,13 @@ export async function initializeViewer(config, instanceId) {
|
|
| 297 |
|
| 298 |
const canvas = document.createElement("canvas");
|
| 299 |
canvas.id = canvasId;
|
| 300 |
-
// ... (tous les listeners de canvas sont conservés) ...
|
| 301 |
canvas.className = "ply-canvas";
|
| 302 |
canvas.style.width = "100%";
|
| 303 |
canvas.style.height = "100%";
|
| 304 |
canvas.setAttribute("tabindex", "0");
|
| 305 |
viewerContainer.insertBefore(canvas, progressDialog);
|
|
|
|
|
|
|
| 306 |
canvas.style.touchAction = "none";
|
| 307 |
canvas.style.webkitTouchCallout = "none";
|
| 308 |
canvas.addEventListener("gesturestart", (e) => e.preventDefault());
|
|
@@ -359,11 +363,25 @@ export async function initializeViewer(config, instanceId) {
|
|
| 359 |
device.maxPixelRatio = Math.min(window.devicePixelRatio || 1, maxDevicePixelRatio);
|
| 360 |
|
| 361 |
const opts = new pc.AppOptions();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
opts.graphicsDevice = device;
|
| 363 |
opts.mouse = new pc.Mouse(canvas);
|
| 364 |
opts.touch = new pc.TouchDevice(canvas);
|
| 365 |
opts.keyboard = new pc.Keyboard(canvas);
|
| 366 |
-
Note:
|
| 367 |
opts.componentSystems = [
|
| 368 |
pc.RenderComponentSystem,
|
| 369 |
pc.CameraComponentSystem,
|
|
@@ -380,7 +398,7 @@ Note: This component system list *must* include RigidBody and Collision.
|
|
| 380 |
app.setCanvasResolution(pc.RESOLUTION_AUTO);
|
| 381 |
|
| 382 |
// *** NOUVEAU : Définir la gravité pour le monde physique ***
|
| 383 |
-
app.systems.rigidbody.gravity.set(0, -9.81, 0);
|
| 384 |
|
| 385 |
// --- Debounce resize (Inchangé) ---
|
| 386 |
resizeObserver = new ResizeObserver((entries) => {
|
|
@@ -412,6 +430,7 @@ Note: This component system list *must* include RigidBody and Collision.
|
|
| 412 |
});
|
| 413 |
|
| 414 |
// --- Chargement des assets (Inchangé) ---
|
|
|
|
| 415 |
const sogAsset = new pc.Asset("gsplat", "gsplat", { url: sogUrl });
|
| 416 |
const glbAsset = new pc.Asset("glb", "container", { url: glbUrl });
|
| 417 |
app.assets.add(sogAsset);
|
|
@@ -452,6 +471,7 @@ Note: This component system list *must* include RigidBody and Collision.
|
|
| 452 |
if (node.render) {
|
| 453 |
meshCount++;
|
| 454 |
// 1. Le rend statique (il ne bouge pas)
|
|
|
|
| 455 |
node.addComponent('rigidbody', {
|
| 456 |
type: pc.BODYTYPE_STATIC,
|
| 457 |
restitution: 0.0
|
|
@@ -478,16 +498,16 @@ Note: This component system list *must* include RigidBody and Collision.
|
|
| 478 |
playerEntity.addComponent('rigidbody', {
|
| 479 |
type: pc.BODYTYPE_DYNAMIC,
|
| 480 |
mass: 70, // Poids d'un humain
|
| 481 |
-
friction: 0.
|
| 482 |
-
restitution: 0.0,
|
| 483 |
angularFactor: new pc.Vec3(0, 0, 0) // Empêche la capsule de basculer
|
| 484 |
});
|
| 485 |
|
| 486 |
// Ajoute une forme de collision CAPSULE
|
| 487 |
playerEntity.addComponent('collision', {
|
| 488 |
type: 'capsule',
|
| 489 |
-
radius: 0.35,
|
| 490 |
-
height: 1.7
|
| 491 |
});
|
| 492 |
|
| 493 |
// 2. L'entité "Camera" (les yeux)
|
|
@@ -498,7 +518,8 @@ Note: This component system list *must* include RigidBody and Collision.
|
|
| 498 |
farClip: 250
|
| 499 |
});
|
| 500 |
// Positionne la caméra à hauteur des "yeux" dans la capsule
|
| 501 |
-
|
|
|
|
| 502 |
|
| 503 |
// 3. Attache la caméra au joueur
|
| 504 |
playerEntity.addChild(cameraEntity);
|
|
@@ -508,7 +529,7 @@ Note: This component system list *must* include RigidBody and Collision.
|
|
| 508 |
playerEntity.script.create("orbitCamera", {
|
| 509 |
attributes: {
|
| 510 |
cameraEntity: cameraEntity,
|
| 511 |
-
moveSpeed: 4.0, //
|
| 512 |
lookSpeed: 0.25,
|
| 513 |
pitchAngleMax: maxAngle, // Utilise vos configs
|
| 514 |
pitchAngleMin: minAngle
|
|
@@ -533,7 +554,6 @@ Note: This component system list *must* include RigidBody and Collision.
|
|
| 533 |
if (app.graphicsDevice.maxPixelRatio !== clamped) {
|
| 534 |
app.graphicsDevice.maxPixelRatio = clamped;
|
| 535 |
app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
|
| 536 |
-
---
|
| 537 |
}
|
| 538 |
};
|
| 539 |
const bumpInteraction = () => {
|
|
@@ -566,8 +586,13 @@ export function resetViewerCamera() {
|
|
| 566 |
|
| 567 |
// Téléporte le JOUEUR (pas la caméra)
|
| 568 |
playerEntity.rigidbody.teleport(chosenCameraX, chosenCameraY, chosenCameraZ);
|
|
|
|
|
|
|
|
|
|
| 569 |
// Réinitialise le regard
|
| 570 |
-
|
|
|
|
|
|
|
| 571 |
|
| 572 |
// Met à jour les angles dans le script
|
| 573 |
var angles = playerEntity.getLocalEulerAngles();
|
|
|
|
| 1 |
// viewer_pr_env.js
|
| 2 |
// ==============================
|
| 3 |
+
// Version 2.1 : Utilisation du MOTEUR PHYSIQUE de PlayCanvas
|
| 4 |
+
// - CORRIGÉ : Inclut le chargement du moteur physique (Ammo.js) pour fixer l'écran noir.
|
| 5 |
// - Utilise RigidBody (dynamique) pour le joueur (capsule)
|
| 6 |
// - Utilise RigidBody (statique) pour l'environnement (mesh)
|
| 7 |
// - Gère la gravité, le "vrai" mesh des portes, etc.
|
| 8 |
+
// - L'ancien fichier camera.js (ou 'registerFreeCamScripts') n'est plus utilisé.
|
| 9 |
|
| 10 |
/* -------------------------------------------
|
| 11 |
Utils communs (Inchangés)
|
|
|
|
| 63 |
}
|
| 64 |
}
|
| 65 |
|
| 66 |
+
// Helpers math (Inchangés)
|
| 67 |
function vAdd(a,b){ return new pc.Vec3(a.x+b.x,a.y+b.y,a.z+b.z); }
|
| 68 |
function vSub(a,b){ return new pc.Vec3(a.x-b.x,a.y-b.y,a.z-b.z); }
|
| 69 |
function vScale(v,s){ return new pc.Vec3(v.x*s,v.y*s,v.z*s); }
|
|
|
|
| 134 |
this.yaw -= e.dx * this.lookSpeed;
|
| 135 |
this.pitch -= e.dy * this.lookSpeed;
|
| 136 |
this.pitch = pc.math.clamp(this.pitch, this.pitchAngleMin, this.pitchAngleMax);
|
| 137 |
+
t };
|
| 138 |
|
| 139 |
FirstPersonCamera.prototype.update = function (dt) {
|
| 140 |
// --- 1. Rotation (Look) ---
|
|
|
|
| 148 |
// --- 2. Mouvement (Clavier) ---
|
| 149 |
var fwd = 0;
|
| 150 |
var strf = 0;
|
| 151 |
+
const kb = this.app.keyboard; // Raccourci
|
| 152 |
|
| 153 |
+
if (kb.isPressed(pc.KEY_Z) || kb.isPressed(pc.KEY_W) || kb.isPressed(pc.KEY_UP)) {
|
| 154 |
fwd += 1;
|
| 155 |
}
|
| 156 |
+
if (kb.isPressed(pc.KEY_S) || kb.isPressed(pc.KEY_DOWN)) {
|
| 157 |
fwd -= 1;
|
| 158 |
}
|
| 159 |
+
if (kb.isPressed(pc.KEY_Q) || kb.isPressed(pc.KEY_A) || kb.isPressed(pc.KEY_LEFT)) {
|
| 160 |
strf -= 1;
|
| 161 |
}
|
| 162 |
+
if (kb.isPressed(pc.KEY_D) || kb.isPressed(pc.KEY_RIGHT)) {
|
| 163 |
strf += 1;
|
| 164 |
}
|
| 165 |
|
| 166 |
+
// Réinitialise la force à chaque frame
|
| 167 |
+
this.force.set(0, 0, 0);
|
| 168 |
+
|
| 169 |
if (fwd !== 0 || strf !== 0) {
|
| 170 |
// On utilise les vecteurs de l'entité (qui a le yaw)
|
| 171 |
var forward = this.entity.forward;
|
| 172 |
var right = this.entity.right;
|
| 173 |
|
| 174 |
// Calcule la force de déplacement
|
|
|
|
| 175 |
this.force.add(forward.mulScalar(fwd));
|
| 176 |
this.force.add(right.mulScalar(strf));
|
| 177 |
|
|
|
|
| 187 |
this.velocity.copy(this.entity.rigidbody.linearVelocity);
|
| 188 |
|
| 189 |
// Définit la vélocité XZ (mouvement)
|
| 190 |
+
// On applique la vitesse au vecteur de force normalisé
|
| 191 |
this.velocity.x = this.force.x * this.moveSpeed;
|
| 192 |
this.velocity.z = this.force.z * this.moveSpeed;
|
| 193 |
|
| 194 |
// Applique la nouvelle vélocité (conserve Y pour la gravité)
|
| 195 |
this.entity.rigidbody.linearVelocity = this.velocity;
|
| 196 |
}
|
|
|
|
|
|
|
|
|
|
| 197 |
};
|
| 198 |
}
|
| 199 |
|
| 200 |
/* -------------------------------------------
|
| 201 |
+
State (Modifié)
|
| 202 |
-------------------------------------------- */
|
| 203 |
|
| 204 |
let pc;
|
|
|
|
| 211 |
let resizeObserver = null;
|
| 212 |
let resizeTimeout = null;
|
| 213 |
|
| 214 |
+
// paramètres courants de l'instance
|
| 215 |
let chosenCameraX, chosenCameraY, chosenCameraZ;
|
| 216 |
let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minY;
|
| 217 |
let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
|
| 218 |
let presentoirScaleX, presentoirScaleY, presentoirScaleZ;
|
| 219 |
let sogUrl, glbUrl, presentoirUrl;
|
| 220 |
let color_bg_hex, color_bg, espace_expo_bool;
|
| 221 |
+
|
| 222 |
+
// perf dynamique
|
| 223 |
let maxDevicePixelRatio = 1.75;
|
| 224 |
let interactDpr = 1.0;
|
| 225 |
let idleRestoreDelay = 350;
|
|
|
|
| 300 |
|
| 301 |
const canvas = document.createElement("canvas");
|
| 302 |
canvas.id = canvasId;
|
|
|
|
| 303 |
canvas.className = "ply-canvas";
|
| 304 |
canvas.style.width = "100%";
|
| 305 |
canvas.style.height = "100%";
|
| 306 |
canvas.setAttribute("tabindex", "0");
|
| 307 |
viewerContainer.insertBefore(canvas, progressDialog);
|
| 308 |
+
|
| 309 |
+
// ... (tous les listeners de canvas sont conservés) ...
|
| 310 |
canvas.style.touchAction = "none";
|
| 311 |
canvas.style.webkitTouchCallout = "none";
|
| 312 |
canvas.addEventListener("gesturestart", (e) => e.preventDefault());
|
|
|
|
| 363 |
device.maxPixelRatio = Math.min(window.devicePixelRatio || 1, maxDevicePixelRatio);
|
| 364 |
|
| 365 |
const opts = new pc.AppOptions();
|
| 366 |
+
|
| 367 |
+
// ++++++++++ CORRECTIF ÉCRAN NOIR (DÉBUT) ++++++++++
|
| 368 |
+
// Indique à l'application où trouver les fichiers du moteur physique (Ammo.js)
|
| 369 |
+
const ammoUrl = "https://playcanvas.vercel.app/static/lib/ammo/ammo.js";
|
| 370 |
+
const ammoWasmUrl = "https://playcanvas.vercel.app/static/lib/ammo/ammo.wasm.js";
|
| 371 |
+
const ammoWasmBinaryUrl = "https://playcanvas.vercel.app/static/lib/ammo/ammo.wasm.wasm";
|
| 372 |
+
|
| 373 |
+
opts.physics = {
|
| 374 |
+
url: ammoUrl,
|
| 375 |
+
wasmUrl: ammoWasmUrl,
|
| 376 |
+
binaryUrl: ammoWasmBinaryUrl
|
| 377 |
+
};
|
| 378 |
+
// ++++++++++ CORRECTIF ÉCRAN NOIR (FIN) ++++++++++
|
| 379 |
+
|
| 380 |
opts.graphicsDevice = device;
|
| 381 |
opts.mouse = new pc.Mouse(canvas);
|
| 382 |
opts.touch = new pc.TouchDevice(canvas);
|
| 383 |
opts.keyboard = new pc.Keyboard(canvas);
|
| 384 |
+
// Note: Cette liste *doit* inclure RigidBody et Collision.
|
| 385 |
opts.componentSystems = [
|
| 386 |
pc.RenderComponentSystem,
|
| 387 |
pc.CameraComponentSystem,
|
|
|
|
| 398 |
app.setCanvasResolution(pc.RESOLUTION_AUTO);
|
| 399 |
|
| 400 |
// *** NOUVEAU : Définir la gravité pour le monde physique ***
|
| 401 |
+
app.systems.rigidbody.gravity.set(0, -9.81, 0); // Gravité standard
|
| 402 |
|
| 403 |
// --- Debounce resize (Inchangé) ---
|
| 404 |
resizeObserver = new ResizeObserver((entries) => {
|
|
|
|
| 430 |
});
|
| 431 |
|
| 432 |
// --- Chargement des assets (Inchangé) ---
|
| 433 |
+
section
|
| 434 |
const sogAsset = new pc.Asset("gsplat", "gsplat", { url: sogUrl });
|
| 435 |
const glbAsset = new pc.Asset("glb", "container", { url: glbUrl });
|
| 436 |
app.assets.add(sogAsset);
|
|
|
|
| 471 |
if (node.render) {
|
| 472 |
meshCount++;
|
| 473 |
// 1. Le rend statique (il ne bouge pas)
|
| 474 |
+
content
|
| 475 |
node.addComponent('rigidbody', {
|
| 476 |
type: pc.BODYTYPE_STATIC,
|
| 477 |
restitution: 0.0
|
|
|
|
| 498 |
playerEntity.addComponent('rigidbody', {
|
| 499 |
type: pc.BODYTYPE_DYNAMIC,
|
| 500 |
mass: 70, // Poids d'un humain
|
| 501 |
+
friction: 0.3, // Un peu de friction pour ne pas glisser
|
| 502 |
+
restitution: 0.0, // Pas de rebond
|
| 503 |
angularFactor: new pc.Vec3(0, 0, 0) // Empêche la capsule de basculer
|
| 504 |
});
|
| 505 |
|
| 506 |
// Ajoute une forme de collision CAPSULE
|
| 507 |
playerEntity.addComponent('collision', {
|
| 508 |
type: 'capsule',
|
| 509 |
+
radius: 0.35, // Rayon de 35cm (diamètre 70cm)
|
| 510 |
+
height: 1.7 // Hauteur totale 1m70
|
| 511 |
});
|
| 512 |
|
| 513 |
// 2. L'entité "Camera" (les yeux)
|
|
|
|
| 518 |
farClip: 250
|
| 519 |
});
|
| 520 |
// Positionne la caméra à hauteur des "yeux" dans la capsule
|
| 521 |
+
// (Hauteur / 2) - Rayon = (1.7 / 2) - 0.35 = 0.85 - 0.35 = 0.5
|
| 522 |
+
cameraEntity.setLocalPosition(0, 0.5, 0); // Hauteur des yeux
|
| 523 |
|
| 524 |
// 3. Attache la caméra au joueur
|
| 525 |
playerEntity.addChild(cameraEntity);
|
|
|
|
| 529 |
playerEntity.script.create("orbitCamera", {
|
| 530 |
attributes: {
|
| 531 |
cameraEntity: cameraEntity,
|
| 532 |
+
moveSpeed: 4.0, // Vitesse de 4 m/s (marche rapide)
|
| 533 |
lookSpeed: 0.25,
|
| 534 |
pitchAngleMax: maxAngle, // Utilise vos configs
|
| 535 |
pitchAngleMin: minAngle
|
|
|
|
| 554 |
if (app.graphicsDevice.maxPixelRatio !== clamped) {
|
| 555 |
app.graphicsDevice.maxPixelRatio = clamped;
|
| 556 |
app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight);
|
|
|
|
| 557 |
}
|
| 558 |
};
|
| 559 |
const bumpInteraction = () => {
|
|
|
|
| 586 |
|
| 587 |
// Téléporte le JOUEUR (pas la caméra)
|
| 588 |
playerEntity.rigidbody.teleport(chosenCameraX, chosenCameraY, chosenCameraZ);
|
| 589 |
+
playerEntity.rigidbody.linearVelocity = pc.Vec3.ZERO;
|
| 590 |
+
playerEntity.rigidbody.angularVelocity = pc.Vec3.ZERO;
|
| 591 |
+
|
| 592 |
// Réinitialise le regard
|
| 593 |
+
// Calcule le yaw nécessaire pour regarder vers le centre du modèle (modelPos)
|
| 594 |
+
const targetPos = new pc.Vec3(modelPos.x, playerEntity.getPosition().y, modelPos.z);
|
| 595 |
+
playerEntity.lookAt(targetPos);
|
| 596 |
|
| 597 |
// Met à jour les angles dans le script
|
| 598 |
var angles = playerEntity.getLocalEulerAngles();
|