Initial commit
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1 @@
 | 
			
		||||
assets
 | 
			
		||||
							
								
								
									
										79
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,79 @@
 | 
			
		||||
# TP Interaction
 | 
			
		||||
 | 
			
		||||
Ce TP a pour but de vous faire coder des interactions avec un modèle 3D. Pour
 | 
			
		||||
cela, vous implémenterez en Javascript des interactions avec la souris et avec
 | 
			
		||||
les touches du clavier qui permettent de changer de point de vue, c'est à dire,
 | 
			
		||||
de mettre à jour la position et l'orientation de la caméra (Partie 1), et
 | 
			
		||||
ensuite d'enregistrer de tels points de vues pour permettre une navigation plus
 | 
			
		||||
haut niveau (Partie 2).
 | 
			
		||||
 | 
			
		||||
Ce TP sera fait pendant les séances consacrées (un TP jeudi 9, un TP jeudi 16).
 | 
			
		||||
 | 
			
		||||
### Cloner le repository
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
git clone https://gitea.tforgione.fr/tforgione/tp-interaction
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Lancer le server
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
python -m SimpleHTTPServer
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Vous pouvez ensuite aller sur la page [localhost:8000](http://localhost:8000)
 | 
			
		||||
pour lancer l'interface. Pour voir la console vous pouvez cliquer sur `F12`,
 | 
			
		||||
ce qui vous permettra de debugger plus facilement.
 | 
			
		||||
 | 
			
		||||
### Sujet
 | 
			
		||||
 | 
			
		||||
#### Partie 1 : interaction clavier / souris
 | 
			
		||||
 | 
			
		||||
L'objectif de cette premiere partie est d'implémenter les interactions type
 | 
			
		||||
*free fly camera*. Nous vous proposons de mettre à jour les interactions avec
 | 
			
		||||
la souris pour tourner la caméra et avec le clavier pour la deplacer.
 | 
			
		||||
 | 
			
		||||
L'utilisateur peut appuyer sur les flèches du clavier pour déplacer la caméra :
 | 
			
		||||
  - flèche en haut (ou touche z) pour avancer
 | 
			
		||||
  - flèche du bas (ou touche s) pour reculer
 | 
			
		||||
  - flèche de gauche (ou touche q) pour se translater vers la gauche
 | 
			
		||||
  - flèche de droite (ou touche d) pour se translater vers la droite
 | 
			
		||||
 | 
			
		||||
Ces directions seront définies à partir de l'orientation de la caméra, donnée
 | 
			
		||||
par 2 angles `theta` et `delta`.
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
Vous pouvez trouver des exemples de coordonnées sphériques sur
 | 
			
		||||
[wikipedia](https://fr.wikipedia.org/wiki/Coordonn%C3%A9es_sph%C3%A9riques).
 | 
			
		||||
 | 
			
		||||
**Attention** : dans THREE.js, l'axe des y est celui qui va vers le haut.
 | 
			
		||||
 | 
			
		||||
Pour cette partie, vous aurez besoin de compléter les *TODO Part 1* du fichier
 | 
			
		||||
`js/main.js`.
 | 
			
		||||
 | 
			
		||||
#### Partie 2 : interaction via point de vue
 | 
			
		||||
 | 
			
		||||
L'objectif de cette deuxième partie est d'utiliser les points de vue
 | 
			
		||||
enregistrés pour faciliter l'interaction. Pour commencer, vous pouvez
 | 
			
		||||
décommenter les lignes 236 à 239 du fichier `js/main.js` pour faire apparaitre
 | 
			
		||||
un point de vue. Vous devez ensuite compléter les *TODO Part 2* pour permettre
 | 
			
		||||
à un utilisateur de cliquer sur un point de vue pour s'y déplacer.
 | 
			
		||||
 | 
			
		||||
### Les vecteurs dans THREE.js
 | 
			
		||||
 | 
			
		||||
Ce TP utilise le moteur de rendu THREE.js. Puisque javascript ne permet pas la
 | 
			
		||||
surcharge d'opérateurs, il est impossible d'écrire `x + y` quand `x` et `y`
 | 
			
		||||
sont des vecteurs de THREE.js. Ansi, THREE.js définit des méthodes pour
 | 
			
		||||
effectuer ces opérations :
 | 
			
		||||
 | 
			
		||||
| Avec opérateurs | En THREE.js |
 | 
			
		||||
|:----:|:---:|
 | 
			
		||||
| `a += b` | `a.add(b)` |
 | 
			
		||||
| `a -= b` | `a.sub(b)` |
 | 
			
		||||
| `a *= l` | `a.multiplyScalar(l)` |
 | 
			
		||||
| `a = b` | `a.copy(b)` |
 | 
			
		||||
| `a + b` | `a.clone().add(b)` |
 | 
			
		||||
| `a = b + c` | `a.copy(b.clone().add(c))` |
 | 
			
		||||
| ... | ... |
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								assets/eye.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 17 KiB  | 
							
								
								
									
										66
									
								
								assets/scheme.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,66 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="360" height="360" version="1.1">
 | 
			
		||||
 | 
			
		||||
  <g id="Coord_LatLong" transform="translate(159.5, 195.5) scale(1,-1)">
 | 
			
		||||
    <path d="M -143,0 A 143,62 0 1 0 143,0" style="stroke:#808080;stroke-width:1;stroke-dasharray:6,6;fill:none;"/>
 | 
			
		||||
    <path d="M 0,143 A 143,60 -90 1 1 0,-143" transform="rotate(13)" style="stroke:#808080;stroke-dasharray:6,6;stroke-width:1;fill:none;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M -125,0 H 186" transform="rotate(-135)" style="stroke:#000000;stroke-width:1;fill:none;"/>
 | 
			
		||||
    <path d="M 0,-2.5 L 4,-3 L 2,4 L 0,12 L -2,4 L -4,-3 L 0,-2.5 Z" transform="rotate(-225) translate(0,186)" style="stroke:none;fill:#000000;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M -155,0 H 188" transform="rotate(-10.6)" style="stroke:#000000;stroke-width:1;fill:none;"/>
 | 
			
		||||
    <path d="M 0,-2.5 L 4,-3 L 2,4 L 0,12 L -2,4 L -4,-3 L 0,-2.5 Z" transform="rotate(-10.6) translate(188,0) rotate(270)" style="stroke:none;fill:#000000;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M 0,-163 V 177" style="stroke:#000000;stroke-width:1;fill:none;"/>
 | 
			
		||||
    <path d="M 0,-2.5 L 4,-3 L 2,4 L 0,12 L -2,4 L -4,-3 L 0,-2.5 Z" transform="translate(0,177)" style="stroke:none;fill:#000000;"/>
 | 
			
		||||
 | 
			
		||||
    <circle cx="0" cy="0" r="143" style="stroke:#000000;stroke-width:2;fill:none;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M 0,-143 A 143,60 -90 1 1 0,143" transform="rotate(13)" style="stroke:#000000;stroke-width:1;fill:none;"/>
 | 
			
		||||
    <path d="M -143,0 A 143,62 0 1 1 143,0" style="stroke:#000000;stroke-width:1;fill:none;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M 0,0 L -56.88,-56.88 A 143,62 0 0 1 66.73,-54.84 L 0,0 Z" style="stroke:none;fill:#204a87;opacity:0.2;"/>
 | 
			
		||||
    <path d="M 0,0 L 52.68,-68.44 A 143,60 -90 0 1 53.71,63.72 L 0,0 Z" transform="rotate(13)" style="stroke:none;fill:#f57900;opacity:0.3;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M 0,0 L 38,74.17" style="stroke:#4e9a06;stroke-width:2;fill:none;"/>
 | 
			
		||||
    <path d="M 0,0 L -10,3 L -10,-3 L 0,0 Z" transform="translate(38, 74.17) rotate(63)" style="stroke:#4e9a06;stroke-width:2;fill:#4e9a06;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M 52.68,-68.44 A 143,60 -90 0 1 53.71,63.72" transform="rotate(13)" style="stroke:#f57900;stroke-width:2;fill:none;"/>
 | 
			
		||||
    <path d="M 0,0 L -10,3 L -10,-3 L 0,0 Z" transform="translate(38, 74.17) rotate(112)" style="stroke:#f57900;stroke-width:2;fill:#f57900;"/>
 | 
			
		||||
 | 
			
		||||
    <path d="M -56.88,-56.88 A 143,62 0 0 1 62,-55.87" style="stroke:#204a87;stroke-width:2;fill:none;"/>
 | 
			
		||||
    <path d="M 0,0 L -10,3 L -10,-3 L 0,0 Z" transform="translate(66.73,-54.84) rotate(11)" style="stroke:#204a87;stroke-width:2;fill:#204a87;"/>
 | 
			
		||||
 | 
			
		||||
    <circle cx="38" cy="74.17" r="4" style="stroke:none;fill:#5c3566;"/>
 | 
			
		||||
    <circle cx="0" cy="0" r="2" style="stroke:none;fill:#000000;"/>
 | 
			
		||||
 | 
			
		||||
    <text transform="scale(1,-1)" x="6" y="-44" xml:space="preserve" style="font-size:28px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;stroke:none;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Italic"><tspan x="6" y="-44">ρ</tspan>
 | 
			
		||||
    </text>
 | 
			
		||||
 | 
			
		||||
    <text transform="scale(1,-1)" x="64" y="-10" xml:space="preserve" style="font-size:28px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;stroke:none;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Italic"><tspan x="64" y="-10">δ</tspan>
 | 
			
		||||
    </text>
 | 
			
		||||
 | 
			
		||||
    <text transform="scale(1,-1)" x="-22" y="90" xml:space="preserve" style="font-size:28px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;stroke:none;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Italic"><tspan x="-22" y="90">θ</tspan>
 | 
			
		||||
    </text>
 | 
			
		||||
 | 
			
		||||
    <text transform="scale(1,-1)" x="45" y="-78" xml:space="preserve" style="font-size:28px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;stroke:none;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Italic"><tspan x="45" y="-78">P</tspan>
 | 
			
		||||
    </text>
 | 
			
		||||
 | 
			
		||||
    <g transform="translate(-127,-154) scale(1,-1)">
 | 
			
		||||
      <text x="0" y="0" xml:space="preserve" style="font-size:32px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;stroke:none;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Italic"><tspan x="0" y="0">z</tspan>
 | 
			
		||||
      </text>
 | 
			
		||||
    </g>
 | 
			
		||||
 | 
			
		||||
    <g transform="translate(167,-65) scale(1,-1)">
 | 
			
		||||
      <text x="0" y="0" xml:space="preserve" style="font-size:32px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;stroke:none;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Italic"><tspan x="0" y="0">x</tspan>
 | 
			
		||||
      </text>
 | 
			
		||||
    </g>
 | 
			
		||||
 | 
			
		||||
    <g transform="translate(10,170) scale(1,-1)">
 | 
			
		||||
      <text x="0" y="0" xml:space="preserve" style="font-size:32px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;stroke:none;font-family:DejaVu Serif;-inkscape-font-specification:DejaVu Serif Italic"><tspan x="0" y="0">y</tspan>
 | 
			
		||||
      </text>
 | 
			
		||||
    </g>
 | 
			
		||||
 | 
			
		||||
  </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 5.4 KiB  | 
							
								
								
									
										354
									
								
								assets/windfall/Windfall.mtl
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,354 @@
 | 
			
		||||
# Blender MTL File: 'None'
 | 
			
		||||
# Material Count: 32
 | 
			
		||||
 | 
			
		||||
newmtl m0lambea_v_x_v_x
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd a_tuta.png
 | 
			
		||||
 | 
			
		||||
newmtl m10lambert12_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_siba04.png
 | 
			
		||||
 | 
			
		||||
newmtl m11lambert14_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd rotennuno85.png
 | 
			
		||||
 | 
			
		||||
newmtl m12lambert15_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd wood04.png
 | 
			
		||||
 | 
			
		||||
newmtl m13lambert2_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd a_kusa.png
 | 
			
		||||
 | 
			
		||||
newmtl m14lambert6_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_yuka10.png
 | 
			
		||||
 | 
			
		||||
newmtl m15lambert74_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd a_iwa.png
 | 
			
		||||
 | 
			
		||||
newmtl m16lambert75_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd rotennuno4.png
 | 
			
		||||
 | 
			
		||||
newmtl m17lambert84_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_kabe33.png
 | 
			
		||||
 | 
			
		||||
newmtl m18lambert85_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_ren15.png
 | 
			
		||||
 | 
			
		||||
newmtl m19lambert8_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_miti05.png
 | 
			
		||||
 | 
			
		||||
newmtl m1lambert100_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_ki12.png
 | 
			
		||||
 | 
			
		||||
newmtl m20lambert92_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_yane08.png
 | 
			
		||||
 | 
			
		||||
newmtl m21lambert94_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_ki13.png
 | 
			
		||||
 | 
			
		||||
newmtl m22lambert95_v_x_v_x
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd a_kusa_yane.png
 | 
			
		||||
 | 
			
		||||
newmtl m23lambert98_v_x_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd gakkou03.png
 | 
			
		||||
 | 
			
		||||
newmtl m24lambert98_v_x_v_x
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd gakkou03.png
 | 
			
		||||
 | 
			
		||||
newmtl m25lambert99_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_mado08.png
 | 
			
		||||
 | 
			
		||||
newmtl m26lambertaa_v_v_x
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd a_kysakiwa.png
 | 
			
		||||
 | 
			
		||||
newmtl m27lambv_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_mado02.png
 | 
			
		||||
 | 
			
		||||
newmtl m28test_lambert105_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_leaf01.png
 | 
			
		||||
 | 
			
		||||
newmtl m29test_lambert48_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd k_taru04.png
 | 
			
		||||
 | 
			
		||||
newmtl m2lambert101_v_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_komono11.png
 | 
			
		||||
 | 
			
		||||
newmtl m30test_lambert49_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd k_taru05.png
 | 
			
		||||
 | 
			
		||||
newmtl m31lambert12_v_v_2_
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_siba04.png
 | 
			
		||||
 | 
			
		||||
newmtl m3lambert102_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_ren16.png
 | 
			
		||||
 | 
			
		||||
newmtl m4lambert103_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_kabe38.png
 | 
			
		||||
 | 
			
		||||
newmtl m5lambert104_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_leaf05.png
 | 
			
		||||
 | 
			
		||||
newmtl m6lambert107_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd m_leaf09.png
 | 
			
		||||
 | 
			
		||||
newmtl m7lambert10_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd wood01.png
 | 
			
		||||
 | 
			
		||||
newmtl m8lambert115_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd rotennuno70.png
 | 
			
		||||
 | 
			
		||||
newmtl m9lambert11_v_v
 | 
			
		||||
Ns 0.000000
 | 
			
		||||
Ka 1.000000 1.000000 1.000000
 | 
			
		||||
Kd 0.640000 0.640000 0.640000
 | 
			
		||||
Ks 0.500000 0.500000 0.500000
 | 
			
		||||
Ke 0.000000 0.000000 0.000000
 | 
			
		||||
Ni 1.000000
 | 
			
		||||
d 1.000000
 | 
			
		||||
illum 2
 | 
			
		||||
map_Kd wood06.png
 | 
			
		||||
							
								
								
									
										84882
									
								
								assets/windfall/Windfall.obj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/a_iwa.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/a_kusa.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 18 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/a_kusa_yane.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/a_kysakiwa.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/a_tuta.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/gakkou03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 26 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/k_taru04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 590 B  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/k_taru05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_kabe33.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 99 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_kabe38.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 6.6 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_ki12.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 24 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_ki13.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 6.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_komono11.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 52 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_leaf01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 14 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_leaf05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 16 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_leaf09.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 10 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_mado02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 639 B  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_mado08.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_miti05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_ren15.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 29 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_ren16.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 31 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_siba04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 115 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_yane08.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 66 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/m_yuka10.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 24 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/rotennuno4.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 4.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/rotennuno70.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/rotennuno85.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/water.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 91 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/wood01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 11 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/wood04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 30 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								assets/windfall/wood06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.4 KiB  | 
							
								
								
									
										20
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,20 @@
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <title>TP</title>
 | 
			
		||||
        <meta charset="utf-8">
 | 
			
		||||
        <style>
 | 
			
		||||
            body {
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
                margin: 0px;
 | 
			
		||||
            }
 | 
			
		||||
        </style>
 | 
			
		||||
    </head>
 | 
			
		||||
    <body>
 | 
			
		||||
        <script src="js/three.min.js"></script>
 | 
			
		||||
        <script src="js/OBJLoader.js"></script>
 | 
			
		||||
        <script src="js/MTLLoader.js"></script>
 | 
			
		||||
        <script src="js/Bookmark.js"></script>
 | 
			
		||||
        <script src="js/main.js"></script>
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										83
									
								
								js/Bookmark.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,83 @@
 | 
			
		||||
class Bookmark extends THREE.Object3D {
 | 
			
		||||
    constructor(position, target, scale = 500.0) {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
        position = new THREE.Vector3().copy(position);
 | 
			
		||||
        target = new THREE.Vector3().copy(target);
 | 
			
		||||
 | 
			
		||||
        this.position.copy(position);
 | 
			
		||||
        this.target = new THREE.Vector3().copy(target);
 | 
			
		||||
 | 
			
		||||
        this.t = 0;
 | 
			
		||||
 | 
			
		||||
        let material = new THREE.LineBasicMaterial({
 | 
			
		||||
            color: 0xffffff,
 | 
			
		||||
            linewidth: 3,
 | 
			
		||||
        });
 | 
			
		||||
        let geometry = new THREE.Geometry();
 | 
			
		||||
 | 
			
		||||
        let direction = this.target.clone().sub(position).normalize().multiplyScalar(this.length());
 | 
			
		||||
 | 
			
		||||
        geometry.vertices.push(new THREE.Vector3(0.0, -1000000.0, 0.0));
 | 
			
		||||
        geometry.vertices.push(new THREE.Vector3(0.0, 0.0, 0.0));
 | 
			
		||||
 | 
			
		||||
        this.line = new THREE.Line(geometry, material);
 | 
			
		||||
        this.add(this.line);
 | 
			
		||||
 | 
			
		||||
        this.numberOfPoints = 20;
 | 
			
		||||
        this.createCircle();
 | 
			
		||||
        this._shining = false;
 | 
			
		||||
 | 
			
		||||
        this.t = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createCircle() {
 | 
			
		||||
        let map = new THREE.TextureLoader().load("assets/eye.png");
 | 
			
		||||
        let material = new THREE.SpriteMaterial({
 | 
			
		||||
            map: map,
 | 
			
		||||
            color: 0xfffffff,
 | 
			
		||||
            transparent: true,
 | 
			
		||||
        });
 | 
			
		||||
        let geometry = new THREE.Geometry();
 | 
			
		||||
        this.circle = new THREE.Sprite(material);
 | 
			
		||||
        this.add(this.circle);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    length() {
 | 
			
		||||
        return 25 * (Math.cos(this.t) + 5);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get shining() {
 | 
			
		||||
        return this._shining;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    set shining(other) {
 | 
			
		||||
        this._shining = other;
 | 
			
		||||
        if (!other) {
 | 
			
		||||
            this.circle.material.color = new THREE.Color(1, 1, 1);
 | 
			
		||||
            this.line.material.color = new THREE.Color(1, 1, 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update(camera) {
 | 
			
		||||
        // super.update(camera);
 | 
			
		||||
 | 
			
		||||
        /// assert(camera instanceof THREE.Camera);
 | 
			
		||||
        let distance = this.localToWorld(this.position.clone()).distanceTo(camera.position);
 | 
			
		||||
        this.t += 0.05;
 | 
			
		||||
        let l = this.length();
 | 
			
		||||
        this.circle.scale.x = l * Math.log(1 + distance);
 | 
			
		||||
        this.circle.scale.y = l * Math.log(1 + distance);
 | 
			
		||||
        this.circle.scale.z = l * Math.log(1 + distance);
 | 
			
		||||
        this.line.geometry.vertices[1].y = -this.circle.scale.x / 2;
 | 
			
		||||
        this.line.geometry.verticesNeedUpdate = true;
 | 
			
		||||
 | 
			
		||||
        if (this.shining) {
 | 
			
		||||
            let value = (1 + Math.cos(Math.PI / 2 + this.t * 2)) / 2;
 | 
			
		||||
            this.circle.material.color = new THREE.Color(1 - value, value, 0);
 | 
			
		||||
            this.line.material.color = new THREE.Color(1 - value, value, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										532
									
								
								js/MTLLoader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,532 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Loads a Wavefront .mtl file specifying materials
 | 
			
		||||
 *
 | 
			
		||||
 * @author angelxuanchang
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
THREE.MTLLoader = function ( manager ) {
 | 
			
		||||
 | 
			
		||||
	THREE.Loader.call( this, manager );
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
THREE.MTLLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
 | 
			
		||||
 | 
			
		||||
	constructor: THREE.MTLLoader,
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Loads and parses a MTL asset from a URL.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param {String} url - URL to the MTL file.
 | 
			
		||||
	 * @param {Function} [onLoad] - Callback invoked with the loaded object.
 | 
			
		||||
	 * @param {Function} [onProgress] - Callback for download progress.
 | 
			
		||||
	 * @param {Function} [onError] - Callback for download errors.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @see setPath setResourcePath
 | 
			
		||||
	 *
 | 
			
		||||
	 * @note In order for relative texture references to resolve correctly
 | 
			
		||||
	 * you must call setResourcePath() explicitly prior to load.
 | 
			
		||||
	 */
 | 
			
		||||
	load: function ( url, onLoad, onProgress, onError ) {
 | 
			
		||||
 | 
			
		||||
		var scope = this;
 | 
			
		||||
 | 
			
		||||
		var path = ( this.path === '' ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path;
 | 
			
		||||
 | 
			
		||||
		var loader = new THREE.FileLoader( this.manager );
 | 
			
		||||
		loader.setPath( this.path );
 | 
			
		||||
		loader.load( url, function ( text ) {
 | 
			
		||||
 | 
			
		||||
			onLoad( scope.parse( text, path ) );
 | 
			
		||||
 | 
			
		||||
		}, onProgress, onError );
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	setMaterialOptions: function ( value ) {
 | 
			
		||||
 | 
			
		||||
		this.materialOptions = value;
 | 
			
		||||
		return this;
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Parses a MTL file.
 | 
			
		||||
	 *
 | 
			
		||||
	 * @param {String} text - Content of MTL file
 | 
			
		||||
	 * @return {THREE.MTLLoader.MaterialCreator}
 | 
			
		||||
	 *
 | 
			
		||||
	 * @see setPath setResourcePath
 | 
			
		||||
	 *
 | 
			
		||||
	 * @note In order for relative texture references to resolve correctly
 | 
			
		||||
	 * you must call setResourcePath() explicitly prior to parse.
 | 
			
		||||
	 */
 | 
			
		||||
	parse: function ( text, path ) {
 | 
			
		||||
 | 
			
		||||
		var lines = text.split( '\n' );
 | 
			
		||||
		var info = {};
 | 
			
		||||
		var delimiter_pattern = /\s+/;
 | 
			
		||||
		var materialsInfo = {};
 | 
			
		||||
 | 
			
		||||
		for ( var i = 0; i < lines.length; i ++ ) {
 | 
			
		||||
 | 
			
		||||
			var line = lines[ i ];
 | 
			
		||||
			line = line.trim();
 | 
			
		||||
 | 
			
		||||
			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
 | 
			
		||||
 | 
			
		||||
				// Blank line or comment ignore
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var pos = line.indexOf( ' ' );
 | 
			
		||||
 | 
			
		||||
			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
 | 
			
		||||
			key = key.toLowerCase();
 | 
			
		||||
 | 
			
		||||
			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
 | 
			
		||||
			value = value.trim();
 | 
			
		||||
 | 
			
		||||
			if ( key === 'newmtl' ) {
 | 
			
		||||
 | 
			
		||||
				// New material
 | 
			
		||||
 | 
			
		||||
				info = { name: value };
 | 
			
		||||
				materialsInfo[ value ] = info;
 | 
			
		||||
 | 
			
		||||
			} else {
 | 
			
		||||
 | 
			
		||||
				if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) {
 | 
			
		||||
 | 
			
		||||
					var ss = value.split( delimiter_pattern, 3 );
 | 
			
		||||
					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
 | 
			
		||||
 | 
			
		||||
				} else {
 | 
			
		||||
 | 
			
		||||
					info[ key ] = value;
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions );
 | 
			
		||||
		materialCreator.setCrossOrigin( this.crossOrigin );
 | 
			
		||||
		materialCreator.setManager( this.manager );
 | 
			
		||||
		materialCreator.setMaterials( materialsInfo );
 | 
			
		||||
		return materialCreator;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
} );
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a new THREE.MTLLoader.MaterialCreator
 | 
			
		||||
 * @param baseUrl - Url relative to which textures are loaded
 | 
			
		||||
 * @param options - Set of options on how to construct the materials
 | 
			
		||||
 *                  side: Which side to apply the material
 | 
			
		||||
 *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
 | 
			
		||||
 *                  wrap: What type of wrapping to apply for textures
 | 
			
		||||
 *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
 | 
			
		||||
 *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
 | 
			
		||||
 *                                Default: false, assumed to be already normalized
 | 
			
		||||
 *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
 | 
			
		||||
 *                                  Default: false
 | 
			
		||||
 * @constructor
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) {
 | 
			
		||||
 | 
			
		||||
	this.baseUrl = baseUrl || '';
 | 
			
		||||
	this.options = options;
 | 
			
		||||
	this.materialsInfo = {};
 | 
			
		||||
	this.materials = {};
 | 
			
		||||
	this.materialsArray = [];
 | 
			
		||||
	this.nameLookup = {};
 | 
			
		||||
 | 
			
		||||
	this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
 | 
			
		||||
	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
THREE.MTLLoader.MaterialCreator.prototype = {
 | 
			
		||||
 | 
			
		||||
	constructor: THREE.MTLLoader.MaterialCreator,
 | 
			
		||||
 | 
			
		||||
	crossOrigin: 'anonymous',
 | 
			
		||||
 | 
			
		||||
	setCrossOrigin: function ( value ) {
 | 
			
		||||
 | 
			
		||||
		this.crossOrigin = value;
 | 
			
		||||
		return this;
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	setManager: function ( value ) {
 | 
			
		||||
 | 
			
		||||
		this.manager = value;
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	setMaterials: function ( materialsInfo ) {
 | 
			
		||||
 | 
			
		||||
		this.materialsInfo = this.convert( materialsInfo );
 | 
			
		||||
		this.materials = {};
 | 
			
		||||
		this.materialsArray = [];
 | 
			
		||||
		this.nameLookup = {};
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	convert: function ( materialsInfo ) {
 | 
			
		||||
 | 
			
		||||
		if ( ! this.options ) return materialsInfo;
 | 
			
		||||
 | 
			
		||||
		var converted = {};
 | 
			
		||||
 | 
			
		||||
		for ( var mn in materialsInfo ) {
 | 
			
		||||
 | 
			
		||||
			// Convert materials info into normalized form based on options
 | 
			
		||||
 | 
			
		||||
			var mat = materialsInfo[ mn ];
 | 
			
		||||
 | 
			
		||||
			var covmat = {};
 | 
			
		||||
 | 
			
		||||
			converted[ mn ] = covmat;
 | 
			
		||||
 | 
			
		||||
			for ( var prop in mat ) {
 | 
			
		||||
 | 
			
		||||
				var save = true;
 | 
			
		||||
				var value = mat[ prop ];
 | 
			
		||||
				var lprop = prop.toLowerCase();
 | 
			
		||||
 | 
			
		||||
				switch ( lprop ) {
 | 
			
		||||
 | 
			
		||||
					case 'kd':
 | 
			
		||||
					case 'ka':
 | 
			
		||||
					case 'ks':
 | 
			
		||||
 | 
			
		||||
						// Diffuse color (color under white light) using RGB values
 | 
			
		||||
 | 
			
		||||
						if ( this.options && this.options.normalizeRGB ) {
 | 
			
		||||
 | 
			
		||||
							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						if ( this.options && this.options.ignoreZeroRGBs ) {
 | 
			
		||||
 | 
			
		||||
							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {
 | 
			
		||||
 | 
			
		||||
								// ignore
 | 
			
		||||
 | 
			
		||||
								save = false;
 | 
			
		||||
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
					default:
 | 
			
		||||
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if ( save ) {
 | 
			
		||||
 | 
			
		||||
					covmat[ lprop ] = value;
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return converted;
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	preload: function () {
 | 
			
		||||
 | 
			
		||||
		for ( var mn in this.materialsInfo ) {
 | 
			
		||||
 | 
			
		||||
			this.create( mn );
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	getIndex: function ( materialName ) {
 | 
			
		||||
 | 
			
		||||
		return this.nameLookup[ materialName ];
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	getAsArray: function () {
 | 
			
		||||
 | 
			
		||||
		var index = 0;
 | 
			
		||||
 | 
			
		||||
		for ( var mn in this.materialsInfo ) {
 | 
			
		||||
 | 
			
		||||
			this.materialsArray[ index ] = this.create( mn );
 | 
			
		||||
			this.nameLookup[ mn ] = index;
 | 
			
		||||
			index ++;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return this.materialsArray;
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	create: function ( materialName ) {
 | 
			
		||||
 | 
			
		||||
		if ( this.materials[ materialName ] === undefined ) {
 | 
			
		||||
 | 
			
		||||
			this.createMaterial_( materialName );
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return this.materials[ materialName ];
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	createMaterial_: function ( materialName ) {
 | 
			
		||||
 | 
			
		||||
		// Create material
 | 
			
		||||
 | 
			
		||||
		var scope = this;
 | 
			
		||||
		var mat = this.materialsInfo[ materialName ];
 | 
			
		||||
		var params = {
 | 
			
		||||
 | 
			
		||||
			name: materialName,
 | 
			
		||||
			side: this.side
 | 
			
		||||
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		function resolveURL( baseUrl, url ) {
 | 
			
		||||
 | 
			
		||||
			if ( typeof url !== 'string' || url === '' )
 | 
			
		||||
				return '';
 | 
			
		||||
 | 
			
		||||
			// Absolute URL
 | 
			
		||||
			if ( /^https?:\/\//i.test( url ) ) return url;
 | 
			
		||||
 | 
			
		||||
			return baseUrl + url;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		function setMapForType( mapType, value ) {
 | 
			
		||||
 | 
			
		||||
			if ( params[ mapType ] ) return; // Keep the first encountered texture
 | 
			
		||||
 | 
			
		||||
			var texParams = scope.getTextureParams( value, params );
 | 
			
		||||
			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
 | 
			
		||||
 | 
			
		||||
			map.repeat.copy( texParams.scale );
 | 
			
		||||
			map.offset.copy( texParams.offset );
 | 
			
		||||
 | 
			
		||||
			map.wrapS = scope.wrap;
 | 
			
		||||
			map.wrapT = scope.wrap;
 | 
			
		||||
 | 
			
		||||
			params[ mapType ] = map;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for ( var prop in mat ) {
 | 
			
		||||
 | 
			
		||||
			var value = mat[ prop ];
 | 
			
		||||
			var n;
 | 
			
		||||
 | 
			
		||||
			if ( value === '' ) continue;
 | 
			
		||||
 | 
			
		||||
			switch ( prop.toLowerCase() ) {
 | 
			
		||||
 | 
			
		||||
				// Ns is material specular exponent
 | 
			
		||||
 | 
			
		||||
				case 'kd':
 | 
			
		||||
 | 
			
		||||
					// Diffuse color (color under white light) using RGB values
 | 
			
		||||
 | 
			
		||||
					params.color = new THREE.Color().fromArray( value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'ks':
 | 
			
		||||
 | 
			
		||||
					// Specular color (color when light is reflected from shiny surface) using RGB values
 | 
			
		||||
					params.specular = new THREE.Color().fromArray( value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'ke':
 | 
			
		||||
 | 
			
		||||
					// Emissive using RGB values
 | 
			
		||||
					params.emissive = new THREE.Color().fromArray( value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'map_kd':
 | 
			
		||||
 | 
			
		||||
					// Diffuse texture map
 | 
			
		||||
 | 
			
		||||
					setMapForType( "map", value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'map_ks':
 | 
			
		||||
 | 
			
		||||
					// Specular map
 | 
			
		||||
 | 
			
		||||
					setMapForType( "specularMap", value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'map_ke':
 | 
			
		||||
 | 
			
		||||
					// Emissive map
 | 
			
		||||
 | 
			
		||||
					setMapForType( "emissiveMap", value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'norm':
 | 
			
		||||
 | 
			
		||||
					setMapForType( "normalMap", value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'map_bump':
 | 
			
		||||
				case 'bump':
 | 
			
		||||
 | 
			
		||||
					// Bump texture map
 | 
			
		||||
 | 
			
		||||
					setMapForType( "bumpMap", value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'map_d':
 | 
			
		||||
 | 
			
		||||
					// Alpha map
 | 
			
		||||
 | 
			
		||||
					setMapForType( "alphaMap", value );
 | 
			
		||||
					params.transparent = true;
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'ns':
 | 
			
		||||
 | 
			
		||||
					// The specular exponent (defines the focus of the specular highlight)
 | 
			
		||||
					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
 | 
			
		||||
 | 
			
		||||
					params.shininess = parseFloat( value );
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'd':
 | 
			
		||||
					n = parseFloat( value );
 | 
			
		||||
 | 
			
		||||
					if ( n < 1 ) {
 | 
			
		||||
 | 
			
		||||
						params.opacity = n;
 | 
			
		||||
						params.transparent = true;
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				case 'tr':
 | 
			
		||||
					n = parseFloat( value );
 | 
			
		||||
 | 
			
		||||
					if ( this.options && this.options.invertTrProperty ) n = 1 - n;
 | 
			
		||||
 | 
			
		||||
					if ( n > 0 ) {
 | 
			
		||||
 | 
			
		||||
						params.opacity = 1 - n;
 | 
			
		||||
						params.transparent = true;
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				default:
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
 | 
			
		||||
		return this.materials[ materialName ];
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	getTextureParams: function ( value, matParams ) {
 | 
			
		||||
 | 
			
		||||
		var texParams = {
 | 
			
		||||
 | 
			
		||||
			scale: new THREE.Vector2( 1, 1 ),
 | 
			
		||||
			offset: new THREE.Vector2( 0, 0 )
 | 
			
		||||
 | 
			
		||||
		 };
 | 
			
		||||
 | 
			
		||||
		var items = value.split( /\s+/ );
 | 
			
		||||
		var pos;
 | 
			
		||||
 | 
			
		||||
		pos = items.indexOf( '-bm' );
 | 
			
		||||
 | 
			
		||||
		if ( pos >= 0 ) {
 | 
			
		||||
 | 
			
		||||
			matParams.bumpScale = parseFloat( items[ pos + 1 ] );
 | 
			
		||||
			items.splice( pos, 2 );
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pos = items.indexOf( '-s' );
 | 
			
		||||
 | 
			
		||||
		if ( pos >= 0 ) {
 | 
			
		||||
 | 
			
		||||
			texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
 | 
			
		||||
			items.splice( pos, 4 ); // we expect 3 parameters here!
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pos = items.indexOf( '-o' );
 | 
			
		||||
 | 
			
		||||
		if ( pos >= 0 ) {
 | 
			
		||||
 | 
			
		||||
			texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
 | 
			
		||||
			items.splice( pos, 4 ); // we expect 3 parameters here!
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		texParams.url = items.join( ' ' ).trim();
 | 
			
		||||
		return texParams;
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
 | 
			
		||||
 | 
			
		||||
		var texture;
 | 
			
		||||
		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;
 | 
			
		||||
		var loader = manager.getHandler( url );
 | 
			
		||||
 | 
			
		||||
		if ( loader === null ) {
 | 
			
		||||
 | 
			
		||||
			loader = new THREE.TextureLoader( manager );
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
 | 
			
		||||
		texture = loader.load( url, onLoad, onProgress, onError );
 | 
			
		||||
 | 
			
		||||
		if ( mapping !== undefined ) texture.mapping = mapping;
 | 
			
		||||
 | 
			
		||||
		return texture;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										797
									
								
								js/OBJLoader.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,797 @@
 | 
			
		||||
/**
 | 
			
		||||
 * @author mrdoob / http://mrdoob.com/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
THREE.OBJLoader = ( function () {
 | 
			
		||||
 | 
			
		||||
	// o object_name | g group_name
 | 
			
		||||
	var object_pattern = /^[og]\s*(.+)?/;
 | 
			
		||||
	// mtllib file_reference
 | 
			
		||||
	var material_library_pattern = /^mtllib /;
 | 
			
		||||
	// usemtl material_name
 | 
			
		||||
	var material_use_pattern = /^usemtl /;
 | 
			
		||||
	// usemap map_name
 | 
			
		||||
	var map_use_pattern = /^usemap /;
 | 
			
		||||
 | 
			
		||||
	function ParserState() {
 | 
			
		||||
 | 
			
		||||
		var state = {
 | 
			
		||||
			objects: [],
 | 
			
		||||
			object: {},
 | 
			
		||||
 | 
			
		||||
			vertices: [],
 | 
			
		||||
			normals: [],
 | 
			
		||||
			colors: [],
 | 
			
		||||
			uvs: [],
 | 
			
		||||
 | 
			
		||||
			materialLibraries: [],
 | 
			
		||||
 | 
			
		||||
			startObject: function ( name, fromDeclaration ) {
 | 
			
		||||
 | 
			
		||||
				// If the current object (initial from reset) is not from a g/o declaration in the parsed
 | 
			
		||||
				// file. We need to use it for the first parsed g/o to keep things in sync.
 | 
			
		||||
				if ( this.object && this.object.fromDeclaration === false ) {
 | 
			
		||||
 | 
			
		||||
					this.object.name = name;
 | 
			
		||||
					this.object.fromDeclaration = ( fromDeclaration !== false );
 | 
			
		||||
					return;
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );
 | 
			
		||||
 | 
			
		||||
				if ( this.object && typeof this.object._finalize === 'function' ) {
 | 
			
		||||
 | 
			
		||||
					this.object._finalize( true );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				this.object = {
 | 
			
		||||
					name: name || '',
 | 
			
		||||
					fromDeclaration: ( fromDeclaration !== false ),
 | 
			
		||||
 | 
			
		||||
					geometry: {
 | 
			
		||||
						vertices: [],
 | 
			
		||||
						normals: [],
 | 
			
		||||
						colors: [],
 | 
			
		||||
						uvs: []
 | 
			
		||||
					},
 | 
			
		||||
					materials: [],
 | 
			
		||||
					smooth: true,
 | 
			
		||||
 | 
			
		||||
					startMaterial: function ( name, libraries ) {
 | 
			
		||||
 | 
			
		||||
						var previous = this._finalize( false );
 | 
			
		||||
 | 
			
		||||
						// New usemtl declaration overwrites an inherited material, except if faces were declared
 | 
			
		||||
						// after the material, then it must be preserved for proper MultiMaterial continuation.
 | 
			
		||||
						if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
 | 
			
		||||
 | 
			
		||||
							this.materials.splice( previous.index, 1 );
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						var material = {
 | 
			
		||||
							index: this.materials.length,
 | 
			
		||||
							name: name || '',
 | 
			
		||||
							mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
 | 
			
		||||
							smooth: ( previous !== undefined ? previous.smooth : this.smooth ),
 | 
			
		||||
							groupStart: ( previous !== undefined ? previous.groupEnd : 0 ),
 | 
			
		||||
							groupEnd: - 1,
 | 
			
		||||
							groupCount: - 1,
 | 
			
		||||
							inherited: false,
 | 
			
		||||
 | 
			
		||||
							clone: function ( index ) {
 | 
			
		||||
 | 
			
		||||
								var cloned = {
 | 
			
		||||
									index: ( typeof index === 'number' ? index : this.index ),
 | 
			
		||||
									name: this.name,
 | 
			
		||||
									mtllib: this.mtllib,
 | 
			
		||||
									smooth: this.smooth,
 | 
			
		||||
									groupStart: 0,
 | 
			
		||||
									groupEnd: - 1,
 | 
			
		||||
									groupCount: - 1,
 | 
			
		||||
									inherited: false
 | 
			
		||||
								};
 | 
			
		||||
								cloned.clone = this.clone.bind( cloned );
 | 
			
		||||
								return cloned;
 | 
			
		||||
 | 
			
		||||
							}
 | 
			
		||||
						};
 | 
			
		||||
 | 
			
		||||
						this.materials.push( material );
 | 
			
		||||
 | 
			
		||||
						return material;
 | 
			
		||||
 | 
			
		||||
					},
 | 
			
		||||
 | 
			
		||||
					currentMaterial: function () {
 | 
			
		||||
 | 
			
		||||
						if ( this.materials.length > 0 ) {
 | 
			
		||||
 | 
			
		||||
							return this.materials[ this.materials.length - 1 ];
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						return undefined;
 | 
			
		||||
 | 
			
		||||
					},
 | 
			
		||||
 | 
			
		||||
					_finalize: function ( end ) {
 | 
			
		||||
 | 
			
		||||
						var lastMultiMaterial = this.currentMaterial();
 | 
			
		||||
						if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
 | 
			
		||||
 | 
			
		||||
							lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
 | 
			
		||||
							lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
 | 
			
		||||
							lastMultiMaterial.inherited = false;
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						// Ignore objects tail materials if no face declarations followed them before a new o/g started.
 | 
			
		||||
						if ( end && this.materials.length > 1 ) {
 | 
			
		||||
 | 
			
		||||
							for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) {
 | 
			
		||||
 | 
			
		||||
								if ( this.materials[ mi ].groupCount <= 0 ) {
 | 
			
		||||
 | 
			
		||||
									this.materials.splice( mi, 1 );
 | 
			
		||||
 | 
			
		||||
								}
 | 
			
		||||
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						// Guarantee at least one empty material, this makes the creation later more straight forward.
 | 
			
		||||
						if ( end && this.materials.length === 0 ) {
 | 
			
		||||
 | 
			
		||||
							this.materials.push( {
 | 
			
		||||
								name: '',
 | 
			
		||||
								smooth: this.smooth
 | 
			
		||||
							} );
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						return lastMultiMaterial;
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				// Inherit previous objects material.
 | 
			
		||||
				// Spec tells us that a declared material must be set to all objects until a new material is declared.
 | 
			
		||||
				// If a usemtl declaration is encountered while this new object is being parsed, it will
 | 
			
		||||
				// overwrite the inherited material. Exception being that there was already face declarations
 | 
			
		||||
				// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
 | 
			
		||||
 | 
			
		||||
				if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
 | 
			
		||||
 | 
			
		||||
					var declared = previousMaterial.clone( 0 );
 | 
			
		||||
					declared.inherited = true;
 | 
			
		||||
					this.object.materials.push( declared );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				this.objects.push( this.object );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			finalize: function () {
 | 
			
		||||
 | 
			
		||||
				if ( this.object && typeof this.object._finalize === 'function' ) {
 | 
			
		||||
 | 
			
		||||
					this.object._finalize( true );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			parseVertexIndex: function ( value, len ) {
 | 
			
		||||
 | 
			
		||||
				var index = parseInt( value, 10 );
 | 
			
		||||
				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			parseNormalIndex: function ( value, len ) {
 | 
			
		||||
 | 
			
		||||
				var index = parseInt( value, 10 );
 | 
			
		||||
				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			parseUVIndex: function ( value, len ) {
 | 
			
		||||
 | 
			
		||||
				var index = parseInt( value, 10 );
 | 
			
		||||
				return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addVertex: function ( a, b, c ) {
 | 
			
		||||
 | 
			
		||||
				var src = this.vertices;
 | 
			
		||||
				var dst = this.object.geometry.vertices;
 | 
			
		||||
 | 
			
		||||
				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
 | 
			
		||||
				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
 | 
			
		||||
				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addVertexPoint: function ( a ) {
 | 
			
		||||
 | 
			
		||||
				var src = this.vertices;
 | 
			
		||||
				var dst = this.object.geometry.vertices;
 | 
			
		||||
 | 
			
		||||
				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addVertexLine: function ( a ) {
 | 
			
		||||
 | 
			
		||||
				var src = this.vertices;
 | 
			
		||||
				var dst = this.object.geometry.vertices;
 | 
			
		||||
 | 
			
		||||
				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addNormal: function ( a, b, c ) {
 | 
			
		||||
 | 
			
		||||
				var src = this.normals;
 | 
			
		||||
				var dst = this.object.geometry.normals;
 | 
			
		||||
 | 
			
		||||
				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
 | 
			
		||||
				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
 | 
			
		||||
				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addColor: function ( a, b, c ) {
 | 
			
		||||
 | 
			
		||||
				var src = this.colors;
 | 
			
		||||
				var dst = this.object.geometry.colors;
 | 
			
		||||
 | 
			
		||||
				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
 | 
			
		||||
				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
 | 
			
		||||
				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addUV: function ( a, b, c ) {
 | 
			
		||||
 | 
			
		||||
				var src = this.uvs;
 | 
			
		||||
				var dst = this.object.geometry.uvs;
 | 
			
		||||
 | 
			
		||||
				dst.push( src[ a + 0 ], src[ a + 1 ] );
 | 
			
		||||
				dst.push( src[ b + 0 ], src[ b + 1 ] );
 | 
			
		||||
				dst.push( src[ c + 0 ], src[ c + 1 ] );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addUVLine: function ( a ) {
 | 
			
		||||
 | 
			
		||||
				var src = this.uvs;
 | 
			
		||||
				var dst = this.object.geometry.uvs;
 | 
			
		||||
 | 
			
		||||
				dst.push( src[ a + 0 ], src[ a + 1 ] );
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
 | 
			
		||||
 | 
			
		||||
				var vLen = this.vertices.length;
 | 
			
		||||
 | 
			
		||||
				var ia = this.parseVertexIndex( a, vLen );
 | 
			
		||||
				var ib = this.parseVertexIndex( b, vLen );
 | 
			
		||||
				var ic = this.parseVertexIndex( c, vLen );
 | 
			
		||||
 | 
			
		||||
				this.addVertex( ia, ib, ic );
 | 
			
		||||
 | 
			
		||||
				if ( this.colors.length > 0 ) {
 | 
			
		||||
 | 
			
		||||
					this.addColor( ia, ib, ic );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if ( ua !== undefined && ua !== '' ) {
 | 
			
		||||
 | 
			
		||||
					var uvLen = this.uvs.length;
 | 
			
		||||
					ia = this.parseUVIndex( ua, uvLen );
 | 
			
		||||
					ib = this.parseUVIndex( ub, uvLen );
 | 
			
		||||
					ic = this.parseUVIndex( uc, uvLen );
 | 
			
		||||
					this.addUV( ia, ib, ic );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if ( na !== undefined && na !== '' ) {
 | 
			
		||||
 | 
			
		||||
					// Normals are many times the same. If so, skip function call and parseInt.
 | 
			
		||||
					var nLen = this.normals.length;
 | 
			
		||||
					ia = this.parseNormalIndex( na, nLen );
 | 
			
		||||
 | 
			
		||||
					ib = na === nb ? ia : this.parseNormalIndex( nb, nLen );
 | 
			
		||||
					ic = na === nc ? ia : this.parseNormalIndex( nc, nLen );
 | 
			
		||||
 | 
			
		||||
					this.addNormal( ia, ib, ic );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addPointGeometry: function ( vertices ) {
 | 
			
		||||
 | 
			
		||||
				this.object.geometry.type = 'Points';
 | 
			
		||||
 | 
			
		||||
				var vLen = this.vertices.length;
 | 
			
		||||
 | 
			
		||||
				for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
 | 
			
		||||
 | 
			
		||||
					this.addVertexPoint( this.parseVertexIndex( vertices[ vi ], vLen ) );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			},
 | 
			
		||||
 | 
			
		||||
			addLineGeometry: function ( vertices, uvs ) {
 | 
			
		||||
 | 
			
		||||
				this.object.geometry.type = 'Line';
 | 
			
		||||
 | 
			
		||||
				var vLen = this.vertices.length;
 | 
			
		||||
				var uvLen = this.uvs.length;
 | 
			
		||||
 | 
			
		||||
				for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
 | 
			
		||||
 | 
			
		||||
					this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
 | 
			
		||||
 | 
			
		||||
					this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		state.startObject( '', false );
 | 
			
		||||
 | 
			
		||||
		return state;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//
 | 
			
		||||
 | 
			
		||||
	function OBJLoader( manager ) {
 | 
			
		||||
 | 
			
		||||
		THREE.Loader.call( this, manager );
 | 
			
		||||
 | 
			
		||||
		this.materials = null;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	OBJLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
 | 
			
		||||
 | 
			
		||||
		constructor: OBJLoader,
 | 
			
		||||
 | 
			
		||||
		load: function ( url, onLoad, onProgress, onError ) {
 | 
			
		||||
 | 
			
		||||
			var scope = this;
 | 
			
		||||
 | 
			
		||||
			var loader = new THREE.FileLoader( scope.manager );
 | 
			
		||||
			loader.setPath( this.path );
 | 
			
		||||
			loader.load( url, function ( text ) {
 | 
			
		||||
 | 
			
		||||
				onLoad( scope.parse( text ) );
 | 
			
		||||
 | 
			
		||||
			}, onProgress, onError );
 | 
			
		||||
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		setMaterials: function ( materials ) {
 | 
			
		||||
 | 
			
		||||
			this.materials = materials;
 | 
			
		||||
 | 
			
		||||
			return this;
 | 
			
		||||
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		parse: function ( text ) {
 | 
			
		||||
 | 
			
		||||
			console.time( 'OBJLoader' );
 | 
			
		||||
 | 
			
		||||
			var state = new ParserState();
 | 
			
		||||
 | 
			
		||||
			if ( text.indexOf( '\r\n' ) !== - 1 ) {
 | 
			
		||||
 | 
			
		||||
				// This is faster than String.split with regex that splits on both
 | 
			
		||||
				text = text.replace( /\r\n/g, '\n' );
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if ( text.indexOf( '\\\n' ) !== - 1 ) {
 | 
			
		||||
 | 
			
		||||
				// join lines separated by a line continuation character (\)
 | 
			
		||||
				text = text.replace( /\\\n/g, '' );
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var lines = text.split( '\n' );
 | 
			
		||||
			var line = '', lineFirstChar = '';
 | 
			
		||||
			var lineLength = 0;
 | 
			
		||||
			var result = [];
 | 
			
		||||
 | 
			
		||||
			// Faster to just trim left side of the line. Use if available.
 | 
			
		||||
			var trimLeft = ( typeof ''.trimLeft === 'function' );
 | 
			
		||||
 | 
			
		||||
			for ( var i = 0, l = lines.length; i < l; i ++ ) {
 | 
			
		||||
 | 
			
		||||
				line = lines[ i ];
 | 
			
		||||
 | 
			
		||||
				line = trimLeft ? line.trimLeft() : line.trim();
 | 
			
		||||
 | 
			
		||||
				lineLength = line.length;
 | 
			
		||||
 | 
			
		||||
				if ( lineLength === 0 ) continue;
 | 
			
		||||
 | 
			
		||||
				lineFirstChar = line.charAt( 0 );
 | 
			
		||||
 | 
			
		||||
				// @todo invoke passed in handler if any
 | 
			
		||||
				if ( lineFirstChar === '#' ) continue;
 | 
			
		||||
 | 
			
		||||
				if ( lineFirstChar === 'v' ) {
 | 
			
		||||
 | 
			
		||||
					var data = line.split( /\s+/ );
 | 
			
		||||
 | 
			
		||||
					switch ( data[ 0 ] ) {
 | 
			
		||||
 | 
			
		||||
						case 'v':
 | 
			
		||||
							state.vertices.push(
 | 
			
		||||
								parseFloat( data[ 1 ] ),
 | 
			
		||||
								parseFloat( data[ 2 ] ),
 | 
			
		||||
								parseFloat( data[ 3 ] )
 | 
			
		||||
							);
 | 
			
		||||
							if ( data.length >= 7 ) {
 | 
			
		||||
 | 
			
		||||
								state.colors.push(
 | 
			
		||||
									parseFloat( data[ 4 ] ),
 | 
			
		||||
									parseFloat( data[ 5 ] ),
 | 
			
		||||
									parseFloat( data[ 6 ] )
 | 
			
		||||
 | 
			
		||||
								);
 | 
			
		||||
 | 
			
		||||
							}
 | 
			
		||||
							break;
 | 
			
		||||
						case 'vn':
 | 
			
		||||
							state.normals.push(
 | 
			
		||||
								parseFloat( data[ 1 ] ),
 | 
			
		||||
								parseFloat( data[ 2 ] ),
 | 
			
		||||
								parseFloat( data[ 3 ] )
 | 
			
		||||
							);
 | 
			
		||||
							break;
 | 
			
		||||
						case 'vt':
 | 
			
		||||
							state.uvs.push(
 | 
			
		||||
								parseFloat( data[ 1 ] ),
 | 
			
		||||
								parseFloat( data[ 2 ] )
 | 
			
		||||
							);
 | 
			
		||||
							break;
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
				} else if ( lineFirstChar === 'f' ) {
 | 
			
		||||
 | 
			
		||||
					var lineData = line.substr( 1 ).trim();
 | 
			
		||||
					var vertexData = lineData.split( /\s+/ );
 | 
			
		||||
					var faceVertices = [];
 | 
			
		||||
 | 
			
		||||
					// Parse the face vertex data into an easy to work with format
 | 
			
		||||
 | 
			
		||||
					for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {
 | 
			
		||||
 | 
			
		||||
						var vertex = vertexData[ j ];
 | 
			
		||||
 | 
			
		||||
						if ( vertex.length > 0 ) {
 | 
			
		||||
 | 
			
		||||
							var vertexParts = vertex.split( '/' );
 | 
			
		||||
							faceVertices.push( vertexParts );
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					// Draw an edge between the first vertex and all subsequent vertices to form an n-gon
 | 
			
		||||
 | 
			
		||||
					var v1 = faceVertices[ 0 ];
 | 
			
		||||
 | 
			
		||||
					for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
 | 
			
		||||
 | 
			
		||||
						var v2 = faceVertices[ j ];
 | 
			
		||||
						var v3 = faceVertices[ j + 1 ];
 | 
			
		||||
 | 
			
		||||
						state.addFace(
 | 
			
		||||
							v1[ 0 ], v2[ 0 ], v3[ 0 ],
 | 
			
		||||
							v1[ 1 ], v2[ 1 ], v3[ 1 ],
 | 
			
		||||
							v1[ 2 ], v2[ 2 ], v3[ 2 ]
 | 
			
		||||
						);
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
				} else if ( lineFirstChar === 'l' ) {
 | 
			
		||||
 | 
			
		||||
					var lineParts = line.substring( 1 ).trim().split( " " );
 | 
			
		||||
					var lineVertices = [], lineUVs = [];
 | 
			
		||||
 | 
			
		||||
					if ( line.indexOf( "/" ) === - 1 ) {
 | 
			
		||||
 | 
			
		||||
						lineVertices = lineParts;
 | 
			
		||||
 | 
			
		||||
					} else {
 | 
			
		||||
 | 
			
		||||
						for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) {
 | 
			
		||||
 | 
			
		||||
							var parts = lineParts[ li ].split( "/" );
 | 
			
		||||
 | 
			
		||||
							if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] );
 | 
			
		||||
							if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] );
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
					state.addLineGeometry( lineVertices, lineUVs );
 | 
			
		||||
 | 
			
		||||
				} else if ( lineFirstChar === 'p' ) {
 | 
			
		||||
 | 
			
		||||
					var lineData = line.substr( 1 ).trim();
 | 
			
		||||
					var pointData = lineData.split( " " );
 | 
			
		||||
 | 
			
		||||
					state.addPointGeometry( pointData );
 | 
			
		||||
 | 
			
		||||
				} else if ( ( result = object_pattern.exec( line ) ) !== null ) {
 | 
			
		||||
 | 
			
		||||
					// o object_name
 | 
			
		||||
					// or
 | 
			
		||||
					// g group_name
 | 
			
		||||
 | 
			
		||||
					// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
 | 
			
		||||
					// var name = result[ 0 ].substr( 1 ).trim();
 | 
			
		||||
					var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 );
 | 
			
		||||
 | 
			
		||||
					state.startObject( name );
 | 
			
		||||
 | 
			
		||||
				} else if ( material_use_pattern.test( line ) ) {
 | 
			
		||||
 | 
			
		||||
					// material
 | 
			
		||||
 | 
			
		||||
					state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
 | 
			
		||||
 | 
			
		||||
				} else if ( material_library_pattern.test( line ) ) {
 | 
			
		||||
 | 
			
		||||
					// mtl file
 | 
			
		||||
 | 
			
		||||
					state.materialLibraries.push( line.substring( 7 ).trim() );
 | 
			
		||||
 | 
			
		||||
				} else if ( map_use_pattern.test( line ) ) {
 | 
			
		||||
 | 
			
		||||
					// the line is parsed but ignored since the loader assumes textures are defined MTL files
 | 
			
		||||
					// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
 | 
			
		||||
 | 
			
		||||
					console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
 | 
			
		||||
 | 
			
		||||
				} else if ( lineFirstChar === 's' ) {
 | 
			
		||||
 | 
			
		||||
					result = line.split( ' ' );
 | 
			
		||||
 | 
			
		||||
					// smooth shading
 | 
			
		||||
 | 
			
		||||
					// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
 | 
			
		||||
					// but does not define a usemtl for each face set.
 | 
			
		||||
					// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
 | 
			
		||||
					// This requires some care to not create extra material on each smooth value for "normal" obj files.
 | 
			
		||||
					// where explicit usemtl defines geometry groups.
 | 
			
		||||
					// Example asset: examples/models/obj/cerberus/Cerberus.obj
 | 
			
		||||
 | 
			
		||||
					/*
 | 
			
		||||
					 * http://paulbourke.net/dataformats/obj/
 | 
			
		||||
					 * or
 | 
			
		||||
					 * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
 | 
			
		||||
					 *
 | 
			
		||||
					 * From chapter "Grouping" Syntax explanation "s group_number":
 | 
			
		||||
					 * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
 | 
			
		||||
					 * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
 | 
			
		||||
					 * surfaces, smoothing groups are either turned on or off; there is no difference between values greater
 | 
			
		||||
					 * than 0."
 | 
			
		||||
					 */
 | 
			
		||||
					if ( result.length > 1 ) {
 | 
			
		||||
 | 
			
		||||
						var value = result[ 1 ].trim().toLowerCase();
 | 
			
		||||
						state.object.smooth = ( value !== '0' && value !== 'off' );
 | 
			
		||||
 | 
			
		||||
					} else {
 | 
			
		||||
 | 
			
		||||
						// ZBrush can produce "s" lines #11707
 | 
			
		||||
						state.object.smooth = true;
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
					var material = state.object.currentMaterial();
 | 
			
		||||
					if ( material ) material.smooth = state.object.smooth;
 | 
			
		||||
 | 
			
		||||
				} else {
 | 
			
		||||
 | 
			
		||||
					// Handle null terminated files without exception
 | 
			
		||||
					if ( line === '\0' ) continue;
 | 
			
		||||
 | 
			
		||||
					throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			state.finalize();
 | 
			
		||||
 | 
			
		||||
			var container = new THREE.Group();
 | 
			
		||||
			container.materialLibraries = [].concat( state.materialLibraries );
 | 
			
		||||
 | 
			
		||||
			for ( var i = 0, l = state.objects.length; i < l; i ++ ) {
 | 
			
		||||
 | 
			
		||||
				var object = state.objects[ i ];
 | 
			
		||||
				var geometry = object.geometry;
 | 
			
		||||
				var materials = object.materials;
 | 
			
		||||
				var isLine = ( geometry.type === 'Line' );
 | 
			
		||||
				var isPoints = ( geometry.type === 'Points' );
 | 
			
		||||
				var hasVertexColors = false;
 | 
			
		||||
 | 
			
		||||
				// Skip o/g line declarations that did not follow with any faces
 | 
			
		||||
				if ( geometry.vertices.length === 0 ) continue;
 | 
			
		||||
 | 
			
		||||
				var buffergeometry = new THREE.BufferGeometry();
 | 
			
		||||
 | 
			
		||||
				buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) );
 | 
			
		||||
 | 
			
		||||
				if ( geometry.normals.length > 0 ) {
 | 
			
		||||
 | 
			
		||||
					buffergeometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) );
 | 
			
		||||
 | 
			
		||||
				} else {
 | 
			
		||||
 | 
			
		||||
					buffergeometry.computeVertexNormals();
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if ( geometry.colors.length > 0 ) {
 | 
			
		||||
 | 
			
		||||
					hasVertexColors = true;
 | 
			
		||||
					buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if ( geometry.uvs.length > 0 ) {
 | 
			
		||||
 | 
			
		||||
					buffergeometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Create materials
 | 
			
		||||
 | 
			
		||||
				var createdMaterials = [];
 | 
			
		||||
 | 
			
		||||
				for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
 | 
			
		||||
 | 
			
		||||
					var sourceMaterial = materials[ mi ];
 | 
			
		||||
					var material = undefined;
 | 
			
		||||
 | 
			
		||||
					if ( this.materials !== null ) {
 | 
			
		||||
 | 
			
		||||
						material = this.materials.create( sourceMaterial.name );
 | 
			
		||||
 | 
			
		||||
						// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
 | 
			
		||||
						if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) {
 | 
			
		||||
 | 
			
		||||
							var materialLine = new THREE.LineBasicMaterial();
 | 
			
		||||
							THREE.Material.prototype.copy.call( materialLine, material );
 | 
			
		||||
							materialLine.color.copy( material.color );
 | 
			
		||||
							material = materialLine;
 | 
			
		||||
 | 
			
		||||
						} else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) {
 | 
			
		||||
 | 
			
		||||
							var materialPoints = new THREE.PointsMaterial( { size: 10, sizeAttenuation: false } );
 | 
			
		||||
							THREE.Material.prototype.copy.call( materialPoints, material );
 | 
			
		||||
							materialPoints.color.copy( material.color );
 | 
			
		||||
							materialPoints.map = material.map;
 | 
			
		||||
							material = materialPoints;
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if ( ! material ) {
 | 
			
		||||
 | 
			
		||||
						if ( isLine ) {
 | 
			
		||||
 | 
			
		||||
							material = new THREE.LineBasicMaterial();
 | 
			
		||||
 | 
			
		||||
						} else if ( isPoints ) {
 | 
			
		||||
 | 
			
		||||
							material = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } );
 | 
			
		||||
 | 
			
		||||
						} else {
 | 
			
		||||
 | 
			
		||||
							material = new THREE.MeshPhongMaterial();
 | 
			
		||||
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						material.name = sourceMaterial.name;
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					material.flatShading = sourceMaterial.smooth ? false : true;
 | 
			
		||||
					material.vertexColors = hasVertexColors ? THREE.VertexColors : THREE.NoColors;
 | 
			
		||||
 | 
			
		||||
					createdMaterials.push( material );
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// Create mesh
 | 
			
		||||
 | 
			
		||||
				var mesh;
 | 
			
		||||
 | 
			
		||||
				if ( createdMaterials.length > 1 ) {
 | 
			
		||||
 | 
			
		||||
					for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
 | 
			
		||||
 | 
			
		||||
						var sourceMaterial = materials[ mi ];
 | 
			
		||||
						buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if ( isLine ) {
 | 
			
		||||
 | 
			
		||||
						mesh = new THREE.LineSegments( buffergeometry, createdMaterials );
 | 
			
		||||
 | 
			
		||||
					} else if ( isPoints ) {
 | 
			
		||||
 | 
			
		||||
						mesh = new THREE.Points( buffergeometry, createdMaterials );
 | 
			
		||||
 | 
			
		||||
					} else {
 | 
			
		||||
 | 
			
		||||
						mesh = new THREE.Mesh( buffergeometry, createdMaterials );
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
				} else {
 | 
			
		||||
 | 
			
		||||
					if ( isLine ) {
 | 
			
		||||
 | 
			
		||||
						mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] );
 | 
			
		||||
 | 
			
		||||
					} else if ( isPoints ) {
 | 
			
		||||
 | 
			
		||||
						mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] );
 | 
			
		||||
 | 
			
		||||
					} else {
 | 
			
		||||
 | 
			
		||||
						mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] );
 | 
			
		||||
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				mesh.name = object.name;
 | 
			
		||||
 | 
			
		||||
				container.add( mesh );
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			console.timeEnd( 'OBJLoader' );
 | 
			
		||||
 | 
			
		||||
			return container;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	} );
 | 
			
		||||
 | 
			
		||||
	return OBJLoader;
 | 
			
		||||
 | 
			
		||||
} )();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										283
									
								
								js/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,283 @@
 | 
			
		||||
class Controls {
 | 
			
		||||
    constructor(object) {
 | 
			
		||||
 | 
			
		||||
        // object is the object controlled by the controls, in our case, the camera.
 | 
			
		||||
        this.object = object;
 | 
			
		||||
 | 
			
		||||
        // 3D coordinates where the camera is looking at
 | 
			
		||||
        this.target = new THREE.Vector3(0, 0, 0);
 | 
			
		||||
 | 
			
		||||
        // Unit vectors of the local camera frame
 | 
			
		||||
        // forward is in the z-direction
 | 
			
		||||
        // left point towards the x-direction
 | 
			
		||||
        // (a vector towards y is not necessary)
 | 
			
		||||
        // in the direction of the angles
 | 
			
		||||
        this.forward = new THREE.Vector3(0,0,0);
 | 
			
		||||
        this.left = new THREE.Vector3(0,0,0);
 | 
			
		||||
 | 
			
		||||
        // speed at which the camera will translate
 | 
			
		||||
        this.speed = 50;
 | 
			
		||||
 | 
			
		||||
        // speed at which the camera will rotate
 | 
			
		||||
        this.sensitivity = 0.004;
 | 
			
		||||
 | 
			
		||||
        // angles of the camera
 | 
			
		||||
        this.angles = {
 | 
			
		||||
            delta: 0,
 | 
			
		||||
            theta: 0,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // the position of the camera is this.object.position
 | 
			
		||||
 | 
			
		||||
        this.vectorsFromAngles();
 | 
			
		||||
 | 
			
		||||
        // currently pressed keys
 | 
			
		||||
        this.keys = {
 | 
			
		||||
            up: false,
 | 
			
		||||
            down: false,
 | 
			
		||||
            left: false,
 | 
			
		||||
            right: false,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // whether the mouse is being pressed or not
 | 
			
		||||
        this.mouseClicked = false;
 | 
			
		||||
 | 
			
		||||
        // whether there is a transition running or not
 | 
			
		||||
        //   if not, this.t is NaN
 | 
			
		||||
        //   otherwise, this.t is in [0, 1]
 | 
			
		||||
        this.t = NaN;
 | 
			
		||||
 | 
			
		||||
        // calls this.keyChange(true) when a key is pressed
 | 
			
		||||
        document.addEventListener('keydown', this.keyChange(true));
 | 
			
		||||
 | 
			
		||||
        // calls this.keyChange(false) when a key is released
 | 
			
		||||
        document.addEventListener('keyup', this.keyChange(false));
 | 
			
		||||
 | 
			
		||||
        // calls this.mouseDown(e) when a mouse button is pressed
 | 
			
		||||
        document.addEventListener('mousedown', (e) => this.mouseDown(e));
 | 
			
		||||
 | 
			
		||||
        // sets this.mouseClicked to false when a mouse button is released
 | 
			
		||||
        document.addEventListener('mouseup', () => this.mouseClicked = false);
 | 
			
		||||
 | 
			
		||||
        // calls this.mouseMove(e) when the mouse is moved
 | 
			
		||||
        document.addEventListener('mousemove', (e) => this.mouseMove(e));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // rotates the camera to make it look to its target.
 | 
			
		||||
    look() {
 | 
			
		||||
        this.object.lookAt(this.target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // updates this.forward, this.left and this.target
 | 
			
		||||
    // from this.angles.delta and this.angles.theta
 | 
			
		||||
 | 
			
		||||
    //  this.forward is the vector moving direction
 | 
			
		||||
    //  this.left is the vector moving sideways to the left
 | 
			
		||||
    //  this.target is the point that the camera is looking
 | 
			
		||||
    vectorsFromAngles() {
 | 
			
		||||
        // TODO Part 1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // computes this.angles.delta and this.angles.theta from this.forward
 | 
			
		||||
    // (may be useless)
 | 
			
		||||
    anglesFromVectors() {
 | 
			
		||||
        // TODO Part 2
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // updates this.keys when a key is pressed or released
 | 
			
		||||
    keyChange(setting) {
 | 
			
		||||
        return (event) => {
 | 
			
		||||
            switch (event.keyCode) {
 | 
			
		||||
                case 37: case 81: this.keys.left = setting;          break;
 | 
			
		||||
                case 38: case 90: this.keys.up = setting;            break;
 | 
			
		||||
                case 39: case 68: this.keys.right = setting;         break;
 | 
			
		||||
                case 40: case 83:  this.keys.down = setting;          break;
 | 
			
		||||
                case 13:
 | 
			
		||||
                    console.log("Position:", this.object.position);
 | 
			
		||||
                    console.log("Target:", this.target);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // sets mouseClicked to true, and searches for a bookmark being clicked
 | 
			
		||||
    mouseDown(event) {
 | 
			
		||||
        this.mouseClicked = true;
 | 
			
		||||
 | 
			
		||||
        let mouse = {
 | 
			
		||||
            x: ( event.clientX / window.innerWidth ) * 2 - 1,
 | 
			
		||||
            y: - ( event.clientY / window.innerHeight ) * 2 + 1,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // update the picking ray with the camera and mouse position
 | 
			
		||||
        raycaster.setFromCamera(mouse, camera);
 | 
			
		||||
 | 
			
		||||
        // calculate objects intersecting the picking ray
 | 
			
		||||
        var intersects = raycaster.intersectObjects(scene.children, true);
 | 
			
		||||
 | 
			
		||||
        if (this.testIntersection(intersects)) {
 | 
			
		||||
            this.bookmarkClicked(intersects[0].object.parent);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // tests that a bookmark is clicked or not
 | 
			
		||||
    //
 | 
			
		||||
    // this function filters out other objects of the scene.
 | 
			
		||||
    testIntersection(intersects) {
 | 
			
		||||
        if (intersects.length === 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (intersects[0].object === undefined) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (! (intersects[0].object.parent instanceof Bookmark)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.object.position.distanceTo(intersects[0].object.parent.position) < 10) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.bookmarkClicked(intersects[0].object.parent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // initializes the paramters for the transition to a bookmark.
 | 
			
		||||
    bookmarkClicked(bookmark) {
 | 
			
		||||
        // TODO Part 2
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // changes this.angles depending of event.movementX and event.movementY
 | 
			
		||||
    //
 | 
			
		||||
    // event.movementX indicates how many pixels the mouse has moved to the right
 | 
			
		||||
    // event.movementY indicates how many piels the mouse has moved to the bottom
 | 
			
		||||
    // both those values can be negative to indicate a motion in the opposite direction
 | 
			
		||||
    mouseMove(event) {
 | 
			
		||||
        // TODO Part 1
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // called at every frame
 | 
			
		||||
    update() {
 | 
			
		||||
 | 
			
		||||
        // No transition : use keyboard and mouse to update the camera
 | 
			
		||||
        if (isNaN(this.t)) {
 | 
			
		||||
 | 
			
		||||
            // TODO Part 1
 | 
			
		||||
 | 
			
		||||
            if (this.keys.up) {
 | 
			
		||||
                // ...
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            // Transition to bookmark
 | 
			
		||||
            // TODO Part 2
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // update the camera parameters
 | 
			
		||||
        this.look();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let container, controls;
 | 
			
		||||
let camera, scene, renderer;
 | 
			
		||||
let raycaster = new THREE.Raycaster();
 | 
			
		||||
 | 
			
		||||
init();
 | 
			
		||||
animate();
 | 
			
		||||
 | 
			
		||||
function init() {
 | 
			
		||||
 | 
			
		||||
    container = document.createElement('div');
 | 
			
		||||
    document.body.appendChild(container);
 | 
			
		||||
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 100, 50000);
 | 
			
		||||
    camera.position.y = 1000;
 | 
			
		||||
    camera.position.z = 1000;
 | 
			
		||||
 | 
			
		||||
    scene = new THREE.Scene();
 | 
			
		||||
    let ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
 | 
			
		||||
    scene.add(ambientLight);
 | 
			
		||||
    let pointLight = new THREE.PointLight(0xffffff, 0.8);
 | 
			
		||||
    camera.add(pointLight);
 | 
			
		||||
    scene.add(camera);
 | 
			
		||||
 | 
			
		||||
    let geometry = new THREE.PlaneGeometry(20000, 20000);
 | 
			
		||||
    for (let index = 0; index < geometry.faceVertexUvs[0].length; index++) {
 | 
			
		||||
        geometry.faceVertexUvs[0][index][0].multiplyScalar(10);
 | 
			
		||||
        geometry.faceVertexUvs[0][index][1].multiplyScalar(10);
 | 
			
		||||
        geometry.faceVertexUvs[0][index][2].multiplyScalar(10);
 | 
			
		||||
    }
 | 
			
		||||
    let texture = new THREE.TextureLoader().load('assets/windfall/water.png');
 | 
			
		||||
    texture.wrapS = THREE.RepeatWrapping;
 | 
			
		||||
    texture.wrapT = THREE.RepeatWrapping;
 | 
			
		||||
    let material = new THREE.MeshBasicMaterial({map: texture});
 | 
			
		||||
    let sea = new THREE.Mesh(geometry, material);
 | 
			
		||||
    sea.rotation.x = -Math.PI / 2;
 | 
			
		||||
    scene.add(sea);
 | 
			
		||||
 | 
			
		||||
    // controls
 | 
			
		||||
    controls = new Controls(camera);
 | 
			
		||||
 | 
			
		||||
    // model
 | 
			
		||||
    let directory = "assets/windfall/";
 | 
			
		||||
    let modelName = "Windfall";
 | 
			
		||||
 | 
			
		||||
    let onProgress = function (xhr) {
 | 
			
		||||
        if (xhr.lengthComputable) {
 | 
			
		||||
            let percentComplete = xhr.loaded / xhr.total * 100;
 | 
			
		||||
            console.log(Math.round(percentComplete, 2) + '% downloaded');
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let onError = function () { };
 | 
			
		||||
    let manager = new THREE.LoadingManager();
 | 
			
		||||
 | 
			
		||||
    new THREE.MTLLoader(manager)
 | 
			
		||||
        .setPath(directory)
 | 
			
		||||
        .load(modelName + ".mtl", function (materials) {
 | 
			
		||||
            materials.preload();
 | 
			
		||||
            new THREE.OBJLoader(manager)
 | 
			
		||||
                .setMaterials(materials)
 | 
			
		||||
                .setPath(directory)
 | 
			
		||||
                .load(modelName + ".obj", function (object) {
 | 
			
		||||
                    scene.add(object);
 | 
			
		||||
                }, onProgress, onError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    renderer = new THREE.WebGLRenderer();
 | 
			
		||||
    renderer.setPixelRatio(window.devicePixelRatio);
 | 
			
		||||
    renderer.setSize(window.innerWidth, window.innerHeight);
 | 
			
		||||
    renderer.setClearColor(new THREE.Color(0x87ceeb));
 | 
			
		||||
    container.appendChild(renderer.domElement);
 | 
			
		||||
 | 
			
		||||
    window.addEventListener('resize', onWindowResize, false);
 | 
			
		||||
 | 
			
		||||
    // Add a bookmark to the scene
 | 
			
		||||
    // let position = { x: -3089.6612461510463, y: 3944.8226721499614, z: -2409.0350261969947 };
 | 
			
		||||
    // let target = { x: -3088.665295409939, y: 3944.824672148628, z: -2409.124904566436 };
 | 
			
		||||
    // let bookmark = new Bookmark(position, target);
 | 
			
		||||
    // scene.add(bookmark);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function animate() {
 | 
			
		||||
    requestAnimationFrame(animate);
 | 
			
		||||
    controls.update();
 | 
			
		||||
 | 
			
		||||
    for (let child of scene.children) {
 | 
			
		||||
        if (child instanceof Bookmark) {
 | 
			
		||||
            child.update(camera);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    renderer.render(scene, camera);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onWindowResize() {
 | 
			
		||||
    camera.aspect = window.innerWidth / window.innerHeight;
 | 
			
		||||
    camera.updateProjectionMatrix();
 | 
			
		||||
    renderer.setSize(window.innerWidth, window.innerHeight);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||