sábado, 17 de diciembre de 2016

Dockers linux, procedimiento basico de instalacion

Este tutorial de dockers , se realizo pruebas en un equipo virtual con redhat 6

Se requiere usar los paquetes que están en epel
$yum install docker-io

Iniciamos el servicio y se añade al auto inicio:
$/etc/init.d/docker start
$chkconfig docker on

Si el equipo en el que requerimos el docker cuenta con Internet podemos descargarlo de la siguiente manera:
#Busca imagenes
$docker search debian
#Descarga una imagen
$docker pull debian

Ahora si contamos con una imagen de forma local o es posible conectar el equipo a internet, podemos crear la imagen o descargarla de algún repo
- Repositorio donde descargar imagenes
https://hub.docker.com/explore/
https://hub.docker.com/_/debian/

Para importar nuestra imagen puede realizarse de la siguiente forma

$cat debian_squid.tar.gz |docker import - debian-squid

Ahora podemos visualizar nuestra imagen

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
debian-squid        latest              074db2704fe9        10 days ago         228 MB

Se procede a iniciar la imagen direccionando a un puerto, en este caso a un proxy cache

$docker run -p 3129:3128 -d -i -t debian-squid /bin/bash

Una vez inicializada la imagen del contenedor , podemos instalar los paquetes requeridos, squid, se realiza su configuracion

Para volver a ingresar al contenedor del docker se requiere saber su id

$docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
9b35b6f16b74        debian-squid        "/bin/bash"         10 days ago         Up 10 days          0.0.0.0:3129->3128/tcp   cocky_jones

Ya que se conoce el id se ingresa de la siguiente forma:

$docker exec -it 9b35b6f16b74 bash

[root@iusatec ~]# docker exec -it 9b35b6f16b74 bash
root@9b35b6f16b74:/#

Una vez que tengamos un contenedor con el sw requerido podemos exportarlo o realizar una copia

Exportar
$docker export debian-squid |gzip > debian_squid.tar.gz

Realizar un commit
$docker commit 9b35b6f16b74 debian01

En el firewall la configuracion la realiza docker

$iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination      

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination      
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0        
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           ctstate RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0        
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0        

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination      

Chain DOCKER (1 references)
target     prot opt source               destination      
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.1          tcp dpt:3128

Podemos ver que el docker- proxy esta escuchando
$netstat -tupln

tcp        0      0 :::3129                     :::*                        LISTEN      14946/docker-proxy

Esto es lo basico que se requiere para trabajar con contenedores linux

jueves, 25 de agosto de 2016

processing: efécto básico matrix

Una de las ventajas de usar processing es que solamente te enfocas a realizar animaciones, efectos graficos y pueden ser programados de una manera muy sencilla, por ejemplo realizar una animación que trata de emular el código de la matrix, el cual no lleva mas que unos minutos si uno tiene las bases de pintar figuras y algo de programacion orientada a objetos





Código fuente:
m[] m1=new m[101];
void setup() {
  size(800, 600);
  fill(color(0, 255, 0));
  noStroke();
  for (int i=0; i<=100; i++) {
    m1[i]=new m(random(0, width), random(0, height), random(1, 5));
  }
}
void draw() {
  background(0);
  for (int i=0; i<=100; i++) {
    m1[i].mover();
    m1[i].display();
  }
}
class m {
  float x=0, y=0, v=0, t=1, r=0;
  int i, c;
  int[] cc=new int[61];
  m(float xx, float yy, float vv) {
    x=xx;
    y=yy;
    v=vv;
    t=random(1, 60);
    for (i=0; i<=t; i++) {
      cc[i]=(int)random(0, 150);
    }
  }
  void mover() {
    y=y+v;
    if (y>(height+t*5)) {
      y=0;
      v=random(2, 11);
      x=random(0, width);
      t=random(1, 60);
      for (i=0; i<=t; i++) {
        cc[i]=(int)random(0, 150);
      }
    }
  }
  void display() {
    for (i=0; i<=t; i++) {
      fill(0, cc[i], 0);
      rect(x, y-5*i, 5, 5);
    }
    c=(int)random(0, 255);
    fill(0, c, 0);
    rect(x, y, 5, 5);
  }
}

lunes, 23 de mayo de 2016

cluster de 2 nodos en centos/redhat

* Crear cluster

Video del funcionamiento del cluster

* Es requerido el grupo de paquetes "High Availability Management"
* Iniciar servicio ricci y hacerlo persistente para autoinicio
* Establecer password para el usuario ricci
* Asegurar comunicacion entre los nodos del clsuter
* En el archivo hosts son requeridas las ips y hostname de los nodos

ccs -h rhelcluster01 --createcluster rhelcluster
* Añadir nodos

ccs -h rhelcluster01 --addnode rhelcluster02
ccs -h rhelcluster01 --addnode rhelcluster01


* Listar nodos

ccs -h rhelcluster01 --lsnodes
* Agregar fence del cluster

ccs -h rhelcluster01 --addfencedev myfence agent=fence_virt 


Si es equipo fisico hp y tiene ILO

<fencedevice agent="fence_ilo4" auth="password" ipaddr="ip_ilo" login="cluster" name="nodo1" passwd="cluster123"/>
* Agregar un metodo al fence del cluster

ccs -h rhelcluster01 --addmethod mthd1 rhelcluster01
ccs -h rhelcluster01 --addmethod mthd1 rhelcluster02


* Agregar un dominio del failover (ordered) tomando en cuenta la prioridad de los nodos el dominio de failover

ccs -h rhelcluster01 --addfailoverdomain rhelcluster ordered
* Se agregan nodos el dominio del failover

ccs -h rhelcluster01 --addfailoverdomainnode rhelcluster rhelcluster01
ccs -h rhelcluster01 --addfailoverdomainnode rhelcluster rhelcluster02


* Visualiza configuracion del dominio failover

ccs -h rhelcluster01 --lsfailoverdomain
* Agregar un filesystem para failover

ccs -h rhelcluster01 --addresource fs name=cluster_fs device=/dev/vg_cluster/lv_datos mountpoint=/cluster_fs fstype=ext4
* Agregar un servicio al dominio del failover

ccs -h rhelcluster01 --addservice cluster_filesystem domain=rhelcluster recovery=relocate autostart=1
* Agregar un subservicio del dominio del failover

ccs -h rhelcluster01 --addsubservice cluster_filesystem fs ref=cluster_fs

ccs -h rhelcluster01 --addsubservice cluster_filesystem ip address=10.188.18.76 monitor_link=yes sleeptime=10



* Crear un disco quorum (disco compartido)

mkqdisk -c /dev/vdc -l clusterqdisk
* Agregar el quorum al cluster

ccs -h rhelcluster01 --setquorumd label=clusterqdisk 



** Es posible agregar una heuristica para el voto del quorum
  

 <heuristic program="ping -c1 -w2 10.188.18.1"/>

* Listar quorum y status del quorum

ccs -h rhelcluster01 --lsquorum
mkqdisk -L


* Propagar configuracion del cluster

ccs -h rhelcluster01 --sync --activate
* Validar configuracion de cluster

ccs -h rhelcluster01 --checkconf
* Activar todos los nodos

ccs -h rhelcluster01 --startall
* Activar un nodo

ccs -h rhelcluster01 --start

* Desactivar un nodo

ccs -h rhelcluster01 --stop
* Ver estado del cluster

clustat
Ejemplo de salida

[root@rhelcluster02 ~]# clustat
Cluster Status for rhelcluster @ Mon May 23 12:52:41 2016
Member Status: Quorate

Member Name                                 ID   Status
------ ----                                 ---- ------
rhelcluster01                                   1 Online, rgmanager
rhelcluster02                                   2 Online, Local, rgmanager
/dev/block/252:32                               0 Online, Quorum Disk

Service Name                       Owner (Last)                       State        
------- ----                       ----- ------                       -----        
service:cluster_filesystem         rhelcluster01                      started      
service:cluster_filesystem2        rhelcluster02                      started


* Si se requiere gfs2 (shared filesystem )

service clvmd start
chkconfig clvmd on
mkfs -t gfs2 -p lock_dlm -t rhelcluster:lvgfs -j 2 /dev/vg_compartido/lvgfs

       - Monstar gfs2
       mount -t gfs2 -o noatime /dev/vg_compartido/lvgfs /gfs/
       - En el fstab
       /dev/mapper/vg_compartido-lvgfs /gfs gfs2 defaults,noatime,nodiratime 0 0


* Salida de archivo de configurcion /etc/cluster/cluster.conf
________________________
<?xml version="1.0"?>
<cluster config_version="25" name="rhelcluster">
       <fence_daemon/>
       <clusternodes>
               <clusternode name="rhelcluster01" nodeid="1">
                       <fence>
                               <method name="mthd1">
                                       <device name="myfence"/>
                               </method>
                       </fence>
               </clusternode>
               <clusternode name="rhelcluster02" nodeid="2">
                       <fence>
                               <method name="mthd1">
                                       <device name="myfence"/>
                               </method>
                       </fence>
               </clusternode>
       </clusternodes>
       <cman/>
       <fencedevices>
               <fencedevice agent="fence_virt" name="myfence"/>
       </fencedevices>
       <rm>
               <failoverdomains>
                       <failoverdomain name="rhelcluster" nofailback="0" ordered="1" restricted="0">
                               <failoverdomainnode name="rhelcluster01" priority="1"/>
                               <failoverdomainnode name="rhelcluster02" priority="2"/>
                       </failoverdomain>
                       <failoverdomain name="rhelcluster2" nofailback="0" ordered="1" restricted="0">
                               <failoverdomainnode name="rhelcluster02" priority="1"/>
                               <failoverdomainnode name="rhelcluster01" priority="2"/>
                       </failoverdomain>
               </failoverdomains>
               <resources>
                       <fs device="/dev/vg_cluster/lv_datos" fstype="ext4" mountpoint="/cluster_fs" name="cluster_fs"/>
                       <fs device="/dev/vg_cluster2/lvcluster2" fstype="ext4" mountpoint="/cluster2" name="cluster2"/>
                       <fs device="/dev/vg_cluster3/lv_cluster3" fstype="ext4" mountpoint="/cluster3" name="cluster3"/>
               </resources>
               <service autostart="1" domain="rhelcluster" name="cluster_filesystem" recovery="relocate">
                       <fs ref="cluster_fs"/>
                       <ip address="8.8.8.76" monitor_link="yes" sleeptime="10"/>
               </service>
               <service autostart="1" domain="rhelcluster2" name="cluster_filesystem2" recovery="relocate">
                       <fs ref="cluster2"/>
                       <ip address="
8.8.8.77" monitor_link="yes" sleeptime="10"/>
                       <fs ref="cluster3"/>
               </service>
       </rm>
       <quorumd label="clusterqdisk"/>
</cluster>
________________________

<?xml version="1.0"?>
<cluster config_version="60" name="ccc">
       <clusternodes>
               <clusternode name="ccc01" nodeid="1" votes="1">
                       <fence>
                               <method name="mthd1">
                                       <device name="nodo1"/>
                               </method>
                       </fence>
               </clusternode>
               <clusternode name="ccc02" nodeid="2" votes="1">
                       <fence>
                               <method name="mthd1">
                                       <device name="nodo2"/>
                               </method>
                       </fence>
               </clusternode>
       </clusternodes>
       <cman transport="udpu"/>
       <totem token="27000"/>
       <fencedevices>
               <fencedevice agent="fence_ilo4" auth="password" ipaddr="8.8.8.82" login="cluster" name="nodo1" passwd="ilo123"/>
               <fencedevice agent="fence_ilo4" auth="password" ipaddr="8.8.8.83" login="cluster" name="nodo2" passwd="ilo123"/>
       </fencedevices>
       <rm>
               <failoverdomains>
                       <failoverdomain name="ccc_pakcge1" nofailback="0" ordered="1" restricted="0">
                               <failoverdomainnode name="ccc01" priority="1"/>
                               <failoverdomainnode name="ccc02" priority="2"/>
                       </failoverdomain>
                       <failoverdomain name="ccc_pakcge2" nofailback="0" ordered="1" restricted="0">
                               <failoverdomainnode name="ccc02" priority="1"/>
                               <failoverdomainnode name="ccc01" priority="2"/>
                       </failoverdomain>
               </failoverdomains>
               <resources>
                       <fs device="/dev/vgxxn1/lvaaa" fstype="ext4" mountpoint="/opt/app/aaa/" name="lvaaa"/>
                       <fs device="/dev/vgxxn1/lvrrr_prm" fstype="ext4" mountpoint="/opt/app/rrr/prm/" name="lvrr_prm"/>
                       <fs device="/dev/vgxxn1/lvwww" fstype="ext4" mountpoint="/opt/app/www/" name="lvwww"/>
                       <fs device="/dev/vgxxn2/lvaaa2" fstype="ext4" mountpoint="/opt/app/aaa2/" name="lvaaa2"/>
                       <fs device="/dev/vgxxn2/lvrrr_sec" fstype="ext4" mountpoint="/opt/app/rrr/sec/" name="lvrrr_sec"/>
               </resources>
               <service autostart="1" domain="ccc_pakcge1" name="pakcge1" recovery="relocate">
                       <fs ref="lvaaa"/>
                       <fs ref="lvrrr_prm"/>
                       <fs ref="lvwww"/>
                       <ip address="8.8.8.84" monitor_link="yes" sleeptime="10"/>
               </service>
               <service autostart="1" domain="ccc_pakcge2" name="pakcge2" recovery="relocate">
                       <fs ref="lvaaa2"/>
                       <fs ref="lvrrr_sec"/>
                       <ip address="
8.8.8.85" monitor_link="yes" sleeptime="10"/>
               </service>
       </rm>
       <quorumd label="cluster_ccc" votes="2">
               <heuristic program="ping -c1 -w2 
8.8.8.1"/>
       </quorumd>
</cluster>


________________________

martes, 3 de mayo de 2016

Cyanogen 13 en moto g3

Anexo procedimiento para la instalación de cyanogen mod 13 en un equipo moto g 3, usando una estacion de trabajo con linux arch se requiere instalar los siguientes paquetes a travez de aur

yaourt ncurses5-compat-libs

Posteriormente habilitar multilib en los repos:

tail /etc/pacman.conf  -n 1
Include = /etc/pacman.d/mirrorlist

yaourt android-sdk

Ya teniendo instaladas las herramientas para ejecutar comandos desde nuestra terminal linux, es requerido desbloquear el bootloader del telefono:

Obtener id de nuestro telefono

fastboot oem get_unlock_data

Una vez obtenidos los datos ingresarlos en la pagina:


Para proceder al desbloqueo

fastboot oem unlock 6C67...

Una vez desbloqueado el bootloader mandar el reinicio del telefono en modo bootloader

adb reboot bootloader

Lo siguiente es cargar el kernel y el sistema operativo

Se puede obtener desde:


Carga de kernel:

fastboot flash recovery ~/Downloads/cm-13.0-20160502-NIGHTLY-osprey-recovery.img

Después de procede al reinicio del teléfono en modo recovery:

adb reboot recovery

Ya una vez cargado el modo recovery, se elige la opción install update,y instalar desde el modo ADB,el teléfono se quedara en modo espera hasta que enviaron el sistema operativo a tra vez de adb

adb sideload ~/Downloads/cm-13.0-20160502-NIGHTLY-osprey.zip
Al terminar el proceso podemos reiniciar el teléfono y cargar el sistema ahora con cyanogen.

Para instalar la tienda de aplicaciones de google es posible hacerlo con twrp


fastboot flash recovery ~/Downloads/twrp-osprey-3.0.2-r1.img


La tienda de aplicaciones la obtenemos en:


Y la podemos enviar al telefono una vez que este en modo recovery

adb push ~/Downloads/open_gapps-arm-6.0-nano-20160501.zip  /data/media/0

Desde el menú del modo recovery de twrp en la opcion de install procedemos a buscar el zip de las gapps e instalarlo, es posible que se deba de limpiar el cache desde twrp si es que manda error al instalar las gapps





lunes, 23 de febrero de 2015

Access Point en linux fedora usando hostapd,dnsmasq con bloqueo de ads

Para crear un punto de acceso en linux es requerida una tarjeta wifi con la capacidad de ap, en este caso usare una tarjeta wifi por usb marca g-sky.


Los paquetes a instalar son hostapd,dnsmasq

yum install -y hostapd dnsmasq

Posteriormente le indicaremos al kernel que permita la opcion de retrasmitir paquetes entre la interface wifi y una de ethernet

[root@linux ~]# tail -n 1 /etc/sysctl.conf 
net.ipv4.ip_forward = 1

#sysctl -p

La configuracion que se usara para para hostapd:
# cat /etc/hostapd.conf

ctrl_interface=/var/run/hostapd
ctrl_interface_group=wheel
#########
#beacon_int=100
#dtim_period=2
#max_num_sta=20
#rts_threshold=2347
#fragm_threshold=2346
#preamble=1
#########
# Some usable default settings...
#macaddr_acl=1
macaddr_acl=0
#accept_mac_file=/etc/hostapd/accept
auth_algs=3
ignore_broadcast_ssid=0

# Uncomment these for base WPA & WPA2 support with a pre-shared key
wpa=3
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

# DO NOT FORGET TO SET A WPA PASSPHRASE!!
wpa_passphrase=qwertyuiop

# Most modern wireless drivers in the kernel need driver=nl80211
driver=nl80211

# Customize these for your local configuration...
interface=variable1
hw_mode=g
channel=11
ssid=kernel panic


Ahora para configurar el el dhcp, dns y el bloqueo de paginas publicitarias usaremos dnsmasq

# cat /etc/dnsmasq.conf
#dns externos , se recomiendas de google
server=8.8.8.8
server=8.8.4.4
#las interfaces , en micaso tendo un bridge y el wifi
interface=br0
interface=variable1
#se indica que la interface de ethernet solo servira dns y no dhcp
no-dhcp-interface=br0
#indicamos el rango para el pool de dhcp
dhcp-range=192.166.0.10,192.166.0.100
#indicamos el tipo de servicio que dara cada interface (3-gateway,6-dnsserver)
dhcp-option=variable1,3,192.166.0.1
dhcp-option=6,192.166.0.1
#numero de direcciones que estaran en el cache del dns
cache-size=10000
#incluimos archivos extra(ads-lista)
conf-dir=/etc/dnsmasq.d

Ahora indicaremos las listas de publicidad y las redireccionamos al host local

[root@linux ~]# head -n 10 /etc/dnsmasq.d/ads_block.conf 
address=/ihatepops.com/127.0.0.1
address=/ad319m.adk2.co/127.0.0.1
address=/ads.doktoronline.no/127.0.0.1
address=/www.leadgenetwork.com/127.0.0.1
address=/ads.v-links.net/127.0.0.1
address=/www.marketingtips.com/127.0.0.1
address=/ycv.clearshieldredirect.com/127.0.0.1
address=/tom2.ixn.local.vmsn.de/127.0.0.1
address=/ssdc.icelandair.com/127.0.0.1
address=/oxcash.com/127.0.0.1

Procedemos a activar los servicios de hostapd y dnsmasq

service dnsmasq start
service hostapd start

Los activamos al arranque del sistema

chkconfig dnsmasq on
chkconfig hostapd on

Es necesario abrir el puerto 67 para solicitud de ip en el firewall, iptables

-A IN_public_allow -p udp -m udp --dport 67 -m conntrack --ctstate NEW -j ACCEPT

Con estas configuraciones ya tenemos un ap funcional con dhcp, dns cache con bloqueador de publicidad

Nota: La tarjeta wifi tiene a tener fallos cuando esta encendida por largos periodos de tiempo 2 a 3 dias, por lo que hay que cambiarla de puerto usb, realize el siguiente script para facilitar el cambio de nombre de la tarjeta

cat wifi_upload_dnsmasq.sh 
#!/bin/bash
v1=$(ip link show| grep wl | awk '{print $2}' | tr -d ":"); 
cat hostapd.conf | sed s/variable1/$v1/g > /etc/hostapd/hostapd.conf
cat dnsmasq.conf | sed s/variable1/$v1/g > /etc/dnsmasq.conf
ifconfig $v1 192.166.0.1 netmask 255.255.255.0 up
service dnsmasq stop; service dnsmasq start
service hostapd stop; service hostapd start



martes, 6 de enero de 2015

firefox nightly desde el codigo fuente

Siempre es bueno estar probando las nuevas caracterisiticas de firefox y que mejor hacerlo compilando una version cada dia, para evitar todo el proceso  que mejor manera de siempre hacer un script bash :-)

cat data/compila_firefox.sh
#!/bin/sh
cd /home/usuario/Downloads
rm -rf mozilla-central/

#se obtiene la fuente nightly de firefox
hg clone https://hg.mozilla.org/mozilla-central
cd mozilla-central
#pueden agregarse opciones para la compilacion

touch mozconfig
#proceso de compilacion
sh mach build





Es script esta hecho para fedora 20/21, pero antes hay que cumplir algunos requisitos:

yum install mercurial
yum groupinstall 'Development Tools' 'Development Libraries' 'GNOME Software Development'
yum install mercurial autoconf213 glibc-static libstdc++-static yasm wireless-tools-devel mesa-libGL-devel alsa-lib-devel libXt-devel gstreamer-devel gstreamer-plugins-base-devel pulseaudio-libs-devel gtk2-devel dbus-glib-devel
# 'Development tools' is defunct in Fedora 19 use the following
yum groupinstall 'C Development Tools and Libraries'
yum group mark install "X Software Development"



Posteriormente agregar un cron para que el proceso se ejecute en determinado tiempo:

00 07 * * * /bin/bash /home/usuario/data/compila_firefox.sh 2>&1 >/dev/null




Ya como root pueden crear un enlace simbolico:

cd /usr/local/bin
ln -s /home/usuario/Downloads/mozilla-central/obj-x86_64-unknown-linux-gnu/dist/bin/firefox superfirefox

Y desde nuestro lanzador favorito:

superfirefox

:)


domingo, 28 de diciembre de 2014

graficando en 3d

Una vez mas traigo un ejemplo de como realizar un motor grafico en 3d basico, esta vez decidi recordar los viejos tiempos de estudiante, las formulas de rotacion de puntos en 3d son las siguientes, basandome en el articulo de la wikipedia

en processing y la mayor parte de los lenguajes de progamacion deberian de quedar asi:

void rot(float a, float b, float c) {
    xt=x;
    yt=y;
    zt=z;
    //rotar sobre x

    xr=xt;
    yr=yt*cos1(a)-zt*sin1(a);
    zr=yt*sin1(a)+zt*cos1(a);
    xt=xr;
    yt=yr;
    zt=zr;

    //rotar sobre y

    xr=xt*cos1(b)+zt*sin1(b);
    yr=yt;
    zr=-xt*cos1(b)+zt*cos1(b);
    xt=xr;
    yt=yr;
    zt=zr;

    //rotar sobre z
    xr=xt*cos1(c)-yt*sin1(c);
    yr=xt*sin1(c)+yt*cos1(c);
    zr=zt;

    xt=xr;
    yt=yr;
    zt=zr;
  } 

Pero al no utilizar las librerias 3d de los programas se tiene que representar los puntos 3d en 2d, de la siguiente manera:

int tx() {
    ri=cx+(int)(100000*xt/(zt+100000));
    return ri;
  }
  int ty() {
    rj= cy-(int)(100000*yt/(zt+100000));
    return rj;
  }

 Teniendo la teoria matematica podemos realizar graficas, o la representacion de objetos 3d,

Video





Una vez logrado el cometido, la meta es obtener objetos del mundo exterior a traves de fotografias y representarlos virtualmente en un software , modificarlos y posteriormente imprimirlos en alguna impresora 3d.

Anexo codigo fuente para processing:


float [] coseno=new float[63];
float [] seno=new float[63];
float [][][] malla=new float[101][101][3];
float [][][] malla2d=new float[101][101][3];
float theta=0,alfa=0 ,pi=3.14159265358979, rrr, it, jt;
int i, j, k, click=0;
int con=0, cx=250, cy=250;
p3d px=new p3d(100, 0, 0);
p3d py=new p3d(0, 100, 0);
p3d pz=new p3d(0, 0, 100);
//
p3d p1=new p3d(0, 0, 0);

void setup() {
  size(500, 500);
  con=0;
  for (theta=0; theta<=6.2; theta+=.1) {
    seno[con]=sin(theta);
    coseno[con]=cos(theta);
    con++;
  }
  for (i=0; i<=60; i+=1) {
    for (j=0; j<=60; j+=1) {
      malla[i][j][0]=i*5-150;
      malla[i][j][1]=j*5-150;
      //plano
      //malla[i][j][2]=0;
      //silla
      //malla[i][j][2]=malla[i][j][0]*malla[i][j][0]/100-malla[i][j][1]*malla[i][j][1]/100;
      //sombrero

      jt=(j-30)*.50;
      it=(i-30)*.50;
      rrr=sqrt(it*it+jt*jt)+3*cos(sqrt(it*it+jt*jt));
      malla[i][j][2]=rrr*10-100;
    }
  }

  i=0;
}

void draw() {
  background(255);
  fill(0);
  stroke(0); 
  px.rot(theta, alfa, .75);
  py.rot(theta, alfa, .75);
  pz.rot(theta, alfa, .75);
  stroke(255, 0, 0);
  line(cx, cy, px.tx(), px.ty());
  stroke(0, 255, 0);
  line(cx, cy, py.tx(), py.ty());
  stroke(0, 0, 255);
  line(cx, cy, pz.tx(), pz.ty()); 
  stroke(0); 
  //rotar malla
  for (i=0; i<=60; i+=1) {
    for (j=0; j<=60; j+=1) {
      p1.set(malla[i][j][0], malla[i][j][1], malla[i][j][2]);
      p1.rot(theta, .5, .75);
      malla2d[i][j][0]=p1.tx();
      malla2d[i][j][1]=p1.ty();
      //dibujar malla
      if (j>0 &&i>0) {
        line(malla2d[i][j][0], malla2d[i][j][1], malla2d[i-1][j-1][0], malla2d[i-1][j-1][1]);
        line(malla2d[i][j][0], malla2d[i][j][1], malla2d[i][j-1][0], malla2d[i][j-1][1]);
      }
    }
  }

  delay(10);
  theta+=.1;
  alfa+=.03;
  if (theta>=6.2) {
    theta=0;
  }
  if(alfa>=6.2){
    alfa=0;
  }
}
void mouseClicked() {
  if (click==0) {
    for (i=0; i<=60; i+=1) {
      for (j=0; j<=60; j+=1) {
        malla[i][j][0]=i*5-150;
        malla[i][j][1]=j*5-150;
        //plano
        malla[i][j][2]=0;
      }
    }
  }
  if (click==1) {
    for (i=0; i<=60; i+=1) {
      for (j=0; j<=60; j+=1) {
        malla[i][j][0]=i*5-150;
        malla[i][j][1]=j*5-150;
        //silla
        malla[i][j][2]=malla[i][j][0]*malla[i][j][0]/100-malla[i][j][1]*malla[i][j][1]/100;
      }
    }
  }
  if (click==2) {
    for (i=0; i<=60; i+=1) {
      for (j=0; j<=60; j+=1) {
        malla[i][j][0]=i*5-150;
        malla[i][j][1]=j*5-150;       
        //sombrero

        jt=(j-30)*.50;
        it=(i-30)*.50;
        rrr=sqrt(it*it+jt*jt)+3*cos(sqrt(it*it+jt*jt));
        malla[i][j][2]=rrr*10-100;
      }
    }
  }
  click+=1;
  if (click>=3) {
    click=0;
  }
}
float sin1(float ang) {
  if (ang<0) {
    ang=-ang;
  }
  return seno[(int)(ang*10)];
}
float cos1(float ang) {
  if (ang<0) {
    ang=-ang;
  }
  return coseno[(int)(ang*10)];
}
class p3d {
  float x, y, z, xt, yt, zt, xr, yr, zr;
  int ri, rj;
  p3d(float xx, float yy, float zz) {
    x=xx;
    y=yy;
    z=zz;
  }
  void set(float xx, float yy, float zz) {
    x=xx;
    y=yy;
    z=zz;
  } 
  void rot(float a, float b, float c) {
    xt=x;
    yt=y;
    zt=z;
    //rotar sobre x

    xr=xt;
    yr=yt*cos1(a)-zt*sin1(a);
    zr=yt*sin1(a)+zt*cos1(a);
    xt=xr;
    yt=yr;
    zt=zr;

    //rotar sobre y

    xr=xt*cos1(b)+zt*sin1(b);
    yr=yt;
    zr=-xt*cos1(b)+zt*cos1(b);
    xt=xr;
    yt=yr;
    zt=zr;

    //rotar sobre z
    xr=xt*cos1(c)-yt*sin1(c);
    yr=xt*sin1(c)+yt*cos1(c);
    zr=zt;

    xt=xr;
    yt=yr;
    zt=zr;
  } 
  int tx() {
    ri=cx+(int)(100000*xt/(zt+100000));
    return ri;
  }
  int ty() {
    rj= cy-(int)(100000*yt/(zt+100000));
    return rj;
  }
}