1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/*
* More or less equal to the interference heightmap, except that it's wrapped around
* a circle instead of on a plane. :-)
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#endif
#include <GL/gl.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846264
#endif
#include "main/heightmaptunnelhandler.h"
#include "math/vector.h"
#include "exception.h"
#include "demolib_prefs.h"
#if DEMOLIB_MAINLOOP
HeightmapTunnelHandler::HeightmapTunnelHandler(MainLoop *ml, const char *title, const char *elem, Hashtable *attr) :
Object(ml, title, elem, attr)
{
this->xlod = attr->get_int("xlod");
this->ylod = attr->get_int("ylod");
this->speedlin = attr->get_float("speedlin");
this->freqlinx = attr->get_float("freqlinx");
this->freqliny = attr->get_float("freqliny");
this->ampllin = attr->get_float("ampllin");
this->speedcirc = attr->get_float("speedcirc");
this->freqcirc = attr->get_float("freqcirc");
this->amplcirc = attr->get_float("amplcirc");
this->pure_indices = true;
this->vertices_per_face = 4;
float xradscale = 2.0f * M_PI / (float)(xlod);
float xscale = 1.0f / (float)xlod;
float yscale = 1.0f / (float)ylod;
int x, y;
float xf, xrf, yf;
for (y = 0, yf = -0.5f; y < ylod; y++, yf += yscale) {
for (x = 0, xrf = 0.0f, xf = 0.0f; x < xlod; x++, xf += xscale, xrf += xradscale) {
struct vertex v = { cos(xrf) * 10.0f, sin(xrf) * 10.0f, yf * 100.0f };
struct texcoord t = { xf, yf + 0.5f };
struct normal n = { 0.0f, 1.0f, 0.0f };
this->vertices.add_end(v);
this->texcoords.add_end(t);
this->normals.add_end(n);
}
}
for (y = 0; y < ylod-1; y++) {
for (x = 0; x < xlod-1; x++) {
this->faces.add_end(y*xlod + x);
this->faces.add_end((y+1)*xlod + x);
this->faces.add_end((y+1)*xlod + ((x+1)%xlod));
this->faces.add_end(y*ylod + ((x+1)%xlod));
}
}
}
HeightmapTunnelHandler::~HeightmapTunnelHandler()
{
}
void HeightmapTunnelHandler::start_effect()
{
Object::start_effect();
}
void HeightmapTunnelHandler::draw_scene(float progress)
{
this->unlock_object();
float u1 = this->get_val("user1", progress);
float u2 = this->get_val("user2", progress);
float u3 = this->get_val("user3", progress);
float u4 = this->get_val("user4", progress);
float xscale = 1.0f / (float)(xlod-1);
float yscale = 1.0f / (float)ylod;
float xscale2 = freqlinx * xscale;
float yscale2 = freqliny * yscale;
const float p_sl = progress * speedlin;
const float flx_al = freqlinx * ampllin;
const float fly_al = freqliny * ampllin;
float xf = -u3, xfs = 0.0f;
for (int x = 0; x < xlod; x++, xf += xscale, xfs += xscale2) {
const float xxf = xf * 2.0f * M_PI;
const float xwrap = sin(xxf);
const float xwrap2 = sin(xfs * 2.0f * M_PI);
const float cosrot = cos(xxf);
const float sinrot = sin(xxf);
float yf = -u4, yfs = 0.0f;
for (int y = 0; y < ylod; y++, yf += yscale, yfs += yscale2) {
/* copied more or less directly from interferenceheightmaphandler.cpp :-) */
const float dist = hypot(xwrap, yf);
#if __GNUC__
float sin_v, cos_v;
__asm__("fsincos" : "=t" (cos_v), "=u" (sin_v) :
"0" (dist * freqcirc + progress * speedcirc));
#else
const float temp = dist * freqcirc + progress * speedcirc;
const float sin_v = sin(temp);
const float cos_v = cos(temp);
#endif
const float divval = freqcirc * amplcirc / dist;
const float z = sin_v * amplcirc +
(sin(xwrap2 + p_sl + u1) +
sin(yfs + p_sl + u2)) * ampllin;
const float dx = cos_v * xwrap * divval
+ flx_al * cos(xwrap2 + p_sl + u1);
const float dy = cos_v * yf * divval
+ fly_al * cos(yfs + p_sl + u2);
Vector normal(dx * -0.2f, dy * -0.2f, 1.0f);
normal.normalize();
vertices[y * xlod + x].x = cosrot * (10.0f - z * 2.0f);
vertices[y * xlod + x].y = sinrot * (10.0f - z * 2.0f);
/* also rotate the normal */
normals[y * xlod + x].nx = normal.x * cosrot + normal.y * sinrot;
normals[y * xlod + x].ny = normal.x * -sinrot + normal.y * cosrot;
normals[y * xlod + x].nz = normal.z;
}
}
Object::draw_scene(progress);
}
void HeightmapTunnelHandler::end_effect()
{
Object::end_effect();
}
#endif /* DEMOLIB_MAINLOOP */
|