⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ripple.c

📁 C:Documents and SettingsAdministrator桌面VC++多媒体特效制作百例CHAR20Distort
💻 C
字号:
/*	ripple.c	Drew Olbrich, 1992	This distortion effect approximates looking down at an	image through a layer of water.  The user can poke	at the water using the mouse, generating one or more	ripple patterns.	To create the effect, an large texture image is mapped	onto a mesh of polygons.  Only the texture coordinates of	the polygon vertices are distorted -- not the vertex	coordinates.	Port to OpenGL	Nate Robins, 1997*/#include <stdio.h>#include <math.h>#include "glut.h"#include "defs.h"#include "ripple.h"extern RIPPLE_VECTOR ripple_vector[GRID_SIZE_X][GRID_SIZE_Y];extern RIPPLE_AMP ripple_amp[RIPPLE_LENGTH];extern int win_size_x, win_size_y;EFFECT ripple = { ripple_init, ripple_dynamics, ripple_redraw, ripple_click };static RIPPLE_VERTEX ripple_vertex[GRID_SIZE_X][GRID_SIZE_Y];static int cx[RIPPLE_COUNT];static int cy[RIPPLE_COUNT];static int t[RIPPLE_COUNT];static int max[RIPPLE_COUNT];static int ripple_max;/*	Initialize ripple location and age information.	Also, precompute the vertex coordinates and the default texture	coordinates assigned to them.*/void ripple_init(){  int i, j;  glDisable(GL_DEPTH_TEST);  ripple_max = (int)sqrt(win_size_y*win_size_y+win_size_x*win_size_x);  for (i = 0; i < RIPPLE_COUNT; i++)  {    t[i] = ripple_max + RIPPLE_LENGTH;    cx[i] = 0;    cy[i] = 0;    max[i] = 0;  }  for (i = 0; i < GRID_SIZE_X; i++)    for (j = 0; j < GRID_SIZE_Y; j++)    {      ripple_vertex[i][j].x[0] = i/(GRID_SIZE_X - 1.0)*win_size_x;      ripple_vertex[i][j].x[1] = j/(GRID_SIZE_Y - 1.0)*win_size_y;      ripple_vertex[i][j].dt[0] = i/(GRID_SIZE_X - 1.0);      ripple_vertex[i][j].dt[1] = j/(GRID_SIZE_Y - 1.0);    }}/*	Advance one time step and compute new texture coordinates	for the next frame of animation.*/void ripple_dynamics(int mousex, int mousey){  int i, j, k;  int x, y;  int mi, mj;  int r;  float sx, sy;  float amp;  for (i = 0; i < RIPPLE_COUNT; i++)    t[i] += RIPPLE_STEP;  for (i = 0; i < GRID_SIZE_X; i++)    for (j = 0; j < GRID_SIZE_Y; j++)    {      ripple_vertex[i][j].t[0] = ripple_vertex[i][j].dt[0];      ripple_vertex[i][j].t[1] = ripple_vertex[i][j].dt[1];      for (k = 0; k < RIPPLE_COUNT; k++)      {	x = i - cx[k];	y = j - cy[k];	if (x < 0)	{	  x *= -1;	  sx = -1.0;	}	else	  sx = 1.0;	if (y < 0)	{	  y *= -1;	  sy = -1.0;	}	else	  sy = 1.0;	mi = x;	mj = y;		r = t[k] - ripple_vector[mi][mj].r;		if (r < 0)	  r = 0;	if (r > RIPPLE_LENGTH - 1)	  r = RIPPLE_LENGTH - 1;	amp = 1.0 - 1.0*t[k]/RIPPLE_LENGTH;	amp *= amp;	if (amp < 0.0)	  amp = 0.0;		ripple_vertex[i][j].t[0]	  += ripple_vector[mi][mj].dx[0]*sx*ripple_amp[r].amplitude*amp;	ripple_vertex[i][j].t[1]	  += ripple_vector[mi][mj].dx[1]*sy*ripple_amp[r].amplitude*amp;      }    }}/*	Draw the next frame of animation.*/void ripple_redraw(){  int i, j;  glClear(GL_COLOR_BUFFER_BIT);  for (i = 0; i < GRID_SIZE_X - 1; i++)  {    for (j = 0; j < GRID_SIZE_Y - 1; j++)    {      glBegin(GL_POLYGON);      glTexCoord2fv(ripple_vertex[i][j].t);      glVertex2fv(ripple_vertex[i][j].x);      glTexCoord2fv(ripple_vertex[i][j + 1].t);      glVertex2fv(ripple_vertex[i][j + 1].x);      glTexCoord2fv(ripple_vertex[i + 1][j + 1].t);      glVertex2fv(ripple_vertex[i + 1][j + 1].x);      glTexCoord2fv(ripple_vertex[i + 1][j].t);      glVertex2fv(ripple_vertex[i + 1][j].x);      glEnd();    }  }  glutSwapBuffers();}/*	Calculate the distance between two points.*/float ripple_distance(int gx, int gy, int cx, int cy){  return sqrt(1.0*(gx - cx)*(gx - cx) + 1.0*(gy - cy)*(gy - cy));}/*	Compute the distance of the given window coordinate	to the nearest window corner, in pixels.*/int ripple_max_distance(int gx, int gy){  float d;  float temp_d;  d = ripple_distance(gx, gy, 0, 0);  temp_d = ripple_distance(gx, gy, GRID_SIZE_X, 0);  if (temp_d > d)    d = temp_d;  temp_d = ripple_distance(gx, gy, GRID_SIZE_X, GRID_SIZE_Y);  if (temp_d > d)    d = temp_d;  temp_d = ripple_distance(gx, gy, 0, GRID_SIZE_Y);  if (temp_d > d)    d = temp_d;  return (d/GRID_SIZE_X)*win_size_x + RIPPLE_LENGTH/6;}/*	Generate a new ripple when the mouse is pressed.  There's	a limit on the number of ripples that can be simultaneously	generated.*/void ripple_click(int mousex, int mousey, int state){  int index;  if (state)  {    index = 0;    while (t[index] < max[index] && index < RIPPLE_COUNT)      index++;        if (index < RIPPLE_COUNT)    {      cx[index] = 1.0*mousex/win_size_x*GRID_SIZE_X;      cy[index] = 1.0*mousey/win_size_y*GRID_SIZE_Y;      t[index] = 4*RIPPLE_STEP;      max[index] = ripple_max_distance(cx[index], cy[index]);    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -