Spaces:
Running
Running
Update viewer.js
Browse files
viewer.js
CHANGED
|
@@ -1,12 +1,30 @@
|
|
| 1 |
// viewer.js
|
| 2 |
// ==============================
|
| 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
let pc;
|
| 5 |
export let app = null;
|
| 6 |
let cameraEntity = null;
|
| 7 |
let modelEntity = null;
|
| 8 |
let tubeEntity = null;
|
| 9 |
-
let
|
| 10 |
let viewerInitialized = false;
|
| 11 |
let resizeObserver = null;
|
| 12 |
|
|
@@ -20,7 +38,7 @@ let tubeOpaque = null;
|
|
| 20 |
let chosenCameraX, chosenCameraY, chosenCameraZ;
|
| 21 |
let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minPivotY, minY;
|
| 22 |
let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
|
| 23 |
-
let glbUrl, glbUrl2, glbUrl3
|
| 24 |
|
| 25 |
// RECURSIVE ENTITY TRAVERSAL (needed for material assignment)
|
| 26 |
function traverse(entity, callback) {
|
|
@@ -39,9 +57,6 @@ export async function initializeViewer(config, instanceId) {
|
|
| 39 |
glbUrl = config.glb_url;
|
| 40 |
glbUrl2 = config.glb_url_2;
|
| 41 |
glbUrl3 = config.glb_url_3;
|
| 42 |
-
aoUrl = config.ao_url;
|
| 43 |
-
thicknessUrl = config.thickness_url;
|
| 44 |
-
opacityUrl = config.opacity_url;
|
| 45 |
minZoom = 0.2;
|
| 46 |
maxZoom = 2;
|
| 47 |
minAngle = -Infinity;
|
|
@@ -158,42 +173,38 @@ export async function initializeViewer(config, instanceId) {
|
|
| 158 |
// --- Assets ---
|
| 159 |
const assets = {
|
| 160 |
orbit: new pc.Asset('script', 'script', { url: "https://mikafil-viewer-gs.static.hf.space/orbit-camera.js" }),
|
| 161 |
-
model: new pc.Asset('
|
| 162 |
-
tube: new pc.Asset('
|
| 163 |
-
|
| 164 |
-
ao_map: new pc.Asset('color', 'texture', { url: aoUrl }),
|
| 165 |
-
op_map: new pc.Asset('color', 'texture', { url: opacityUrl }),
|
| 166 |
-
bg_tex: new pc.Asset('color', 'texture', {url: "https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/EARCARE/banniere_earcare.png"}),
|
| 167 |
-
thickness_map: new pc.Asset('color', 'texture', { url: thicknessUrl }),
|
| 168 |
-
helipad: new pc.Asset(
|
| 169 |
-
'helipad-env-atlas',
|
| 170 |
-
'texture',
|
| 171 |
-
{ url: "https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/EARCARE/hdr/ciel_nuageux_1k.png" },
|
| 172 |
-
{ type: pc.TEXTURETYPE_RGBP, mipmaps: false }
|
| 173 |
-
)
|
| 174 |
};
|
| 175 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
for (const key in assets) app.assets.add(assets[key]);
|
| 177 |
|
| 178 |
// Load HDR *before* loading any models
|
| 179 |
assets.helipad.ready(() => {
|
| 180 |
-
app.scene.envAtlas =
|
| 181 |
app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, -90, 0);
|
| 182 |
app.scene.skyboxIntensity = 4;
|
| 183 |
app.scene.skyboxMip = 0;
|
| 184 |
|
| 185 |
|
| 186 |
// Now load all GLBs and other assets
|
| 187 |
-
const loader = new pc.AssetListLoader(
|
| 188 |
-
assets.orbit,
|
| 189 |
-
assets.model,
|
| 190 |
-
assets.tube,
|
| 191 |
-
assets.bouchon,
|
| 192 |
-
assets.ao_map,
|
| 193 |
-
assets.op_map,
|
| 194 |
-
assets.bg_tex,
|
| 195 |
-
assets.thickness_map
|
| 196 |
-
], app.assets);
|
| 197 |
|
| 198 |
loader.load(() => {
|
| 199 |
app.start();
|
|
@@ -207,20 +218,13 @@ export async function initializeViewer(config, instanceId) {
|
|
| 207 |
// 1. Models
|
| 208 |
modelEntity = assets.model.resource.instantiateRenderEntity();
|
| 209 |
tubeEntity = assets.tube.resource.instantiateRenderEntity();
|
| 210 |
-
|
| 211 |
|
| 212 |
app.root.addChild(modelEntity);
|
| 213 |
app.root.addChild(tubeEntity);
|
| 214 |
-
app.root.addChild(
|
| 215 |
|
| 216 |
-
// 2. Materials for main model & tube
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
//the 2 materials for the main model :
|
| 220 |
-
const ao = assets.ao_map.resource;
|
| 221 |
-
const op = assets.op_map.resource;
|
| 222 |
-
const thickness = assets.thickness_map.resource;
|
| 223 |
-
|
| 224 |
//mat transparent
|
| 225 |
matTransparent = new pc.StandardMaterial();
|
| 226 |
matTransparent.blendType = pc.BLEND_NORMAL;
|
|
@@ -234,12 +238,12 @@ export async function initializeViewer(config, instanceId) {
|
|
| 234 |
matTransparent.refraction= 0.8;
|
| 235 |
matTransparent.refractionIndex = 1;
|
| 236 |
matTransparent.thickness = 0.02;
|
| 237 |
-
matTransparent.thicknessMap =
|
| 238 |
-
matTransparent.opacityMap =
|
| 239 |
matTransparent.opacityMapChannel = "r";
|
| 240 |
matTransparent.opacity = 0.97;
|
| 241 |
matTransparent.emissive = new pc.Color(1, 1, 1);
|
| 242 |
-
matTransparent.emissiveMap =
|
| 243 |
matTransparent.emissiveIntensity = 0.1;
|
| 244 |
matTransparent.update();
|
| 245 |
|
|
@@ -254,11 +258,11 @@ export async function initializeViewer(config, instanceId) {
|
|
| 254 |
matOpaque.specularityFactor = 1;
|
| 255 |
matOpaque.gloss = 1;
|
| 256 |
matOpaque.metalness = 0;
|
| 257 |
-
matOpaque.opacityMap =
|
| 258 |
matOpaque.opacityMapChannel = "r";
|
| 259 |
matOpaque.opacity = 1;
|
| 260 |
matOpaque.emissive = new pc.Color(0.372, 0.03, 0.003);
|
| 261 |
-
matOpaque.emissiveMap =
|
| 262 |
matOpaque.emissiveIntensity = 2;
|
| 263 |
matOpaque.update();
|
| 264 |
|
|
@@ -322,9 +326,9 @@ export async function initializeViewer(config, instanceId) {
|
|
| 322 |
tubeEntity.setLocalScale(modelScale, modelScale, modelScale);
|
| 323 |
tubeEntity.setLocalEulerAngles(modelRotationX, modelRotationY, modelRotationZ);
|
| 324 |
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
|
| 329 |
// 4. Camera & orbit
|
| 330 |
|
|
|
|
| 1 |
// viewer.js
|
| 2 |
// ==============================
|
| 3 |
|
| 4 |
+
async function loadImageAsTexture(url, app) {
|
| 5 |
+
return new Promise((resolve, reject) => {
|
| 6 |
+
const img = new window.Image();
|
| 7 |
+
img.crossOrigin = "anonymous";
|
| 8 |
+
img.onload = function() {
|
| 9 |
+
const tex = new pc.Texture(app.graphicsDevice, {
|
| 10 |
+
width: img.width,
|
| 11 |
+
height: img.height,
|
| 12 |
+
format: pc.PIXELFORMAT_R8_G8_B8_A8,
|
| 13 |
+
});
|
| 14 |
+
tex.setSource(img);
|
| 15 |
+
resolve(tex);
|
| 16 |
+
};
|
| 17 |
+
img.onerror = reject;
|
| 18 |
+
img.src = url;
|
| 19 |
+
});
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
let pc;
|
| 23 |
export let app = null;
|
| 24 |
let cameraEntity = null;
|
| 25 |
let modelEntity = null;
|
| 26 |
let tubeEntity = null;
|
| 27 |
+
let filtreEntity = null;
|
| 28 |
let viewerInitialized = false;
|
| 29 |
let resizeObserver = null;
|
| 30 |
|
|
|
|
| 38 |
let chosenCameraX, chosenCameraY, chosenCameraZ;
|
| 39 |
let minZoom, maxZoom, minAngle, maxAngle, minAzimuth, maxAzimuth, minPivotY, minY;
|
| 40 |
let modelX, modelY, modelZ, modelScale, modelRotationX, modelRotationY, modelRotationZ;
|
| 41 |
+
let glbUrl, glbUrl2, glbUrl3;
|
| 42 |
|
| 43 |
// RECURSIVE ENTITY TRAVERSAL (needed for material assignment)
|
| 44 |
function traverse(entity, callback) {
|
|
|
|
| 57 |
glbUrl = config.glb_url;
|
| 58 |
glbUrl2 = config.glb_url_2;
|
| 59 |
glbUrl3 = config.glb_url_3;
|
|
|
|
|
|
|
|
|
|
| 60 |
minZoom = 0.2;
|
| 61 |
maxZoom = 2;
|
| 62 |
minAngle = -Infinity;
|
|
|
|
| 173 |
// --- Assets ---
|
| 174 |
const assets = {
|
| 175 |
orbit: new pc.Asset('script', 'script', { url: "https://mikafil-viewer-gs.static.hf.space/orbit-camera.js" }),
|
| 176 |
+
model: new pc.Asset('model_glb', 'container', { url: glbUrl }),
|
| 177 |
+
tube: new pc.Asset('tube_glb', 'container', { url: glbUrl2 }),
|
| 178 |
+
filtre: new pc.Asset('filtre_glb', 'container', { url: glbUrl3 }),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
};
|
| 180 |
|
| 181 |
+
const hdrUrl = 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/EARCARE/hdr/ciel_nuageux_1k.png';
|
| 182 |
+
const hdrTex = await loadImageAsTexture(hdrUrl, app);
|
| 183 |
+
|
| 184 |
+
const emitUrl = 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/emit_map_2k.png';
|
| 185 |
+
const emitTex = await loadImageAsTexture(emitUrl, app);
|
| 186 |
+
|
| 187 |
+
const opUrl = 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/op_map_2k.png';
|
| 188 |
+
const opTex = await loadImageAsTexture(opUrl, app);
|
| 189 |
+
|
| 190 |
+
const thicknessUrl = 'https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/retop_2/thickness_map_2k.png';
|
| 191 |
+
const thicknessTex = await loadImageAsTexture(thicknessTex, app);
|
| 192 |
+
|
| 193 |
+
const bgurl ='https://huggingface.co/datasets/MikaFil/3D_models/resolve/main/EARCARE/banniere_earcare.png';
|
| 194 |
+
const bgTex = await loadImageAsTexture(bgurl, app);
|
| 195 |
+
|
| 196 |
for (const key in assets) app.assets.add(assets[key]);
|
| 197 |
|
| 198 |
// Load HDR *before* loading any models
|
| 199 |
assets.helipad.ready(() => {
|
| 200 |
+
app.scene.envAtlas = hdrTex;
|
| 201 |
app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, -90, 0);
|
| 202 |
app.scene.skyboxIntensity = 4;
|
| 203 |
app.scene.skyboxMip = 0;
|
| 204 |
|
| 205 |
|
| 206 |
// Now load all GLBs and other assets
|
| 207 |
+
const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
|
| 209 |
loader.load(() => {
|
| 210 |
app.start();
|
|
|
|
| 218 |
// 1. Models
|
| 219 |
modelEntity = assets.model.resource.instantiateRenderEntity();
|
| 220 |
tubeEntity = assets.tube.resource.instantiateRenderEntity();
|
| 221 |
+
filtreEntity = assets.filtre.resource.instantiateRenderEntity();
|
| 222 |
|
| 223 |
app.root.addChild(modelEntity);
|
| 224 |
app.root.addChild(tubeEntity);
|
| 225 |
+
app.root.addChild(filtreEntity);
|
| 226 |
|
| 227 |
+
// 2. Materials for main model & tube
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
//mat transparent
|
| 229 |
matTransparent = new pc.StandardMaterial();
|
| 230 |
matTransparent.blendType = pc.BLEND_NORMAL;
|
|
|
|
| 238 |
matTransparent.refraction= 0.8;
|
| 239 |
matTransparent.refractionIndex = 1;
|
| 240 |
matTransparent.thickness = 0.02;
|
| 241 |
+
matTransparent.thicknessMap = thicknessTex;
|
| 242 |
+
matTransparent.opacityMap = opTex;
|
| 243 |
matTransparent.opacityMapChannel = "r";
|
| 244 |
matTransparent.opacity = 0.97;
|
| 245 |
matTransparent.emissive = new pc.Color(1, 1, 1);
|
| 246 |
+
matTransparent.emissiveMap = emitTex;
|
| 247 |
matTransparent.emissiveIntensity = 0.1;
|
| 248 |
matTransparent.update();
|
| 249 |
|
|
|
|
| 258 |
matOpaque.specularityFactor = 1;
|
| 259 |
matOpaque.gloss = 1;
|
| 260 |
matOpaque.metalness = 0;
|
| 261 |
+
matOpaque.opacityMap = opTex;
|
| 262 |
matOpaque.opacityMapChannel = "r";
|
| 263 |
matOpaque.opacity = 1;
|
| 264 |
matOpaque.emissive = new pc.Color(0.372, 0.03, 0.003);
|
| 265 |
+
matOpaque.emissiveMap = emitTex;
|
| 266 |
matOpaque.emissiveIntensity = 2;
|
| 267 |
matOpaque.update();
|
| 268 |
|
|
|
|
| 326 |
tubeEntity.setLocalScale(modelScale, modelScale, modelScale);
|
| 327 |
tubeEntity.setLocalEulerAngles(modelRotationX, modelRotationY, modelRotationZ);
|
| 328 |
|
| 329 |
+
filtreEntity.setPosition(modelX, modelY, modelZ);
|
| 330 |
+
filtreEntity.setLocalScale(modelScale, modelScale, modelScale);
|
| 331 |
+
filtreEntity.setLocalEulerAngles(modelRotationX, modelRotationY, modelRotationZ);
|
| 332 |
|
| 333 |
// 4. Camera & orbit
|
| 334 |
|