home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 3
/
CDASC03.ISO
/
maj
/
4174
/
dat
/
height
/
wake.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-01
|
6KB
|
218 lines
/* Test file to create a Targa height field for POVRay -- Alexander Enzmann */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <float.h>
#ifndef M_PI
#define M_PI 3.1415926535897932384626
#endif
static float **height_buffer, **height_buffer2;
static int GridHeight, GridWidth;
static FILE *TargaFile;
void
TargaOpen(char *filename, int x, int y)
{
unsigned char tgaheader[18];
if ((TargaFile = fopen(filename, "wb")) == NULL) {
printf("Failed to open Targa file: %s\n", filename);
exit(1);
}
memset(tgaheader, 0, 18);
tgaheader[2] = 2;
tgaheader[12] = (unsigned char)(x & 0xFF);
tgaheader[13] = (unsigned char)((x >> 8) & 0xFF);
tgaheader[14] = (unsigned char)(y & 0xFF);
tgaheader[15] = (unsigned char)((y >> 8) & 0xFF);
tgaheader[16] = 24;
tgaheader[17] = 0x20;
fwrite(tgaheader, 18, 1, TargaFile);
}
void
TargaWrite(unsigned char r, unsigned char g, unsigned char b)
{
fputc(b, TargaFile);
fputc(g, TargaFile);
fputc(r, TargaFile);
}
void
TargaClose()
{
fclose(TargaFile);
}
void
alloc_height_buffers()
{
int i, j;
GridHeight = 160;
GridWidth = 160;
height_buffer = malloc(GridHeight * sizeof(float *));
height_buffer2 = malloc(GridHeight * sizeof(float *));
if (height_buffer == NULL || height_buffer2 == NULL) {
printf("Failed to allocate height buffer\n");
exit(1);
}
for (i=0;i<GridHeight;i++) {
height_buffer[i] = malloc(GridWidth * sizeof(float));
height_buffer2[i] = malloc(GridWidth * sizeof(float));
if (height_buffer[i] == NULL || height_buffer2[i] == NULL) {
printf("Failed to allocate element %d of height buffer\n", i);
exit(1);
}
for (j=0;j<GridWidth;j++)
height_buffer[i][j] = 0.0;
}
}
void
clear_temp_buffer()
{
int i, j;
for (i=0;i<GridHeight;i++)
for (j=0;j<GridWidth;j++)
height_buffer2[i][j] = -10000.0;
}
void
add_buffers()
{
int i, j;
for (i=0;i<GridHeight;i++)
for (j=0;j<GridWidth;j++)
if (height_buffer2[i][j] != -10000.0)
height_buffer[i][j] = (height_buffer[i][j]+height_buffer2[i][j])/2;
}
void
evaluate_wake(int x0, int z0)
{
float wave_phase, crest_angle;
float y;
int x, z;
float wave_count = 4.0;
int wave_steps = 100;
float phase_delta = 2.0 * M_PI / wave_steps;
float total_phase = 2.0 * M_PI * wave_count;
int crest_steps = 180;
float amplitude = 64.0;
float wave_x_scale = 3;
float wave_z_scale = 1.4;
int step_count = 0;
float maxy = -1000.0;
float miny = 1000.0;
float decay_factor = 0.8; /* Amount of decay by wavelength */
for (wave_phase=0.0;wave_phase<=total_phase;wave_phase+=phase_delta) {
clear_temp_buffer();
printf("Step %d of %d\r", step_count, (int)(wave_count * wave_steps));
step_count++;
/* Determine the amplitude of the wave at this phase angle */
y = amplitude * /* Full wave height */
cos(fmod(wave_phase, 2.0 * M_PI)) * /* Change with phase angle */
pow(decay_factor, wave_phase); /* Decay with distance */
if (y < miny) miny = y;
if (y > maxy) maxy = y;
/* Steps through the equation for wave crests, generating offsets */
for (crest_angle=-M_PI/2.0+M_PI/((float)crest_steps);
crest_angle<M_PI/2.0;
crest_angle += M_PI / ((float)crest_steps)) {
x = x0 + wave_x_scale * (float)wave_phase *
(5 * cos(crest_angle) - cos(3 * crest_angle));
z = z0 + wave_z_scale * (float)wave_phase *
(sin(crest_angle) + sin(3 * crest_angle));
/* Add the deflection into the buffer */
if (x >= 0 && x < GridWidth && z >= -GridWidth/2 && z < GridHeight/2) {
if (height_buffer2[x][z + GridWidth/2] == -10000.0)
height_buffer2[x][z + GridWidth/2] = y;
}
}
add_buffers();
}
printf("Max: %f, Min: %f\n", maxy, miny);
}
void
evaluate_wake1(int x0, int z0)
{
int x, z;
float xx0, xx1, y, r, t0, t1, theta, wave_phase;
float k1, k2;
float wave_number = 1.0;
float amplitude = 128.0;
float ship_velocity = 50.0;
float wave_velocity = 50.0;
float miny = 10000.0;
float maxy = -10000.0;
float decay_factor = 0.8;
float dist_scale0 = 0.2;
float dist_scale1 = 0.1;
clear_temp_buffer();
for (x=1;x<GridHeight;x++) {
for (z=-GridWidth/2;z<GridWidth/2;z++) {
xx0 = x - x0;
xx1 = z - z0;
theta = atan(xx1 / xx0);
k1 = cos(theta);
k2 = sin(theta);
t0 = xx0 / ship_velocity;
t1 = fabs(xx1) / wave_velocity;
if (t1 <= t0) {
r = sqrt(xx0 * xx0 + xx1 * xx1);
wave_phase = (k1 * xx0 + k2 * xx1) * dist_scale0;
/* Determine the amplitude of the wave at this phase angle */
y = amplitude * /* Full wave height */
cos(wave_phase) * /* Change with phase angle */
pow(decay_factor, r * dist_scale1); /* Decay with distance */
if (y < miny) miny = y;
if (y > maxy) maxy = y;
height_buffer2[x][z + GridWidth/2] = y;
}
}
}
add_buffers();
}
void
dump_height_buffer()
{
unsigned char r, g, b;
float height;
int y, i, j;
for (i=0;i<GridHeight;i++) {
for (j=0;j<GridWidth;j++) {
height = height_buffer[i][j];
if (height < -128.0) height = -128.0;
if (height > 127.0) height = 127.0;
height += 128.0;
r = height;
height -= (float)r;
g = 0; /* (unsigned char)(256.0 * height); */
b = 0;
TargaWrite(r, g, b);
}
}
}
void
main()
{
alloc_height_buffers();
evaluate_wake(0, 0);
TargaOpen("wave.tga", GridWidth, GridHeight);
dump_height_buffer();
TargaClose();
}