Recursos 3JS (aka three.js)
Referências
- Página: https://threejs.org
- Documentação em threejs.org.
- Manual em threejs.org.
- Exemplos em threejs.org.
- Downloads
- Para Computação Gráfica; ← recomendado!
- Do repositório oficial do threejs.org; (pode ser um ficheiro de tamanho substancial)
- Documentação
Javascriptrelevante:
Modelos
Os modelos abaixo funcionam assumindo que:
- Fez o download recomendado;
- O arquivo
zipfoi descompactado para a pastalib/da sua diretoria de trabalho;
Isto é, deve obter a seguinte àrvore:
(directoria de trabalho)/
lib/
threejs/
build/
(vários ficheiros)
addons/
jsm/
(vários ficheiros)
(os seus ficheiros de trabalho)
Um documento «standalone>
<!DOCTYPE html>
<html lang="en">
<head>
<title>3JS Embebido</title>
<meta charset="utf-8">
<script type="importmap">
{
"imports": {
"three": "./lib/threejs/build/three.module.js",
"three/addons/": "./lib/threejs/addons/jsm/"
}
}
</script>
</head>
<body>
<div id="3js:container">
</div>
<script type="module">
// Bibliotecas
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// Elemento HTML com o modelo gráfico
const container = document.getElementById("3js:container");
container.width = 512;
container.height = 512;
// Construtor (Renderer) do modelo gráfico
const renderer = new THREE.WebGLRenderer( {alpha: true} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(
container.width,
container.height );
renderer.setClearColor("khaki", 0.25);
// Ligar elemento <-> construtor
container.appendChild(renderer.domElement);
// Câmara para observar o modelo
const camera = new THREE.PerspectiveCamera(
35, // abertura
container.width/container.height, // proporção largura/altura
0.1, // corte perto
10000 // corte longe
);
camera.position.set( -2.5, 0, 20 );
// Controlos da câmara
const controls = new OrbitControls(
camera,
renderer.domElement );
// Cena do modelo (raiz)
const scene = new THREE.Scene();
// Orientar a câmara para a cena
camera.lookAt(scene.position);
// Uma geometria (caixa)
const geometry = new THREE.BoxGeometry( 5, 5, 5 );
// Um material (cor)
const material = new THREE.MeshLambertMaterial( {color: "steelblue"} );
// Um objecto gráfico (geometria + material)
const mesh = new THREE.Mesh( geometry, material );
// Ligar cena <-> objecto gráfica
scene.add( mesh );
// Uma luz
const light = new THREE.AmbientLight( "white" );
// Ligar cena <-> luz
scene.add( light );
// Processo da animação
function animate() {
controls.update(); // Atualizar os controlos
mesh.rotation.y += 0.01; // Atualizar o modelo
renderer.render(scene, camera); // Construir a cena atualizada
}
renderer.setAnimationLoop( animate ); // Ligar animação <-> construtor
</script>
</body>
</html>
Código e Documento separados
Parte HTML (Documento)
Atenção ao seguinte:
A linha
"prog": "./prog.js"noimportmapdefine o nome"prog"para importar o código que está no ficheiro./prog.js.No segundo elemento
script:
- O tipo
module, necessário para se utilizar sistema de módulos daJavascript;- A instrução
import main from "prog":na primeira linha desse elemento: Esta instrução importa para este elemento o código referido pelo nome"prog"definido noimportmapacima.
Ficheiro doc.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Modelo + Documento 3JS</title>
<meta charset="utf-8">
<script type="importmap">
{
"imports": {
"three": "./lib/threejs/build/three.module.js",
"three/addons/": "./lib/threejs/addons/jsm/",
"prog": "./prog.js"
}
}
</script>
</head>
<body>
<div id="3js:container">
</div>
<script type="module">
import main from "prog";
main();
</script>
</body>
</html>
Parte Javascript (Programa)
Atenção: A declaração
export default fucntion main()(emprog.js) é necessária para permitir-se o acesso «externo» a esta função.
Ficheiro prog.js
// Bibliotecas
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
export default function main() {
// Elemento HTML com o modelo gráfico
const container = document.getElementById("3js:container");
container.width = 512;
container.height = 512;
// Construtor (Renderer) do modelo gráfico
const renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(
container.width,
container.height);
renderer.setClearColor("khaki", 0.25);
// Ligar elemento <-> construtor
container.appendChild(renderer.domElement);
// Câmara para observar o modelo
const camera = new THREE.PerspectiveCamera(
35, // abertura
container.width / container.height, // proporção largura/altura
0.1, // corte perto
10000 // corte longe
);
camera.position.set(-2.5, 0, 20);
// Controlos da câmara
const controls = new OrbitControls(
camera,
renderer.domElement);
// Cena do modelo (raiz)
const scene = new THREE.Scene();
// Orientar a câmara para a cena
camera.lookAt(scene.position);
// Uma geometria (caixa)
const geometry = new THREE.BoxGeometry(5, 5, 5);
// Um material (cor)
const material = new THREE.MeshLambertMaterial({ color: "steelblue" });
// Um objecto gráfico (geometria + material)
const mesh = new THREE.Mesh(geometry, material);
// Ligar cena <-> objecto gráfica
scene.add(mesh);
// Uma luz
const light = new THREE.AmbientLight("white");
// Ligar cena <-> luz
scene.add(light);
// Processo da animação
function animate() {
controls.update(); // Atualizar os controlos
mesh.rotation.y += 0.01; // Atualizar o modelo
renderer.render(scene, camera); // Construir a cena atualizada
}
renderer.setAnimationLoop(animate); // Ligar animação <-> construtor
}
Geometria por Faces com mapa UV
Veja como obter mapas de reflexos e de normais em NormalMap-Online.
Geometria e mapa UV
O three.js suporta geometrias definidas por faces, e aplicação de texturas por mapas uv. A função seguinte define uma geometria por faces com um papa UV
function IndexedFaceGeometry(vertices, faces, points, sectors) {
//
// Geometry: "Indexed Face Set"
//
// Generate all the vertexes in the XYZ plane
const positions = [];
for (const i of faces) {
const xyz_point = vertices.slice(3 * i, 3 * i + 3);
positions.push(...xyz_point);
}
//
// Generate all the points in the UV plane
const uvs = [];
for (const i of sectors) {
const uv_point = points.slice(2 * i, 2 * i + 2);
uvs.push(...uv_point);
}
//
const geo = new THREE.BufferGeometry();
//
geo.setAttribute("position",
new THREE.Float32BufferAttribute(positions, 3));
geo.setAttribute("uv",
new THREE.Float32BufferAttribute(uvs, 2));
//
geo.computeVertexNormals();
geo.computeBoundingSphere();
//
return geo;
}
Textura com mapas de difusão, reflexos e normais
const textureLoader = new THREE.TextureLoader();
const diffuseMap = textureLoader.load('[ mapa de DIFUSÃO ]');
const specularMap = textureLoader.load('[ mapa de REFLEXOS ]');
const normalMap = textureLoader.load('[ mapa de NORMAIS ]');
const material = new THREE.MeshPhongMaterial( {
map: diffuseMap,
specularMap: specularMap,
normalMap: normalMap
} );