martes 30 de junio de 2009

CubesWithinACube [ejemplo de Processing]

Jugueteando y mezclando entre si algunos de los ejemplos de Processing, salió esto.

cubeswithincube.pde

import processing.opengl.*;

// Flock array
int birdCount = 20;
Bird[]birds = new Bird[birdCount];
float[]birdsx = new float[birdCount];
float[]birdsy = new float[birdCount];
float[]birdsz = new float[birdCount];
float[]birdsrx = new float[birdCount];
float[]birdsry = new float[birdCount];
float[]birdsrz = new float[birdCount];
float[]birdsspd = new float[birdCount];
float[]birdsrot = new float[birdCount];

Cube stage; // external large cube
int cubies = 50;
Cube[]c = new Cube[cubies]; // internal little cubes
color[][]quadBG = new color[cubies][6];

// Controls cubie's movement
float[]x = new float[cubies];
float[]y = new float[cubies];
float[]z = new float[cubies];
float[]xSpeed = new float[cubies];
float[]ySpeed = new float[cubies];
float[]zSpeed = new float[cubies];

// Controls cubie's rotation
float[]xRot = new float[cubies];
float[]yRot = new float[cubies];
float[]zRot = new float[cubies];

// Size of external cube
float bounds = 300;

void setup() {
size(400, 300, OPENGL);
colorMode(RGB, 1);
texmap = loadImage("world32k.jpg");
initializeSphere(sDetail);

for (int i = 0; i < cubies; i++){
// Each cube face has a random color component
float colorShift = random(0, 1);
quadBG[i][0] = color(0, 0, 0);
quadBG[i][1] = color(random(0, .1), random(0, .1), random(0, .1));
quadBG[i][2] = color(random(0, .2), random(0, .2), random(0, .2));
quadBG[i][3] = color(random(0, .3), random(0, .3), random(0, .3));
quadBG[i][4] = color(random(0, .4), random(0, .4), random(0, .4));
quadBG[i][5] = color(random(0, .5), random(0, .5), random(0, .5));

// Cubies are randomly sized
float cubieSizex = random(10, 250);
float cubieSizey = random(10, 250);
float cubieSizez = random(10, 250);
c[i] = new Cube(cubieSizex, cubieSizey, cubieSizez);

// Initialize cubie's position, speed and rotation
x[i] = random(-10, 10);
y[i] = random(-10, 10);
z[i] = random(-10, 10);

xSpeed[i] = random(-.25, .25);
ySpeed[i] = random(-.25, .25);
zSpeed[i] = random(-.25, .25);

xRot[i] = random(1000, 100000);
yRot[i] = random(1000, 100000);
zRot[i] = random(1000, 100000);
}


for (int i = 0; i < birdCount; i++){
birds[i] = new Bird(random(-300, 300), random(-300, 300), random(-500, -2500), random(5, 30), random(5, 30));

birdsx[i] = random(20, 340);
birdsy[i] = random(30, 350);
birdsz[i] = random(1000, 4800);
birdsrx[i] = random(-160, 160);
birdsry[i] = random(-55, 55);
birdsrz[i] = random(-20, 20);
birdsspd[i] = random(.1, 3.75);
birdsrot[i] = random(.025, .15);
}

// Instantiate external large cube
stage = new Cube(bounds, bounds, bounds);
}

void draw(){
background(random(0, .025));
lights();
renderGlobe();

for (int i = 0; i < birdCount; i++){
birds[i].setFlight(birdsx[i], birdsy[i], birdsz[i], birdsrx[i], birdsry[i], birdsrz[i]);
birds[i].setWingSpeed(birdsspd[i]);
birds[i].setRotSpeed(birdsrot[i]);
birds[i].fly();
}

// Center in display window
translate(width/2, height/2, -130);

// Outer transparent cube
noFill();

// Rotate everything, including external large cube
rotateX(frameCount * 0.001);
rotateY(frameCount * 0.002);
rotateZ(frameCount * 0.001);
stroke(255);

// Move and rotate cubies
for (int i = 0; i < cubies; i++){
pushMatrix();
translate(x[i], y[i], z[i]);
rotateX(frameCount*PI/xRot[i]);
rotateY(frameCount*PI/yRot[i]);
rotateX(frameCount*PI/zRot[i]);
noStroke();
c[i].create(quadBG[i]);
x[i] += xSpeed[i];
y[i] += ySpeed[i];
z[i] += zSpeed[i];
popMatrix();

// Draw lines connecting cubbies
stroke(0);
if (i < cubies-1){
line(x[i], y[i], z[i], x[i+1], y[i+1], z[i+1]);
}

}
}

// ----------------------------------------------------------------------------------------------

PImage bg;
PImage texmap;

int sDetail = 35; // Sphere detail setting
float rotationX = 0;
float rotationY = 0;
float velocityX = 0;
float velocityY = 0;
float globeRadius = 450;
float pushBack = 0;

float[] cx, cz, sphereX, sphereY, sphereZ;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5;
int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION);

void renderGlobe() {
pushMatrix();
translate(width/2,height/2,-130);
pushMatrix();
noFill();
stroke(255,200);
strokeWeight(2);
smooth();
popMatrix();
lights();
pushMatrix();
rotateX( radians(-rotationX) );
rotateY( radians(270 - rotationY) );
fill(200);
noStroke();
textureMode(IMAGE);
texturedSphere(globeRadius, texmap);
popMatrix();
popMatrix();
rotationX += velocityX;
rotationY += velocityY;
velocityX *= 0.95;
velocityY *= 0.95;

// Implements mouse control (interaction will be inverse when sphere is upside down)
if(mousePressed){
velocityX += (mouseY-pmouseY) * 0.01;
velocityY -= (mouseX-pmouseX) * 0.01;
}
}

void initializeSphere(int res)
{
sinLUT = new float[SINCOS_LENGTH];
cosLUT = new float[SINCOS_LENGTH];

for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
}

float delta = (float)SINCOS_LENGTH/res;
float[] cx = new float[res];
float[] cz = new float[res];

// Calc unit circle in XZ plane
for (int i = 0; i < res; i++) {
cx[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
}

// Computing vertexlist vertexlist starts at south pole
int vertCount = res * (res-1) + 2;
int currVert = 0;

// Re-init arrays to store vertices
sphereX = new float[vertCount];
sphereY = new float[vertCount];
sphereZ = new float[vertCount];
float angle_step = (SINCOS_LENGTH*0.5f)/res;
float angle = angle_step;

// Step along Y axis
for (int i = 1; i < res; i++) {
float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
for (int j = 0; j < res; j++) {
sphereX[currVert] = cx[j] * curradius;
sphereY[currVert] = currY;
sphereZ[currVert++] = cz[j] * curradius;
}
angle += angle_step;
}
sDetail = res;
}

// Generic routine to draw textured sphere
void texturedSphere(float r, PImage t)
{
int v1,v11,v2;
r = (r + 100) * 0.2;
beginShape(TRIANGLE_STRIP);
texture(t);
float iu=(float)(t.width-1)/(sDetail);
float iv=(float)(t.height-1)/(sDetail);
float u=0,v=iv;
for (int i = 0; i < sDetail; i++) {
vertex(0, -r, 0,u,0);
vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
u+=iu;
}
vertex(0, -r, 0,u,0);
vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
endShape();

// Middle rings
int voff = 0;
for(int i = 2; i < sDetail; i++) {
v1=v11=voff;
voff += sDetail;
v2=voff;
u=0;
beginShape(TRIANGLE_STRIP);
texture(t);
for (int j = 0; j < sDetail; j++) {
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
u+=iu;
}

// Close each ring
v1=v11;
v2=voff;
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
endShape();
v+=iv;
}
u=0;

// Add the northern cap
beginShape(TRIANGLE_STRIP);
texture(t);
for (int i = 0; i < sDetail; i++) {
v2 = voff + i;
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
vertex(0, r, 0,u,v+iv);
u+=iu;
}
vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
endShape();

}


bird.pde

class Bird {

// Properties
float offsetX, offsetY, offsetZ;
float w, h;
int bodyFill;
int wingFill;
float ang = 0, ang2 = 0, ang3 = 0, ang4 = 0;
float radiusX = 120, radiusY = 200, radiusZ = 700;
float rotX = 15, rotY = 10, rotZ = 5;
float flapSpeed = 0.4;
float rotSpeed = 0.1;

// Constructors
Bird(){
this(0, 0, 0, 60, 80);
}

Bird(float offsetX, float offsetY, float offsetZ, float w, float h){
this.offsetX = offsetX;
this.offsetY = offsetY;
this.offsetZ = offsetZ;
this.h = h;
this.w = w;
bodyFill = color(random(0, .5), random(0, .5), random(0, .5));
wingFill = color(random(0, .1), random(0, .1), random(0, .1));
}

void setFlight(float radiusX, float radiusY, float radiusZ,
float rotX, float rotY, float rotZ){
this.radiusX = radiusX;
this.radiusY = radiusY;
this.radiusZ = radiusZ;

this.rotX = rotX;
this.rotY = rotY;
this.rotZ = rotZ;
}

void setWingSpeed(float flapSpeed){
this.flapSpeed = flapSpeed;
}

void setRotSpeed(float rotSpeed){
this.rotSpeed = rotSpeed;
}

void fly() {
pushMatrix();
float px, py, pz;

// Flight
px = sin(radians(ang3)) * radiusX;
py = cos(radians(ang3)) * radiusY;
pz = sin(radians(ang4)) * radiusZ;

translate(width/2 + offsetX + px, height/2 + offsetY+py, -700 + offsetZ+pz);

rotateX(sin(radians(ang2)) * rotX);
rotateY(sin(radians(ang2)) * rotY);
rotateZ(sin(radians(ang2)) * rotZ);

// Body
fill(bodyFill);
box(w/5, h, w/5);

// Left wing
fill(wingFill);
pushMatrix();
rotateY(sin(radians(ang)) * 20);
rect(0, -h/2, w, h);
popMatrix();

// Right wing
pushMatrix();
rotateY(sin(radians(ang)) * -20);
rect(-w, -h/2, w, h);
popMatrix();

// Wing flap
ang += flapSpeed;
if (ang > 3) {
flapSpeed*=-1;
}
if (ang < -3) {
flapSpeed*=-1;
}

// Ang's run trig functions
ang2 += rotSpeed;
ang3 += 1.25;
ang4 += 0.55;
popMatrix();
}
}



cube.pde

// Custom Cube Class

class Cube{
PVector[] vertices = new PVector[24];
float w, h, d;

// Default constructor
Cube(){ }

// Constructor 2
Cube(float w, float h, float d) {
this.w = w;
this.h = h;
this.d = d;

// cube composed of 6 quads
//front
vertices[0] = new PVector(-w/2,-h/2,d/2);
vertices[1] = new PVector(w/2,-h/2,d/2);
vertices[2] = new PVector(w/2,h/2,d/2);
vertices[3] = new PVector(-w/2,h/2,d/2);
//left
vertices[4] = new PVector(-w/2,-h/2,d/2);
vertices[5] = new PVector(-w/2,-h/2,-d/2);
vertices[6] = new PVector(-w/2,h/2,-d/2);
vertices[7] = new PVector(-w/2,h/2,d/2);
//right
vertices[8] = new PVector(w/2,-h/2,d/2);
vertices[9] = new PVector(w/2,-h/2,-d/2);
vertices[10] = new PVector(w/2,h/2,-d/2);
vertices[11] = new PVector(w/2,h/2,d/2);
//back
vertices[12] = new PVector(-w/2,-h/2,-d/2);
vertices[13] = new PVector(w/2,-h/2,-d/2);
vertices[14] = new PVector(w/2,h/2,-d/2);
vertices[15] = new PVector(-w/2,h/2,-d/2);
//top
vertices[16] = new PVector(-w/2,-h/2,d/2);
vertices[17] = new PVector(-w/2,-h/2,-d/2);
vertices[18] = new PVector(w/2,-h/2,-d/2);
vertices[19] = new PVector(w/2,-h/2,d/2);
//bottom
vertices[20] = new PVector(-w/2,h/2,d/2);
vertices[21] = new PVector(-w/2,h/2,-d/2);
vertices[22] = new PVector(w/2,h/2,-d/2);
vertices[23] = new PVector(w/2,h/2,d/2);
}
void create(){
// Draw cube
for (int i=0; i<6; i++){
beginShape(QUADS);
for (int j=0; j<4; j++){
vertex(vertices[j+4*i].x, vertices[j+4*i].y, vertices[j+4*i].z);
}
endShape();
}
}
void create(color[]quadBG){
// Draw cube
for (int i=0; i<6; i++){
fill(quadBG[i]);
beginShape(QUADS);
for (int j=0; j<4; j++){
vertex(vertices[j+4*i].x, vertices[j+4*i].y, vertices[j+4*i].z);
}
endShape();
}
}
}


jueves 25 de junio de 2009

Los radios-celulares

¿Qué tan difícil es que cuando los radios-celulares utilizan el sistema de radio usen también el mismo sistema de llamar/contestar que cuando se llama como celular normal? Es decir, que en lugar de que el distinguidísimo usuario tenga que sostener su teléfono frente a su rostro y gritar para hablar pueda simplemente pegarlo a su orejita y hablar.

Analicemos la situación:

Radio: *clic* *crack* ¡GÜEY! ¡GÜEY!
Fulano: *sosteniendo su teléfono de la mencionada forma y gritando como ya se apuntó* ¡SI! ¡ADELANTE! ¡SI!
Radio: *clic* ¡GÜEY! ¡NO LLEGÓ EL PINCHE EMBARQUE, NO MAMES!
Fulano: *paseándose* ¡LE DIJE A AQUEL CABRÓN QUE NO LA FUERA A CAGAR! ¡¿YA LE LLAMARON A GODINEZ?!
Radio: *clic* ¡SI, GÜEY! ¡PERO NO MAMES!

Etc. Por el diálogo y el fino vocabulario de los personajes, se entiende que son ingenieros.

Se entenderá el disgusto que esto causa. Ahora, si se utilizara el radio-celular como un celular normal, la cosa sería así:

Fulano: *sosteniendo su teléfono como la gente* Bueno. ¡Le dije a aquel cabrón que no la fuera a cagar! ¡¿Ya le llamaron a Godinez?

¡Mucho mejor! Asi, cuando menos, nos ahorramos la mitad de la molestia y la perturbación. Creo yo que mi propuesta es 100% factible, y desconociendo el manejo de dichos telefonitos, no estoy seguro de que todos puedan usarse de tal forma, pero las posibilidades son dos:

1) Si se pueden usar de esa forma y los usuarios no lo hacen. Entonces, en lo que a mi respecta, pueden proceder a metérselos por el orificio corporal que encuentren más apropiado para dicho fin.

2) No se pueden usar de esa forma. Los fabricantes son unos idiotas que no piensan en la incomodidad de terceros y en el hecho de que tales artefactos pueden llegar a caer en manos de ingenieros mexicanos (¡el horror!).

He dicho.

sábado 6 de junio de 2009

Felices 25 años, Tetris



Has traído tanta felicidad a este mundo.

Fuente de la imagen.