---
title: "P3D: Texturas en Mallas"
---

En el mundo 3D podemos utilizar imágenes de mapa de bits como *texturas* de nuestras mallas.

[[P3D: Mallas]](/notasP3D/mallas.html)

Hay múltiples formas de asignar una imagen como textura de una malla. El sistema de coordenadas UV nos permitirá determinar con precisión qué puntos de nuestra textura corresponden a qué vértices de nuestra malla.

# Coordenadas UV

Se les llaman coordenadas UV a las que nos permiten ubicar puntos en una *textura*. El eje U es el horizontal y comienza en 0 en el borde izquierdo, y el eje V es el eje vertical que comienza en 0 en el borde superior.

![](/img/coordenadas-uv.png)

## Modos: `IMAGE` o `NORMAL`

El valor máximo de cada coordenada UV va a depender del modo que escojamos.

La función para asignarlo es `textureMode( )`, que puede tener alguno de los siguientes dos argumentos:

* `IMAGE`: Las coordenadas UV corresponden a las coordenadas de los pixeles de la imagen original.
* `NORMAL`: Las coordenadas UV se *normalizan*: la U va de 0 (borde izquierdo) a 1 (borde derecho), y la V de 0 (borde superior) a 1 (borde inferior)

![](/img/textura-ladrillos-image-y-normal.png)

Es recomendable trabajar con el modo `NORMAL` pues nos permite pensar en términos de porcentajes, sin importar las dimensiones de la imagen original:

```java
// normaliza las coordenadas UV de las texturas
textureMode( NORMAL ); 
```

## Wrapping: `CLAMP` o `REPEAT`

Con el modo de *wrapping* indicamos qué queremos que suceda al utilizar coordenadas UV que excedan los límites de la textura. 

La función para asignarlo es `textureWrap( )`, que puede tener alguno de los siguientes dos argumentos:

* `CLAMP`: La textura original solo existe dentro de sus límites, y fuera de ellos se asigna el color más cercano a los bordes
* `REPEAT`: La textura se repite tanto en el eje U como en V.

![](/img/textura-ladrillos-clamp-y-repeat.png)

En general puede convenir utilizar la modalidad de `REPEAT`:

```java
// repite las texturas en sus ejes U y V
textureWrap( REPEAT ); 
```

## Mapeo de coordenadas

Para utilizar una textura en una malla, necesitamos:

* Indicar una textura de tipo `PImage` o `PGraphics` con la función `texture( )`
* Asignar a cada vértice, no solo sus coordenadas x,y,z, sino también las coordenadas u,v que le corresponderían de la textura.

A continuación algunos ejemplos donde se ve en acción.

La textura utilizada es la siguiente imagen:

![](/img/ladrillos.jpg)

# Ejemplos

## Plano con textura de imagen

En este ejemplo se carga una imagen y se utiliza como textura de un plano en XY.

![](/img/textura-ladrillos-perspectiva.png)

Observa la correspondencia entre las coordenadas `x,y,z, u,v` de los cuatro vértices.

Experimenta cambiando las coordenadas de los vértices para observar qué pasa con la malla y su textura.

```java
import peasy.PeasyCam;
PeasyCam cam;

// declara variable para textura
PImage textura;

void setup() {
  size(800, 600, P3D);
  cam = new PeasyCam(this, 40);
  perspective(PI/3, 1.0*width/height, 1, 100);
  
  // carga imagen en la variable
  textura = loadImage("ladrillos.jpg");
  
  // configura modos de textura
  textureMode( NORMAL ); // coords normalizadas
  textureWrap( REPEAT ); // repite textura
}

void draw() {
  background(255);
  lights();
  
  beginShape(QUADS);
  texture( textura ); //asigna textura a malla
  // coordenadas x,y,z,  u,v:
  vertex( 0, 0, 0,    0, 0); // superior izquierda
  vertex( 5, 0, 0,    1, 0); // superior derecha
  vertex( 5, 5, 0,    1, 1); // inferior derecha
  vertex( 0, 5, 0,    0, 1); // inferior izquierda
  endShape();
  
}
```

Importante: la imagen debe estar en el mismo directorio que el sketch.

Aquí más notas sobre cargar imágenes:

[[Imágenes: Abrir, mostrar, leer]](/notas/imagenes-read.html)

## Plano con textura generada (`PGraphics`)

Este ejemplo es similar al anterior, pero con una imagen generada algorítmicamente dentro de un canvas virtual o "capa" de tipo `PGraphics`.

![](/img/textura-circulos.png)

Nota cómo las funciones de dibujo que ya conoces se utilizan para dibujar *dentro* de la capa.

```java
import peasy.PeasyCam;
PeasyCam cam;

// declara variable para capa
PGraphics capa;

void setup() {
  size(800, 600, P3D);
  cam = new PeasyCam(this, 40);
  perspective(PI/3, 1.0*width/height, 1, 100);
  
  capa = createGraphics( 400, 400 );
  
  // configura modos de textura
  textureMode( NORMAL ); // coords normalizadas
  textureWrap( REPEAT ); // repite textura
}

void draw() {
  background(255);
  lights();
  
  // dibuja en la capa dos círculos que crecen
  capa.beginDraw();
  capa.background( 0 ); // fondo negro
  capa.stroke( 255 );
  capa.noFill();
  capa.strokeWeight(10);
  capa.circle( 200, 200, frameCount%400);
  capa.circle( 200, 200, (frameCount+200)%400);
  capa.endDraw();
  
  beginShape(QUADS);
  texture( capa ); //asigna textura a malla
  // coordenadas x,y,z,  u,v:
  vertex( 0, 0, 0,    0, 0); // superior izquierda
  vertex( 5, 0, 0,    1, 0); // superior derecha
  vertex( 5, 5, 0,    1, 1); // inferior derecha
  vertex( 0, 5, 0,    0, 1); // inferior izquierda
  endShape();
  
}

```

Notas sobre capas:

[[Imágenes: Capas y máscaras]](/notas/imagenes-capas.html)

La técnica de animación utilizada en el ejemplo se aborda en estas notas:

[[Animación en función del tiempo (*frameCount*)]](/notas/animacion-frameCount.html)

## Cilindro con textura de imagen

Este ejemplo parte de un cilindro tradicional, asignando a cada cara cuadrangular una fracción proporcional de la textura en U. 

![](/img/textura-cilindro.png)

Mira qué pasa si cambias el factor que multiplica a la cantidad correspondiente a la coordenada U.

```java
import peasy.PeasyCam;
PeasyCam cam;

// declara variable para textura
PImage textura;

void setup() {
  size(800, 600, P3D);
  cam = new PeasyCam(this, 40);
  perspective(PI/3, 1.0*width/height, 1, 100);
  
  // carga imagen en la variable
  textura = loadImage("ladrillos.jpg");
  
  // configura modos de textura
  textureMode( NORMAL ); // coords normalizadas
  textureWrap( REPEAT ); // repite textura
}

void draw() {
  background(255);
  lights();
  
  noStroke();
  rotateX( PI/2 );
  cilindro(5, 10, 20);
  
}

void cilindro(float r, float h, int N){
// dibuja un cilindro tradicional
// r: radio de la base
// h: altura
// N: número de divisiones en la base

  // variables auxiliares
  float x,y,angulo;

  beginShape(QUAD_STRIP);
  texture( textura ); // asigna textura
  for(int i=0; i<=N; i=i+1){
    angulo = i*TWO_PI/N;
    x = r*cos(angulo);
    y = r*sin(angulo);
    // vértice en la base
    vertex(x,y,0,   1.0*i, 1); // uv: 1.0*i, 1
    // vértice en la tapa
    vertex(x,y,h,   1.0*i, 0); // uv: 1.0*i, 0
  }
  endShape();
}

```

[[P3D: Sólidos cilíndricos y cónicos]](/notasP3D/cilindricos-y-conicos.html)
