Desenhando Nuvens ou o Fractal de Plasma

Publicado por Rafael 19/11/2008

[ Hits: 7.171 ]

Homepage: nenhum

Download plasma.c




O fractal de plasma, ou fractal da nuvem, ou ainda o algoritmo para deslocamento do ponto do meio, é um algoritmo que pode ser usado tanto para gerar nuvens como terrenos aleatórios.

Para mais:
http://www.gameprogrammer.com/fractal.html#cloudyskies
http://www.ic.sunysb.edu/Stu/jseyster/plasma/

  



Esconder código-fonte

/*
* Copyright (C) 2008, 2008 Rafael Siqueira Telles Vieira
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* License: http://www.lia.ufc.br/~rafaelstv/licenca_GPL_pt.txt
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <GL/glut.h>

// aspero: rugosidade > 1 suave: rugosidade < 1
#define RUGOSIDADE 0.75
// altura e comprimento maximo do seu quadrado inicial ou janela
#define ALTURA 500
#define COMPRIMENTO 500

float distancia(float A[2], float B[2])
{
   return sqrt((A[0]-B[0])*(A[0]-B[0]) + (A[1]-B[1])*(A[1]-B[1])); 
}
// Plasma
void divideEm4(float h1,float h2,float h3,float h4, float *A, float *B, float *C, float *D)
{
   float E[2], F[2], G[2], H[2], I[2];
   float H1, H2, H3, H4, H5 ;

   // calcula novos pontos dos quadrados
   E[0] = (float) (A[0]+B[0])/2.0f;
   E[1] = (float) (A[1]+B[1])/2.0f;

   F[0] = (float) (B[0]+C[0])/2.0f;
   F[1] = (float) (B[1]+C[1])/2.0f;

   G[0] = (float) (C[0]+D[0])/2.0f;
   G[1] = (float) (C[1]+D[1])/2.0f;

   H[0] = (float) (D[0]+A[0])/2.0f;
   H[1] = (float) (D[1]+A[1])/2.0f;

   I[0] = (float) (A[0]+B[0]+C[0]+D[0])/4.0f;
   I[1] = (float) (A[1]+B[1]+C[1]+D[1])/4.0f;
   
   // calcula novas "alturas" 
   H1 = (h1+h2)/2.0f;
   H2 = (h2+h3)/2.0f;
   H3 = (h3+h4)/2.0f;
   H4 = (h4+h1)/2.0f;

   if (distancia(A,B) > 1.0f)
   {
      H5 = (h1+h2+h3+h4)/4.0f;

      float cp;
      // deslocamento da altura central sugerido pela wikipedia
      cp = (distancia(A,B)/COMPRIMENTO)*RUGOSIDADE;   

      float k;

      k = random()%100;
      k /= 100.0f;

      // subtrai ou soma aleatoriamente
      if (k > 0.5f)
         cp*= -1.0f;

      // desloca a altura do ponto do meio para cima ou para baixo
      H5 += cp;
      // evita alturas negativas ou acimas de um ponto maximo
      if (H5 < 0.0f)
      {
         H5 = 0.0f;
      }
      else if (H5 > 1.0f)
      {
         H5 = 1.0f;
      }

      divideEm4(H1,h2,H2,H5,E,B,F,I);
      divideEm4(H5,H2,h3,H3,I,F,C,G);
      divideEm4(h1,H1,H5,H4,A,E,I,H);
      divideEm4(H4,H5,H3,h4,H,I,G,D);
   }
   else
   {
      H5 = (h1+h2+h3+h4)/4.0f;      
      // pinta o ponto
      glColor3f(H5,H5,H5);
      glBegin(GL_POINTS);
         glVertex2f(I[0],I[1]);
      glEnd();   
   }
}
void exibe(void)
{
   
   float A[2], B[2], C[2], D[2];
   float H1, H2, H3, H4;

   // inicia semente aleatoria
    srand(time(NULL));
   // define os pontos limites do quadrado de desenho
   A[0]=0.0f;
   A[1]=0.0f;

   B[0]=0.0f;
   B[1]=ALTURA;

   C[0]=COMPRIMENTO;
   C[1]=ALTURA;

   D[0]=COMPRIMENTO;
   D[1]=0.0f;
   // sorteia valores aleatorios para as alturas iniciais
   H1 = random()%100;
   H1 /= 100;
   H2 = random()%100;
   H2 /= 100;
   H3 = random()%100;
   H3 /= 100;
   H4 = random()%100;
   H4 /= 100;

   glClearColor(1.0f,1.0f,1.0f,1.0f);
   glClear(GL_COLOR_BUFFER_BIT);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluOrtho2D(0,COMPRIMENTO,0,ALTURA);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   divideEm4(H1, H2, H3, H4, A, B, C, D);      
   glFlush();
}

void teclado(unsigned char tecla, int x, int y)
{
   glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc,argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize(COMPRIMENTO,ALTURA);
   glutInitWindowPosition(20,20);
   glutCreateWindow("Desenhando Nuvens");
   glutDisplayFunc(exibe);
   glutKeyboardFunc(teclado);   
   glutMainLoop();

   return 0;
}

Scripts recomendados

Exemplo de uso de Math.h

Pilha Encadeada

Método eficiente de armazenamento utilizando containers (Vector e Map)

Algoritmo de Ordenação Radix

Pilha estática em C


  

Comentários
[1] Comentário enviado por rafastv em 19/11/2008 - 23:19h

Para compilar: gcc plasma.c -lglut -o plasma
Para executar: ./plasma

Aumente ou diminua a rugosidade para fazer nuvens mais suaves ou ásperas. Altere a largura e o comprimento para aumentar ou diminuir o tamanho da imagem gerada.
Pressione qualquer tecla no teclado para gerar um novo fractal, um novo padrão de nuvens. Tire screenshots das que você gostar mais, pode ser a primeira e última vez que você as verá :)


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts