00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <water/Water2Patch.h>
00022 #include <water/Water2Constants.h>
00023 #include <common/Logger.h>
00024 #include <graph/OptionsDisplay.h>
00025 #include <GLEXT/GLState.h>
00026 #include <GLEXT/GLStateExtension.h>
00027 #include <GLEXT/GLVertexBufferObject.h>
00028 #include <GLEXT/GLInfo.h>
00029
00030 Water2Patch::Water2Patch() :
00031 data_(0), dataSize_(0), size_(0), bufferOffSet_(-1)
00032 {
00033 }
00034
00035 Water2Patch::~Water2Patch()
00036 {
00037 delete [] data_;
00038 }
00039
00040 static Vector getPosition(Water2Points &heights,
00041 int x, int y, int startX, int startY, int totalSize)
00042 {
00043 int currentX = startX + x;
00044 int currentY = startY + y;
00045 int currentXNormalized = currentX % totalSize;
00046 int currentYNormalized = currentY % totalSize;
00047 if (currentXNormalized < 0) currentXNormalized += totalSize;
00048 if (currentYNormalized < 0) currentYNormalized += totalSize;
00049
00050 int position = currentXNormalized + currentYNormalized * totalSize;
00051 DIALOG_ASSERT(position >= 0 && position < totalSize * totalSize);
00052
00053 Vector &height = heights.getPoint(currentXNormalized, currentYNormalized);
00054
00055 Vector result(
00056 height[0] + float(x) * 2.0f,
00057 height[1] + float(y) * 2.0f,
00058 height[2]);
00059 return result;
00060 }
00061
00062 void Water2Patch::generate(Water2Points &heights,
00063 int size, int totalSize,
00064 int posX, int posY,
00065 float waterHeight)
00066 {
00067 size_ = size;
00068 dataSize_ = (size + 1) * (size + 1);
00069 if (!data_) data_ = new Data[dataSize_];
00070
00071 int startX = posX * size;
00072 int startY = posY * size;
00073
00074 {
00075 Data *data = data_;
00076 for (int y=0; y<=size; y++)
00077 {
00078 for (int x=0; x<=size; x++, data++)
00079 {
00080
00081 Vector position = getPosition(heights, x, y, startX, startY, totalSize);
00082
00083
00084 data->x = position[0];
00085 data->y = position[1];
00086 data->z = position[2];
00087 }
00088 }
00089
00090 data = data_;
00091 for (int y=0; y<=size; y++)
00092 {
00093 for (int x=0; x<=size; x++, data++)
00094 {
00095
00096 Vector current(data->x, data->y, data->z);
00097 Vector other1, other2, other3, other4;
00098
00099 if (x<size) other1 = Vector((data+1)->x, (data+1)->y, (data+1)->z);
00100 else other1 = getPosition(heights, x + 1, y, startX, startY, totalSize);
00101
00102 if (y<size) other2 = Vector((data+size+1)->x, (data+size+1)->y, (data+size+1)->z);
00103 else other2 = getPosition(heights, x, y + 1, startX, startY, totalSize);
00104
00105 if (x>0) other3 = Vector((data-1)->x, (data-1)->y, (data-1)->z);
00106 else other3 = getPosition(heights, x - 1, y, startX, startY, totalSize);
00107
00108 if (y>0) other4 = Vector((data-size-1)->x, (data-size-1)->y, (data-size-1)->z);
00109 else other4 = getPosition(heights, x, y - 1, startX, startY, totalSize);
00110
00111 Vector dir1 = other1 - current;
00112 Vector dir2 = other2 - current;
00113 Vector dir3 = other3 - current;
00114 Vector dir4 = other4 - current;
00115
00116 Vector normal1 = dir1 * dir2;
00117 Vector normal3 = dir3 * dir4;
00118
00119 Vector normal = (normal1 + normal3).Normalize();
00120
00121
00122 data->nx = normal[0];
00123 data->ny = normal[1];
00124 data->nz = normal[2];
00125 }
00126 }
00127 }
00128 }
00129
00130 void Water2Patch::draw(MipMapPatchIndex &index)
00131 {
00132
00133 GLInfo::addNoTriangles(index.getSize());
00134
00135 if (!OptionsDisplay::instance()->getNoGLDrawElements() &&
00136 GLStateExtension::hasDrawRangeElements())
00137 {
00138
00139 unsigned short *indices = 0;
00140 if (index.getBufferOffSet() != -1)
00141 {
00142 indices = (unsigned short *) NULL + (index.getBufferOffSet() / sizeof(unsigned short));
00143 }
00144 else
00145 {
00146 indices = index.getIndices();
00147 }
00148
00149
00150 glDrawRangeElements(GL_TRIANGLE_STRIP,
00151 index.getMinIndex(),
00152 index.getMaxIndex(),
00153 index.getSize(),
00154 GL_UNSIGNED_SHORT,
00155 indices);
00156 DIALOG_ASSERT((index.getMaxIndex()-index.getMinIndex()+1) <
00157 GLStateExtension::getMaxElementVertices());
00158 DIALOG_ASSERT(index.getSize() <
00159 GLStateExtension::getMaxElementIndices());
00160 }
00161 else
00162 {
00163 glBegin(GL_TRIANGLE_STRIP);
00164 for (int i=0; i<index.getSize(); i++)
00165 {
00166 float *data = &data_[0].x +
00167 (sizeof(Data) / 4 * index.getIndices()[i]);
00168
00169 glNormal3fv(data + 3);
00170 glVertex3fv(data);
00171 }
00172 glEnd();
00173 }
00174 }
00175
00176 Water2Patch::Data *Water2Patch::getData(int x, int y)
00177 {
00178 DIALOG_ASSERT(x >= 0 && y >= 0 &&
00179 x <= size_ && y <= size_);
00180 return &data_[x + y * (size_ + 1)];
00181 }