Referências
-
TODO
Modelos Básicos
Objetos Básicos
Geometria por Faces (indexada)
-
Instalar
vite
:npm install -D vite
. -
Criar
index.html
emain.js
como abaixo. -
Correr o "projeto":
npx vite
.
index.html
<!DOCTYPE html>
<html lang="pt">
<head>
<meta charset="utf8">
<link rel="icon" href="favicon.ico" />
<title>3JS - 2024</title>
<script type='module' src='main.js' defer></script>
</head>
<body>
<h1>3JS - 2024</h1>
<div>
<span id="terminal">(empty)</span>
<span id="container" tabindex="0"></span>
<span id="debug"></span>
</div>
</body>
</html>
main.js
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
const div_container = document.getElementById("container");
const terminal = document.getElementById("terminal");
function indexed_faces_geometry(coords, 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 = coords.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;
}
function create_model() {
//
// Lights
//
const ambient_light = new THREE.AmbientLight(0xFFFFFF);
const directional_light = new THREE.DirectionalLight( 0xffffff, 1.0 );
//
// Material
//
const loader = new THREE.TextureLoader();
const diffuseMap = loader.load("tri_textures/tri_d.png");
const specularMap = loader.load("tri_textures/tri_s.png");
const normalMap = loader.load("tri_textures/tri_n.png");
//
const grob_material = new THREE.MeshPhongMaterial({
specular: "black",
map: diffuseMap,
specularMap: specularMap,
normalMap: normalMap,
});
//
// Geometry: "Indexed Face Set"
//
// Vertexes in the XYZ space
const coords = [
0.0, 1.0, 0.0,
1.0, 0.0, 1.0,
1.0, 0.0, -1.0,
-1.0, 0.0, -1.0,
-1.0, 0.0, 1.0,
];
//
// Faces are triangles in the XYZ space
const faces = [
0, 4, 1,
0, 1, 2,
0, 2, 3,
0, 3, 4,
// ----
1, 4, 3,
1, 3, 2,
];
//
// Points in the UV plane
const points = [
0.0, 0.0,
1.0, 0.0,
0.5, 1.0,
1.0, 1.0,
0.0, 1.0,
];
//
// Segments are triangles in the UV plane
const sectors = [
2, 0, 1,
2, 0, 1,
2, 0, 1,
2, 0, 1,
0, 1, 3,
0, 3, 4,
];
//
const grob_geometry = indexed_faces_geometry(coords, faces, points, sectors);
//
const grob = new THREE.Mesh(grob_geometry, grob_material);
return [ambient_light, directional_light, grob];
}
/**
* Setup the rendering context and build a model
**/
function init(objects) {
//
const renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
});
//let size = Math.min(parent.innerWidth, parent.innerHeight, 1024);
const size = 512;
renderer.setSize(size, size);
renderer.setClearColor("skyblue", 0.1);
div_container.appendChild(renderer.domElement);
//
const scene = new THREE.Scene();
//
// Camera (and TrackballControls)
//
const camera = new THREE.PerspectiveCamera(
90, // abertura
1.0, // proporção largura/altura
0.01, // corte perto
100 // corte longe
);
camera.position.set(2, 1, 1);
camera.lookAt(scene.position);
//
const controls = new OrbitControls(camera, renderer.domElement);
div_container.addEventListener("keydown", (e) => {
if (e.key === "R" || e.key === "r") {
controls.reset();
}
});
//
//
for (const object of objects) {
scene.add(object);
}
return {
age: 1,
camera: camera,
scene: scene,
renderer: renderer,
controls: controls
}
}
/**
* Animate the model
*/
function animate(step) {
requestAnimationFrame(() => animate(step));
step.age += 1;
terminal.innerHTML = `${step.age}`;
step.controls.update();
step.renderer.render(step.scene, step.camera);
}
/**
* Entry function
*/
function main() {
const model = create_model();
const step = init(model);
animate(step);
}
terminal.innerHTML = "START";
main();
terminal.innerHTML = "DONE";