Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
webgl25
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Villard PierreFrederic
webgl25
Commits
2a4044f8
Commit
2a4044f8
authored
3 weeks ago
by
RIFI Zaynab
Browse files
Options
Downloads
Patches
Plain Diff
Update file script.js
parent
26bc4151
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
RIFI/script.js
+105
-167
105 additions, 167 deletions
RIFI/script.js
with
105 additions
and
167 deletions
RIFI/script.js
+
105
−
167
View file @
2a4044f8
...
@@ -14,9 +14,7 @@ var candle, candleHolder, flame;
...
@@ -14,9 +14,7 @@ var candle, candleHolder, flame;
var
backgroundMesh
;
var
backgroundMesh
;
var
environmentMap
;
var
environmentMap
;
var
compass
;
var
compass
;
// var waxGroup;
var
cubeCamera
,
cubeRenderTarget
;
// var cubeCamera, cubeRenderTarget;
var
params
=
{
var
params
=
{
flickerSpeed
:
2.0
,
flickerSpeed
:
2.0
,
...
@@ -25,7 +23,7 @@ var params = {
...
@@ -25,7 +23,7 @@ var params = {
candleLightIntensity
:
2.2
,
candleLightIntensity
:
2.2
,
candleLightDistance
:
400
,
candleLightDistance
:
400
,
ambientLightIntensity
:
0.22
,
ambientLightIntensity
:
0.22
,
fogEnabled
:
tru
e
,
fogEnabled
:
fals
e
,
fogColor
:
0x000000
,
fogColor
:
0x000000
,
fogNear
:
100
,
fogNear
:
100
,
fogFar
:
1000
,
fogFar
:
1000
,
...
@@ -36,10 +34,43 @@ var params = {
...
@@ -36,10 +34,43 @@ var params = {
showFlower
:
true
showFlower
:
true
};
};
import
{
Coordinates
}
from
'
./lib/Coordinates.js
'
;
function
fillScene
()
{
function
init
()
{
renderer
=
new
THREE
.
WebGLRenderer
({
antialias
:
true
});
renderer
.
setSize
(
846
,
494
);
renderer
.
setClearColor
(
0x000000
,
1.0
);
renderer
.
physicallyCorrectLights
=
true
;
renderer
.
toneMapping
=
THREE
.
ACESFilmicToneMapping
;
renderer
.
toneMappingExposure
=
1.2
;
renderer
.
shadowMap
.
enabled
=
true
;
renderer
.
shadowMap
.
type
=
THREE
.
PCFSoftShadowMap
;
var
container
=
document
.
getElementById
(
'
webGL
'
);
container
.
appendChild
(
renderer
.
domElement
);
camera
=
new
THREE
.
PerspectiveCamera
(
35
,
846
/
494
,
1
,
8000
);
camera
.
position
.
set
(
0
,
200
,
600
);
scene
=
new
THREE
.
Scene
();
scene
=
new
THREE
.
Scene
();
cameraControls
=
new
OrbitControls
(
camera
,
renderer
.
domElement
);
cameraControls
.
target
.
set
(
0
,
50
,
0
);
cubeRenderTarget
=
new
THREE
.
WebGLCubeRenderTarget
(
256
,
{
format
:
THREE
.
RGBFormat
,
generateMipmaps
:
true
,
minFilter
:
THREE
.
LinearMipmapLinearFilter
});
cubeCamera
=
new
THREE
.
CubeCamera
(
1
,
1000
,
cubeRenderTarget
);
scene
.
add
(
cubeCamera
);
}
function
fillScene
()
{
createGradientBackground
();
createGradientBackground
();
var
mainLight
=
new
THREE
.
DirectionalLight
(
0xFFAA55
,
0.5
);
var
mainLight
=
new
THREE
.
DirectionalLight
(
0xFFAA55
,
0.5
);
...
@@ -56,34 +87,33 @@ function fillScene() {
...
@@ -56,34 +87,33 @@ function fillScene() {
mainLight
.
shadow
.
bias
=
-
0.0005
;
mainLight
.
shadow
.
bias
=
-
0.0005
;
scene
.
add
(
mainLight
);
scene
.
add
(
mainLight
);
const
cubeTextureLoader
=
new
THREE
.
CubeTextureLoader
();
var
ambientLight
=
new
THREE
.
AmbientLight
(
0x222222
,
params
.
ambientLightIntensity
);
var
ambientLight
=
new
THREE
.
AmbientLight
(
0x222222
,
params
.
ambientLightIntensity
);
scene
.
add
(
ambientLight
);
scene
.
add
(
ambientLight
);
const
environmentMap
=
c
ubeTextureLoader
.
load
([
const
cubeTextureLoader
=
new
THREE
.
C
ubeTextureLoader
();
'
textures/envmap/px.png
'
,
environmentMap
=
cubeTextureLoader
.
load
([
'
textures/envmap/
n
x.png
'
,
'
textures/envmap/
p
x.png
'
,
'
textures/envmap/
py
.png
'
,
'
textures/envmap/
nx
.png
'
,
'
textures/envmap/
n
y.png
'
,
'
textures/envmap/
p
y.png
'
,
'
textures/envmap/
pz
.png
'
,
'
textures/envmap/
ny
.png
'
,
'
textures/envmap/
n
z.png
'
'
textures/envmap/
p
z.png
'
,
'
textures/envmap/nz.png
'
]);
]);
scene
.
environment
=
environmentMap
;
scene
.
environment
=
environmentMap
;
createTable
();
createTable
();
loadSkull
();
loadSkull
();
createEnhancedCandle
();
createEnhancedCandle
();
loadFlower
();
loadFlower
();
loadCompass
();
loadInk
();
loadInk
();
loadWalnut
();
loadWalnut
();
loadKey
();
addMeltedWaxOnTable
();
setupFog
();
loadKey
()
;
loadCompass
()
}
}
function
createGradientBackground
()
{
function
createGradientBackground
()
{
const
bgGeometry
=
new
THREE
.
PlaneGeometry
(
2000
,
1000
);
const
bgGeometry
=
new
THREE
.
PlaneGeometry
(
2000
,
1000
);
...
@@ -111,9 +141,7 @@ function createGradientBackground() {
...
@@ -111,9 +141,7 @@ function createGradientBackground() {
function
setupFog
()
{
function
setupFog
()
{
if
(
params
.
fogEnabled
)
{
if
(
params
.
fogEnabled
)
{
scene
.
fog
=
new
THREE
.
Fog
(
params
.
fogColor
,
params
.
fogNear
,
params
.
fogFar
);
scene
.
fog
=
new
THREE
.
Fog
(
params
.
fogColor
,
params
.
fogNear
,
params
.
fogFar
);
}
else
{
}
else
{
scene
.
fog
=
null
;
scene
.
fog
=
null
;
}
}
...
@@ -265,39 +293,53 @@ function loadCompass() {
...
@@ -265,39 +293,53 @@ function loadCompass() {
const
textureLoader
=
new
THREE
.
TextureLoader
();
const
textureLoader
=
new
THREE
.
TextureLoader
();
textureLoader
.
load
(
'
textures/compass.jpg
'
,
function
(
texture
)
{
textureLoader
.
load
(
'
textures/compass.jpg
'
,
function
(
texture
)
{
texture
.
encoding
=
THREE
.
sRGBEncoding
;
texture
.
flipY
=
false
;
texture
.
generateMipmaps
=
true
;
texture
.
needsUpdate
=
true
;
loader
.
load
(
loader
.
load
(
'
boussole1.obj
'
,
'
boussole1.obj
'
,
function
(
compass
)
{
function
(
compass
)
{
compass
.
scale
.
set
(
30
,
30
,
30
);
compass
.
scale
.
set
(
30
,
30
,
30
);
compass
.
position
.
set
(
7
0
,
-
10
,
85
);
compass
.
position
.
set
(
9
0
,
-
10
,
85
);
compass
.
rotation
.
set
(
0
,
-
Math
.
PI
/
1.5
,
0
);
compass
.
rotation
.
set
(
0
,
-
Math
.
PI
/
1.5
,
0
);
const
compassMaterial
=
new
THREE
.
MeshStandardMaterial
({
map
:
texture
,
// Appliquer la texture
const
compassMaterial
=
new
THREE
.
MeshPhysicalMaterial
({
roughness
:
0.3
,
// Ajuster la rugosité pour un effet réaliste
map
:
texture
,
metalness
:
0.8
,
// Ajuster la métallité pour un effet réaliste
envMap
:
cubeRenderTarget
.
texture
,
// Appliquer la carte d'environnement dynamique
emissiveIntensity
:
0.3
,
envMapIntensity
:
1.0
,
// Intensité de l'environnement pour un effet réaliste
metalness
:
1.0
,
transparent
:
false
,
// Désactiver la transparence
roughness
:
0.2
,
opacity
:
1.0
// Opacité complète
reflectivity
:
1.0
,
clearcoat
:
0.8
,
clearcoatRoughness
:
0.2
,
envMapIntensity
:
1.5
,
side
:
THREE
.
DoubleSide
});
});
compass
.
traverse
(
function
(
child
)
{
compass
.
traverse
(
function
(
child
)
{
if
(
child
.
isMesh
)
{
if
(
child
.
isMesh
)
{
child
.
material
=
compassMaterial
;
child
.
material
=
compassMaterial
;
child
.
castShadow
=
true
;
// Permettre à l'objet de projeter des ombres
child
.
castShadow
=
true
;
child
.
receiveShadow
=
true
;
// Permettre à l'objet de recevoir des ombres
child
.
receiveShadow
=
true
;
}
}
});
});
scene
.
add
(
compass
);
scene
.
add
(
compass
);
console
.
log
(
"
Objet chargé :
"
,
compass
);
console
.
log
(
"
Objet chargé :
"
,
compass
);
// Ajouter une lumière spécifique pour éclairer la boussole
const
compassLight
=
new
THREE
.
PointLight
(
0xffffcc
,
2.0
,
150
);
const
compassLight
=
new
THREE
.
PointLight
(
0xffffff
,
1
,
100
);
compassLight
.
position
.
set
(
70
,
20
,
85
);
compassLight
.
position
.
set
(
70
,
20
,
85
);
// Positionner la lumière au-dessus de la boussole
compassLight
.
castShadow
=
true
;
scene
.
add
(
compassLight
);
scene
.
add
(
compassLight
);
const
compassGlow
=
new
THREE
.
PointLight
(
0xffffaa
,
1.0
,
80
);
compassGlow
.
position
.
set
(
70
,
-
5
,
85
);
scene
.
add
(
compassGlow
);
},
},
function
(
xhr
)
{
function
(
xhr
)
{
console
.
log
((
xhr
.
loaded
/
xhr
.
total
*
100
)
+
'
% chargé
'
);
console
.
log
((
xhr
.
loaded
/
xhr
.
total
*
100
)
+
'
% chargé
'
);
...
@@ -319,7 +361,7 @@ function loadWalnut() {
...
@@ -319,7 +361,7 @@ function loadWalnut() {
function
(
walnut
)
{
function
(
walnut
)
{
walnut
.
scale
.
set
(
1
,
1
,
1
);
walnut
.
scale
.
set
(
1
,
1
,
1
);
walnut
.
position
.
set
(
1
2
0
,
6
,
120
);
walnut
.
position
.
set
(
1
6
0
,
6
,
120
);
walnut
.
rotation
.
set
(
0
,
0
,
0
);
walnut
.
rotation
.
set
(
0
,
0
,
0
);
const
walnutMaterial
=
new
THREE
.
MeshPhongMaterial
({
const
walnutMaterial
=
new
THREE
.
MeshPhongMaterial
({
...
@@ -350,9 +392,6 @@ function loadWalnut() {
...
@@ -350,9 +392,6 @@ function loadWalnut() {
);
);
}
}
function
loadInk
()
{
function
loadInk
()
{
const
loader
=
new
OBJLoader
();
const
loader
=
new
OBJLoader
();
...
@@ -394,7 +433,6 @@ function loadInk() {
...
@@ -394,7 +433,6 @@ function loadInk() {
}
}
function
loadKey
()
{
function
loadKey
()
{
const
loader
=
new
OBJLoader
();
const
loader
=
new
OBJLoader
();
...
@@ -435,6 +473,9 @@ function loadKey() {
...
@@ -435,6 +473,9 @@ function loadKey() {
}
}
function
loadFlower
()
{
function
loadFlower
()
{
var
loader
=
new
OBJLoader
();
var
loader
=
new
OBJLoader
();
loader
.
load
(
loader
.
load
(
...
@@ -756,7 +797,7 @@ function createEnhancedCandle() {
...
@@ -756,7 +797,7 @@ function createEnhancedCandle() {
candleGroup
.
position
.
set
(
-
150
,
10
,
20
);
candleGroup
.
position
.
set
(
-
150
,
10
,
20
);
candleGroup
.
scale
.
set
(
2
,
2
,
2
);
candleGroup
.
scale
.
set
(
2
,
2
,
2
);
// Permettre au groupe entier de projeter et recevoir des ombres
candleGroup
.
traverse
(
function
(
object
)
{
candleGroup
.
traverse
(
function
(
object
)
{
if
(
object
.
isMesh
)
{
if
(
object
.
isMesh
)
{
object
.
castShadow
=
true
;
object
.
castShadow
=
true
;
...
@@ -793,15 +834,13 @@ function animateFlame() {
...
@@ -793,15 +834,13 @@ function animateFlame() {
const
innerLight
=
flame
.
userData
.
innerLight
;
const
innerLight
=
flame
.
userData
.
innerLight
;
const
ambientLight
=
flame
.
userData
.
ambientLight
;
const
ambientLight
=
flame
.
userData
.
ambientLight
;
const
particles
=
flame
.
userData
.
particles
;
const
particles
=
flame
.
userData
.
particles
;
// Mouvement de balancement simplifié
const
swayX
=
Math
.
sin
(
time
*
swaySpeed
)
*
swayAmount
;
const
swayX
=
Math
.
sin
(
time
*
swaySpeed
)
*
swayAmount
;
const
swayZ
=
Math
.
cos
(
time
*
swaySpeed
*
0.8
)
*
swayAmount
;
const
swayZ
=
Math
.
cos
(
time
*
swaySpeed
*
0.8
)
*
swayAmount
;
// Variation de hauteur simplifiée
const
heightVariation
=
0.98
+
flickerIntensity
*
Math
.
sin
(
time
*
flickerSpeed
);
const
heightVariation
=
0.98
+
flickerIntensity
*
Math
.
sin
(
time
*
flickerSpeed
);
// Appliquer les transformations à la flamme principale
flame
.
scale
.
set
(
1
,
heightVariation
,
1
);
flame
.
scale
.
set
(
1
,
heightVariation
,
1
);
flame
.
rotation
.
x
=
swayX
*
0.1
;
flame
.
rotation
.
x
=
swayX
*
0.1
;
flame
.
rotation
.
z
=
swayZ
*
0.1
;
flame
.
rotation
.
z
=
swayZ
*
0.1
;
...
@@ -958,108 +997,30 @@ function updateBackgroundWithCandleLight(time, flickerFactor, swayX, swayZ) {
...
@@ -958,108 +997,30 @@ function updateBackgroundWithCandleLight(time, flickerFactor, swayX, swayZ) {
}
}
// function addMeltedWaxOnTable() {
// waxGroup = new THREE.Group();
// const waxMaterial = new THREE.MeshPhysicalMaterial({
// color: 0xf3e5ab, // Couleur de la cire
// roughness: 0.8,
// metalness: 0.05,
// transparent: true,
// opacity: 0.95,
// thickness: 1.5,
// transmission: 0.5
// });
// const waxCount = 8; // Nombre de gouttes de cire
// for (let i = 0; i < waxCount; i++) {
// let waxDroplets = new THREE.Group();
// // Position de base près de la bougie
// let baseX = -150 + (Math.random() - 0.5) * 20; // Près de la position X de la bougie
// let baseZ = 1 + (Math.random() - 0.5) * 20; // Près de la position Z de la bougie
// let dropCount = Math.floor(Math.random() * 5) + 3; // Nombre de gouttes par groupe
// for (let j = 0; j < dropCount; j++) {
// let waxRadius = Math.random() * 2 + 1; // Rayon aléatoire pour les gouttes
// let waxGeometry = new THREE.SphereGeometry(waxRadius, 16, 16);
// let wax = new THREE.Mesh(waxGeometry, waxMaterial);
// // Position initiale près de la bougie
// wax.position.set(
// baseX + Math.random() * 5 - 2.5,
// 50 - j * 5, // Position Y pour simuler la chute
// baseZ + Math.random() * 5 - 2.5
// );
// // Étirer les gouttes pour un effet de dégoulinement
// wax.scale.y = Math.random() * 2 + 1;
// // Activer les ombres
// wax.castShadow = true;
// wax.receiveShadow = true;
// waxDroplets.add(wax);
// }
// waxGroup.add(waxDroplets);
// }
// scene.add(waxGroup);
// animateWax(waxGroup); // Animer les gouttes de cire
// }
// function animateWax(waxGroup) {
// waxGroup.children.forEach((waxDroplets) => {
// // Position finale sur la table
// const targetY = -40;
// // Durée aléatoire pour chaque goutte
// const duration = Math.random() * 2 + 1;
// // Animation GSAP pour faire tomber les gouttes
// gsap.to(waxDroplets.position, {
// y: targetY,
// duration: duration,
// ease: "power2.out",
// onComplete: () => {
// // Effet de rebond lorsque la goutte touche la table
// gsap.to(waxDroplets.position, {
// y: targetY + 5, // Petit rebond
// duration: 0.2,
// yoyo: true,
// repeat: 1,
// ease: "power2.out"
// });
// }
// });
// });
// }
function
animate
()
{
function
animate
()
{
requestAnimationFrame
(
animate
);
requestAnimationFrame
(
animate
);
var
delta
=
clock
.
getDelta
();
var
delta
=
clock
.
getDelta
();
cameraControls
.
update
(
delta
);
cameraControls
.
update
(
delta
);
if
(
compass
)
{
cubeCamera
.
position
.
copy
(
compass
.
position
);
cubeCamera
.
update
(
renderer
,
scene
);
}
animateFlame
();
animateFlame
();
// animateWax(waxGroup);
renderer
.
render
(
scene
,
camera
);
renderer
.
render
(
scene
,
camera
);
}
}
function
initGUI
()
{
function
initGUI
()
{
var
gui
=
new
dat
.
GUI
();
var
gui
=
new
dat
.
GUI
();
// Dossier pour les paramètres de la flamme
var
flameFolder
=
gui
.
addFolder
(
'
Flamme
'
);
var
flameFolder
=
gui
.
addFolder
(
'
Flamme
'
);
flameFolder
.
add
(
params
,
'
flickerSpeed
'
,
0.5
,
5.0
).
name
(
'
Vitesse vacillement
'
);
flameFolder
.
add
(
params
,
'
flickerSpeed
'
,
0.5
,
5.0
).
name
(
'
Vitesse vacillement
'
);
flameFolder
.
add
(
params
,
'
flickerIntensity
'
,
0.01
,
0.3
).
name
(
'
Intensité vacillement
'
);
flameFolder
.
add
(
params
,
'
flickerIntensity
'
,
0.01
,
0.3
).
name
(
'
Intensité vacillement
'
);
flameFolder
.
open
();
flameFolder
.
open
();
// Dossier pour les paramètres d'éclairage
var
lightFolder
=
gui
.
addFolder
(
'
Éclairage
'
);
var
lightFolder
=
gui
.
addFolder
(
'
Éclairage
'
);
lightFolder
.
add
(
params
,
'
candleLightIntensity
'
,
0.5
,
5.0
).
name
(
'
Intensité bougie
'
).
onChange
(
function
(
value
)
{
lightFolder
.
add
(
params
,
'
candleLightIntensity
'
,
0.5
,
5.0
).
name
(
'
Intensité bougie
'
).
onChange
(
function
(
value
)
{
scene
.
traverse
(
function
(
object
)
{
scene
.
traverse
(
function
(
object
)
{
...
@@ -1084,7 +1045,7 @@ function initGUI() {
...
@@ -1084,7 +1045,7 @@ function initGUI() {
});
});
lightFolder
.
open
();
lightFolder
.
open
();
// Dossier pour les éléments de la scène
var
sceneFolder
=
gui
.
addFolder
(
'
Éléments de scène
'
);
var
sceneFolder
=
gui
.
addFolder
(
'
Éléments de scène
'
);
sceneFolder
.
add
(
params
,
'
showSkull
'
).
name
(
'
Afficher crâne
'
).
onChange
(
function
(
value
)
{
sceneFolder
.
add
(
params
,
'
showSkull
'
).
name
(
'
Afficher crâne
'
).
onChange
(
function
(
value
)
{
if
(
skull
)
skull
.
visible
=
value
;
if
(
skull
)
skull
.
visible
=
value
;
...
@@ -1101,12 +1062,11 @@ function initGUI() {
...
@@ -1101,12 +1062,11 @@ function initGUI() {
var
fogFolder
=
gui
.
addFolder
(
'
Brouillard
'
);
var
fogFolder
=
gui
.
addFolder
(
'
Brouillard
'
);
fogFolder
.
add
(
params
,
'
fogEnabled
'
).
name
(
'
Activer brouillard
'
).
onChange
(
setupFog
);
fogFolder
.
add
(
params
,
'
fogEnabled
'
).
name
(
'
Activer brouillard
'
).
onChange
(
setupFog
);
// Si vous utilisez THREE.Fog (linéaire)
fogFolder
.
add
(
params
,
'
fogNear
'
,
1
,
500
).
name
(
'
Distance proche
'
).
onChange
(
setupFog
);
fogFolder
.
add
(
params
,
'
fogNear
'
,
1
,
500
).
name
(
'
Distance proche
'
).
onChange
(
setupFog
);
fogFolder
.
add
(
params
,
'
fogFar
'
,
500
,
2000
).
name
(
'
Distance lointaine
'
).
onChange
(
setupFog
);
fogFolder
.
add
(
params
,
'
fogFar
'
,
500
,
2000
).
name
(
'
Distance lointaine
'
).
onChange
(
setupFog
);
// Si vous utilisez THREE.FogExp2 (exponentiel)
// fogFolder.add(params, 'fogDensity', 0.001, 0.05).name('Densité').onChange(setupFog);
fogFolder
.
addColor
(
params
,
'
fogColor
'
).
name
(
'
Couleur
'
).
onChange
(
function
(
value
)
{
fogFolder
.
addColor
(
params
,
'
fogColor
'
).
name
(
'
Couleur
'
).
onChange
(
function
(
value
)
{
if
(
scene
.
fog
)
{
if
(
scene
.
fog
)
{
...
@@ -1118,28 +1078,6 @@ function initGUI() {
...
@@ -1118,28 +1078,6 @@ function initGUI() {
fogFolder
.
open
();
fogFolder
.
open
();
}
}
function
init
()
{
renderer
=
new
THREE
.
WebGLRenderer
({
antialias
:
true
});
renderer
.
setSize
(
846
,
494
);
renderer
.
setClearColor
(
0x000000
,
1.0
);
renderer
.
physicallyCorrectLights
=
true
;
renderer
.
toneMapping
=
THREE
.
ACESFilmicToneMapping
;
renderer
.
toneMappingExposure
=
1.2
;
renderer
.
shadowMap
.
enabled
=
true
;
renderer
.
shadowMap
.
type
=
THREE
.
PCFSoftShadowMap
;
var
container
=
document
.
getElementById
(
'
webGL
'
);
container
.
appendChild
(
renderer
.
domElement
);
camera
=
new
THREE
.
PerspectiveCamera
(
35
,
846
/
494
,
1
,
8000
);
camera
.
position
.
set
(
0
,
200
,
600
);
cameraControls
=
new
OrbitControls
(
camera
,
renderer
.
domElement
);
cameraControls
.
target
.
set
(
0
,
50
,
0
);
}
try
{
try
{
init
();
init
();
fillScene
();
fillScene
();
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment