Daiu

Voy a ir documentando conceptos nuevos que aprendo en https://threejs-journey.xyz/

Crypto 101

Crypto 101

Interrumpimos la programación habitual (Three.js) para hablar un ratito sobre conceptos básicos de crypto

(No te preocupes, voy a seguir subiendo información sobre Three.js!)

La idea de esto es simplemente dar un gran pantallazo a la gente que quiere entrar al mundo de crypto.

¿Me vas a dar consejos financieros?

No, no es mi idea, este posteo no es consejo financiero. Esto es como la lotería, no se sabe qué va a pasar, lo que vos hagas es bajo tu responsabilidad

Voy a terminar siendo un/a experto/a después de leer esto?

No

¿Acaso sos una experta en crypto?

Tampoco!

¿Podemos dejar de joder con las preguntas e ir a lo que nos interesa?

Bueno, dale

Quiero invertir en Crypto y ser millonario

Oh boy, tengo malas noticias para vos... It doesn't work that way. Voy a dejar en claro unos conceptos:

1- No pongas plata que no estás dispuesto a perder o plata que no tengas. No te endeudes para poder comprar BTC solo porque estás leyendo en el diario que Fulanito recuperó 3 veces lo que invirtió y ahora vive de rentas. Es como ir al casino o jugar a la lotería. No escuches a los que te digan que saben que X moneda va a estar Y precio para Z fecha, porque no hay manera de saberlo, sino serían millonarios

2- Hay varios tipos de crypto monedas: alt coins y stable coins. Las primeras varían constantemente (si no me creen, miren cómo se mueven los últimos dígitos de la cotización del ETH respecto del dólar) y no se sabe cuánto van valer. En cambio, las stable coins son monedas que tienen el valor atado al del dólar, es decir, la relación es de 1-1 (por ejemplo la moneda DAI vale 1 USD siempre)

3- Not your keys, not your coins si vos no tenés acceso a la clave privada, no son tus monedas del todo. JAMÁS de los jamases compartas tu private key con alguien, es como entregarle la billetera a otra persona. La clave privada es como la llave a una billetera digital donde uno tiene sus monedas ahí. Repetí conmigo: no se comparte la clave privada con nadie

4- DYOR: do your own research

5- OJO con las shitcoins!! Y ojo con las que son scam. Acá algunos ejemplos: XRP, DOGE, USDT, etc.

6- Si quieren entender algunos conceptos más técnicos, les dejo algunas palabras claves para que investiguen:

  • Blockchain
  • DeFi
  • Smart Contracts
  • Clave privada y pública
  • Market cap. Acá tienen una lista https://coinmarketcap.com/es/
  • Bear market/Bull market
  • Fiat currency
  • P2P (peer to peer)
  • Crypto Address
  • Staking

Bitcoin y alt-coins

BTC fue la primer crypto moneda, si quieren leer más sobre la historia podés leer sobre Satoshi Nakamoto en Wikipedia

Por eso se dice que Bitcoin es la madre de todas las crypto monedas. Después están las alt-coins que son ETH, ADA, entre otras. En general, cada moneda tiene como un "proyecto", es por esto que es importante investigar y entender en qué están invirtiendo

De acá no quiero profundizar mucho más, en internet hay muchos recursos. Les recomiendo evitar youtubers con carteles llamativos y cara de sorpresa en los thumbnails. A mí personalmente me gusta mucho el canal de Benjamin Cowen para tener un análisis técnico del mercado y una perspectiva poco sensacionalista

Cómo compro?

Las compras se hacen mediante exchanges por ejemplo Binance o ripio

¿Mis monedas están seguras en un exchange?

Emm... Más o menos

Como les mencioné más arriba en el punto 3, hay una frase muy conocida que es "not your keys, not your coins". Es decir, si no tenés la clave privada, no son 100% tus monedas

¿¿¿Cómo que no son mis monedas??? ¿Voy corriendo a sacar la plata del exchange?

Pará, tranquilo/a. Cuando vos dejás tus monedas en un exchange, lo único que tenés es la "promesa" del exchange de que las monedas son tuyas, nada más. O sea, si el día de mañana hackean la plataforma y roban las claves privadas... fuiste. Esto no es muy común que suceda dado que al tratarse de un exchange, tienen en cuenta todas estas cosas (o deberían) y usan las medidas de seguridad que corresponden (o deberían).
Por ejemplo, hace poco salió la historia de cómo en Turquía el dueño de un exchange desapareció y dejó a muchísima gente sin acceso a sus monedas

Es raro que pase, pero no imposible. Yo duermo mejor de noche sabiendo que tengo casi todas mis monedas en una wallet, por ejemplo, Exodus

Creo que eso es todo por ahora, si van surgiendo más dudas iré agregando más cosas

Esto es solo un pantallazo, el mundo de crypto es muy interesante y divertido siempre y cuando uno sepa lo que está haciendo.
Les recomiendo que investiguen, lean, se informen y hagan las cosas a conciencia

Pueden verme en Twitch o leerme en Twitter

Si quieren recibir notificaciones cada vez que subo un posteo nuevo, pueden suscribirse https://listed.to/@daiuszw/subscribe y si les sirvió/gusta esto, también me pueden dejar un mensajito https://listed.to/authors/15023/guestbook

Basics parte I

Bienvenidos y bienvenidas!

La idea de este blog es ir volcando resúmenes de lo que voy aprendiendo en el curso de Three.js de Bruno Simon para hacerlo un poco más accesible para todos y todas y que puedan aprender sobre animaciones. Mientras tanto, también pueden ver contenido teórico sobre animaciones en el canal de youtube de la materia Técnicas de Gráficos por Computadora de la UTN FRBA donde soy ayudante 😄

Ahora si, vamos a lo que nos incumbe

Introducción

Three.js es una librería de javascript que se encuentra por encima de WebGL y es open source! Pueden ver el código acá

También se puede usar con CSS y SVG pero no es lo que nos interesa por ahora

Acá se pueden ver paginas hechas con Three.js😍:

Bueno pero, que es WebGL exactamente?

Es una API de javascript que renderiza triángulos en un <canvas> de una manera increíblemente veloz, dado que usa la placa de video (la GPU) y hace operaciones en paralelo

La GPU dibuja triángulos, y para hacerlo, necesita saber dónde se encuentran posicionados. Esta información se encuentra en los shaders, que tienen la posición de los vertices y el color de los triángulos.

Manos a la obra!

Lo primero que vamos a hacer es crear una escena bien básica con un cubo rojo en el centro.

Antes que nada, necesitamos descargarnos Three.js en nuestra compu: entran acá https://threejs.org/ y van a donde dice download. Se les va a descargar un zip, lo extraen y el archivo que vamos a usar es el que se llama three.min.js

Necesitamos crear 2 archivos: index.html y script.js. En el primero lo único que hacemos es lo siguiente:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>03 - Basic Scene</title>
</head>
<body>
    <canvas class="webgl"></canvas>
    <script src="three.min.js"></script>
    <script src="script.js"></script>
</body>
</html>

Por ahora nada raro, simplemente ponemos en el body el canvas que les mencioné anteriormente y cargamos Three.js y el código javascript.

Ahora en script.js podemos usar el objeto THREE y acceder a los métodos y clases que nos provee la librería.

Si no me creen, escriban en script.js

console.log(THREE);

Y pueden ver en la consola del navegador todo lo que tiene THREE

Para crear una escena necesitamos 4 elementos:

  • Objetos
  • Una escena que contiene los objetos
  • Una cámara
  • Un renderer

Escena

Una escena es como un container. Ahí es donde vamos a poner todos los objetos que queremos mostrar en el browser, para luego renderizarlo.

Para instanciar una escena, el código es:

const scene = new THREE.Scene();

Objetos

En este ejemplo nuestro objeto va a ser un cubo rojo.

Para crear el cubo necesitamos un mesh. Un Mesh es una combinación de una geometría (figura) y un material (cómo se ve)
Como queremos hacer un cubo rojo, vamos a usar BoxGeometry para la geometría y MeshBasicMaterial para el material.

const geometry = new THREE.BoxGeometry(1, 1, 1);

Y para instanciar el material le pasamos como parámetro un objeto que tiene el color que queremos que tenga el material (se pueden pasar más pero en este caso solo nos interesa el color)

const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });

Como pueden observar, le pasamos 0x seguido del color en hexadecimal. El color se puede setear de muchas maneras: https://threejs.org/docs/?q=mesh#api/en/math/Color

Ahora sí podemos crear nuestro mesh:

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);

Y lo agregamos a nuestra escena (muy importante! Si no no se va a ver)

scene.add(mesh);

Cámara

La cámara no es algo que nosotros vemos, sino que es el punto de vista desde donde se ve la escena. Podemos usar varias cámaras pero en general se usa una

Para setear la cámara, instanciamos una clase de PerspectiveCamera a la que le pasamos dos parámetros: el FOV (field of view) que es el ángulo de visión en grados, en este caso vamos a usar 75. El segundo parámetro es el aspect ratio que es lo que el ancho del canvas / el alto.
Recuerden al final agregar la cámara a la escena.

const sizes = {
    width: 800,
    height: 600
};

const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
scene.add(camera);

Renderer

El renderer se encarga de hacer el render. Vamos a instanciar un WebGLRenderer y le pasaremos como parámetro un objeto que tiene el canvas que pusimos en el HTML más arriba.
También tenemos que setearle el tamaño que va a ser el mismo que usamos para el aspect ratio 😉

const canvas = document.querySelector('canvas.webgl');

const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(sizes.width, sizes.height);

Ahora llegó el momento de renderizar. Para eso, hacemos:

renderer.render(scene, camera);

Si abren index.html, van a notar que solo se ve un cuadrado negro. Esto es porque la cámara está adentro del cubo. Para poder verlo, necesitamos alejar la cámara de este y para eso hacemos:

camera.position.z = 3;

AxesHelper

Algo que nos puede ayudar mucho a saber dónde están los ejes es la clase AxesHelper
Cuando lo agregamos a la escena, vamos a ver en color verde el eje y positivo, en color rojo el x positivo, y en color azul el eje z positivo

const axesHelper = new THREE.AxesHelper(2);
scene.add(axesHelper);

El parámetro que se manda al instanciar esta clase, es el largo de los ejes (si queremos que se vean más grandes o más chicos)

Transformaciones

Los objetos que usamos en las escenas tienen 4 atributos:

  • position (para moverlo)
  • scale (para cambiar el tamaño)
  • rotation (para rotarlo)
  • quaternion (para rotarlo - luego vamos a profundizar sobre esto)

position

Tiene 3 propiedades esenciales, que son x, y y z.

Para mover un objeto:

  • a la derecha => asignamos un valor > 0 en x
  • a la izquierda => asignamos un valor < 0 en x
  • hacia arriba => asignamos un valor > 0 en y
  • hacia abajo => asignamos un valor < 0 en y
  • hacia adelante (o sea hacia nosotros) => asignamos un valor > 0 en z
  • hacia atrás (o sea alejado de nosotros) => asignamos un valor < 0 en z

Tengan en cuenta que tienen que mover al objeto antes de renderizarlo

Por ejemplo:

mesh.position.x = 0.9;
mesh.position.y = -1;
mesh.position.z = 2;

position es una instancia de Vector3, por lo tanto tiene los siguientes métodos heredados:

console.log(mesh.position.length());
console.log(mesh.position.distanceTo(camera.position)); // distancia a otro Vector3
console.log(mesh.position.normalize()); // normaliza un vector, o sea, hace que su módulo (tamaño) sea 1
mesh.position.set(0.9, -1, 2); // setea los atributos x, y, z

scale

Al igual que position, scale es una instancia de Vector3. Se usa para setear en cuántas veces querés setear el tamaño del objeto. Por ejemplo, si ponemos 0.5, va a ser la mitad de chico; y si ponemos 2, va a ser el doble de grande.

mesh.scale.x = 2;
mesh.scale.y = 0.25;
mesh.scale.z = 0.5;

PD: ojo! no usen números negativos.

rotation

A diferencia de position y scale, rotation no es un Vector3, sino que es un Euler. Según el eje que cambiemos, es sobre el eje que va a rotar el objeto. Por ejemplo, si cambiamos el y, va a rotar como una calesita.

Los valores de x, y y z están expresados en radianes, esto implica que si queremos que rote media vuelta, tenemos que asignarle π. Esto en javascript se logra usando la constante Math.PI

Peeeero tenemos un problemilla: Esta clase de rotaciones nos puede traer problemas dependiendo en qué orden se aplican las rotaciones. Este problema se llama gimbal lock y nos saca un grado de libertad. Si quieren leer más sobre eso pueden leer una explicación matemática. Para ayudarnos con este problema, vienen los quaterniones al rescate!

quaternion

Como dijimos antes, los quaterniones se usan para las rotaciones. En esta parte del curso no profundiza sobre quaterniones así que no vamos a ahondar sobre el tema.

Tengan en cuenta que al actualizar el atributo de rotation, se actualizan los valores de quaternion

Combinando transformaciones

Se pueden combinar la posición, la rotación (ya sea de Euler o quaternión) y la escala en cualquier tipo de orden. El resultado será el mismo

Hi, I'm Mr. Meeseeks, look at me!

Mr. Meeseeks

Todas las instancias de Object3D tienen un método que se llama lookAt() que recibe como argumento un Vector3. Podemos hacer, por ejemplo

camera.lookAt(new THREE.Vector3(0, 1, -1));

Grupos

Muchas veces vamos a querer mover un conjunto de objetos de la misma manera. Por ejemplo, estamos armando un auto, con las ruedas y puertas y queremos que sea más chico. Si quisiéramos achicar el auto, tendriámos que achicar cada parte por separado, o sea, un bajón 😔
Una solución a esto son los Group.

Para usarlo, lo instanciamos y lo agregamos a la escena para luego agregarle los objetos que querramos.

const group = new THREE.Group();
group.scale.y = 2;
group.rotation.y = 0.2;
scene.add(group);

const cube1 = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
cube1.position.x = -1.5;
group.add(cube1);

const cube2 = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
cube2.position.x = 0;
group.add(cube2);

const cube3 = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
cube3.position.x = 1.5;
group.add(cube3);

Tengan en cuenta que group hereda de Object3D, por lo tanto, tiene los atributos y clases que mencioné más arriba.

Animaciones

Cada vez que hacemos renderer.render(...) es como sacarle una "foto" a la escena. Las animaciones no son nada más ni nada menos que muchas fotos consecutivas de la escena, como si fuera un stop-motion.

La pantalla que uno ve corre a determinados FPS (frames per second), que en general suele ser 60FPS.

requestAnimationFrame

window.requestAnimationFrame() es un método que recibe como argumento una función que ejecutará en el próximo render. En el 99% de los casos vamos a usar esta función de manera recursiva ya que queremos que nuestra función que anima a los objetos se ejecute todo el tiempo

const loop = () => {
    mesh.rotation.y += 0.01;
    renderer.render(scene, camera);
    window.requestAnimationFrame(loop);
};

loop();

El código de arriba crea una función y la guarda en la variable loop. Adentro de la función se invoca a window.requestAnimationFrame que hace justamente lo que queremos: ejecuta loop en el próximo render. No se olviden de llamar loop por primera vez porque sino no se ejecuta nuestra función y no podremos ver nuestras bellas animaciones.

Pero tenemos un problema:

Si yo corro este código en una computadora con mejor GPU y en otra con peor, vamos a ver las animaciones a distintas velocidades porque tendremos distintos FPS.

La solución? Que la animación (en este caso, la rotación) dependa del tiempo entre cada render.

let time = Date.now();

const loop = () => {
    const currentTime = Date.now();
    const deltaTime = currentTime - time;
    time = currentTime;

    mesh.rotation.y += 0.01 * deltaTime;

    renderer.render(scene, camera);
    window.requestAnimationFrame(loop);
}

loop();

Solución de Three.js

Three.js tiene una clase que se llama Clock que hace por nosotros el código escrito anteriormente mediante la función getElapsedTime(), que nos retorna cuántos segundos pasaron desde que se instanció la clase Clock.

const clock = new THREE.Clock()

const loop = () => {
    const elapsedTime = clock.getElapsedTime();

    mesh.rotation.y = elapsedTime;

    renderer.render(scene, camera);
    window.requestAnimationFrame(loop);
}

loop();

Volviendo a las animaciones

Acá es donde uno se pone creativo: podemos usar, por ejemplo, la función seno que oscila entre el -1 y 1 para hacer que nuestro cubo se mueva en el eje y entre -1 y 1

const clock = new THREE.Clock()

const loop = () => {
    const elapsedTime = clock.getElapsedTime();

    mesh.rotation.y = Math.sin(elapsedTime);

    renderer.render(scene, camera);
    window.requestAnimationFrame(loop);
}

loop();

Y si queremos que el cubo haga la trayectoria de un círculo

const clock = new THREE.Clock()

const loop = () => {
    const elapsedTime = clock.getElapsedTime();

    mesh.rotation.y = Math.sin(elapsedTime);
    mesh.position.x = Math.cos(elapsedTime);

    renderer.render(scene, camera);
    window.requestAnimationFrame(loop);
}

loop();

Ta-da!

Usando GSAP

GSAP es una librería, por lo tanto tenemos que agregarla a nuestro proyecto. Al igual que la mayoría de las librerías, su objetivo es simplificarnos las cosas, con ella es más simple generar animaciones

gsap.to(mesh.position, { duration: 1, delay: 1, x: 2 });

const loop = () => {
    renderer.render(scene, camera);
    window.requestAnimationFrame(loop);
}

loop();

Acá le decimos a gsap que cambie la posición del mesh, que se mueva 2 unidades en el eje x, que tarde un segundo en empezar y que dure un segundo

PD: ojo! A gsap le pasamos la position, no todo el mesh

That's all folks
That's all folks! Si llegaron hasta acá, gracias por leer🥰
A medida que vaya viendo los otros módulos voy a ir subiendo los resúmenes acá.
Mientras tanto, pueden verme en Twitch o leerme en Twitter

Si quieren recibir notificaciones cada vez que subo un posteo nuevo, pueden suscribirse https://listed.to/@daiuszw/subscribe y si les sirvió/gusta esto, también me pueden dejar un mensajito https://listed.to/authors/15023/guestbook

Hasta la próxima!!