From 69209c38968c6f4066a772e0a51a2928749217de Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Fri, 9 Dec 2011 19:00:23 +0000 Subject: Re-indenting the code to use standard tabs. Yes, I know this is pretty pointless, but who cares? --- Stars45/TerrainPatch.cpp | 1734 +++++++++++++++++++++++----------------------- 1 file changed, 867 insertions(+), 867 deletions(-) (limited to 'Stars45/TerrainPatch.cpp') diff --git a/Stars45/TerrainPatch.cpp b/Stars45/TerrainPatch.cpp index 463ee9b..c04b5f5 100644 --- a/Stars45/TerrainPatch.cpp +++ b/Stars45/TerrainPatch.cpp @@ -1,14 +1,14 @@ /* Project Starshatter 4.5 - Destroyer Studios LLC - Copyright © 1997-2005. All Rights Reserved. + Destroyer Studios LLC + Copyright © 1997-2005. All Rights Reserved. - SUBSYSTEM: Stars.exe - FILE: TerrainPatch.cpp - AUTHOR: John DiCamillo + SUBSYSTEM: Stars.exe + FILE: TerrainPatch.cpp + AUTHOR: John DiCamillo - OVERVIEW - ======== + OVERVIEW + ======== */ #include "MemDebug.h" @@ -43,182 +43,182 @@ static bool illuminating = false; // +--------------------------------------------------------------------+ TerrainPatch::TerrainPatch(Terrain* terr,const Bitmap* patch, const Rect& r, - const Point& p1, const Point& p2) - : ndetail(0), terrain(terr), rect(r), water(0), min_height(1e9), max_height(-1e9) +const Point& p1, const Point& p2) +: ndetail(0), terrain(terr), rect(r), water(0), min_height(1e9), max_height(-1e9) { - luminous = true; // we will do our own lighting - own_model = false; // manage the model lifetimes in this derived class + luminous = true; // we will do our own lighting + own_model = false; // manage the model lifetimes in this derived class - max_detail = Terrain::DetailLevel(); - scale = fabs(p1.x - p2.x) / (PATCH_SIZE-1); - mtnscale = p2.y - p1.y; - base = p1.y; - size = p2.x - p1.x; + max_detail = Terrain::DetailLevel(); + scale = fabs(p1.x - p2.x) / (PATCH_SIZE-1); + mtnscale = p2.y - p1.y; + base = p1.y; + size = p2.x - p1.x; - ZeroMemory(detail_levels, sizeof(detail_levels)); + ZeroMemory(detail_levels, sizeof(detail_levels)); - terrain_width = patch->Width(); + terrain_width = patch->Width(); - loc = (p1 + p2) * 0.5; - loc.y = base; + loc = (p1 + p2) * 0.5; + loc.y = base; - radius = (float) (size * 0.75); - heights = new(__FILE__,__LINE__) float[MAX_VERTS]; + radius = (float) (size * 0.75); + heights = new(__FILE__,__LINE__) float[MAX_VERTS]; - float* pHeight = heights; - int tscale = rect.w / (PATCH_SIZE-1); - int i, j; + float* pHeight = heights; + int tscale = rect.w / (PATCH_SIZE-1); + int i, j; - for (i = 0; i < PATCH_SIZE; i++) { - int ty = rect.y + i * tscale; + for (i = 0; i < PATCH_SIZE; i++) { + int ty = rect.y + i * tscale; - if (ty < 0) - ty = 0; + if (ty < 0) + ty = 0; - if (ty > patch->Height()-1) - ty = patch->Height()-1; + if (ty > patch->Height()-1) + ty = patch->Height()-1; - for (j = 0; j < PATCH_SIZE; j++) { - int tx = rect.x + (PATCH_SIZE-1 - j) * tscale; + for (j = 0; j < PATCH_SIZE; j++) { + int tx = rect.x + (PATCH_SIZE-1 - j) * tscale; - if (tx < 0) - tx = 0; + if (tx < 0) + tx = 0; - if (tx > patch->Width()-1) - tx = patch->Width()-1; + if (tx > patch->Width()-1) + tx = patch->Width()-1; - int red = patch->GetColor(tx,ty).Red(); - float alt = (float) (red * mtnscale); + int red = patch->GetColor(tx,ty).Red(); + float alt = (float) (red * mtnscale); - if (alt < min_height) - min_height = alt; - if (alt > max_height) - max_height = alt; + if (alt < min_height) + min_height = alt; + if (alt > max_height) + max_height = alt; - if (terrain->WaterTexture() && red < 2) - alt = -5000.0f; + if (terrain->WaterTexture() && red < 2) + alt = -5000.0f; - *pHeight++ = alt; - } - } + *pHeight++ = alt; + } + } - Material* mtl = new(__FILE__,__LINE__) Material; - mtl->Ka = ColorValue(0.5f, 0.5f, 0.5f); - mtl->Kd = ColorValue(0.3f, 0.6f, 0.2f); - mtl->Ks = Color::Black; + Material* mtl = new(__FILE__,__LINE__) Material; + mtl->Ka = ColorValue(0.5f, 0.5f, 0.5f); + mtl->Kd = ColorValue(0.3f, 0.6f, 0.2f); + mtl->Ks = Color::Black; - mtl->tex_diffuse = terrain->Texture(); + mtl->tex_diffuse = terrain->Texture(); - materials.append(mtl); + materials.append(mtl); - List& layers = terrain->GetLayers(); - for (i = 0; i < layers.size(); i++) { - Bitmap* tex0 = layers.at(i)->GetTileTexture(); - Bitmap* tex1 = 0; - Bitmap* texd = layers.at(i)->GetDetailTexture(); + List& layers = terrain->GetLayers(); + for (i = 0; i < layers.size(); i++) { + Bitmap* tex0 = layers.at(i)->GetTileTexture(); + Bitmap* tex1 = 0; + Bitmap* texd = layers.at(i)->GetDetailTexture(); - if (i < layers.size()-1) - tex1 = layers.at(i+1)->GetTileTexture(); + if (i < layers.size()-1) + tex1 = layers.at(i+1)->GetTileTexture(); - if (!texd) - texd = terrain->DetailTexture(0); + if (!texd) + texd = terrain->DetailTexture(0); - mtl = new(__FILE__,__LINE__) Material; - mtl->Ka = ColorValue(0.5f, 0.5f, 0.5f); - mtl->Kd = ColorValue(0.3f, 0.6f, 0.2f); - mtl->Ks = Color::Black; + mtl = new(__FILE__,__LINE__) Material; + mtl->Ka = ColorValue(0.5f, 0.5f, 0.5f); + mtl->Kd = ColorValue(0.3f, 0.6f, 0.2f); + mtl->Ks = Color::Black; - if ((i & 1) != 0) { - mtl->tex_diffuse = tex1; - mtl->tex_alternate = tex0; - } - else { - mtl->tex_diffuse = tex0; - mtl->tex_alternate = tex1; - } + if ((i & 1) != 0) { + mtl->tex_diffuse = tex1; + mtl->tex_alternate = tex0; + } + else { + mtl->tex_diffuse = tex0; + mtl->tex_alternate = tex1; + } - mtl->tex_detail = texd; + mtl->tex_detail = texd; - materials.append(mtl); - } + materials.append(mtl); + } - for (i = 0; i <= max_detail; i++) - BuildDetailLevel(i); + for (i = 0; i <= max_detail; i++) + BuildDetailLevel(i); - model = detail_levels[1]; + model = detail_levels[1]; } // +--------------------------------------------------------------------+ TerrainPatch::TerrainPatch(Terrain* terr, - const Rect& r, - const Point& p1, - const Point& p2, - double sea_level) - : ndetail(0), terrain(terr), rect(r), water(0) +const Rect& r, +const Point& p1, +const Point& p2, +double sea_level) +: ndetail(0), terrain(terr), rect(r), water(0) { - luminous = true; // water is lit by the graphics engine - own_model = false; // manage the model lifetimes in this derived class + luminous = true; // water is lit by the graphics engine + own_model = false; // manage the model lifetimes in this derived class - max_detail = Terrain::DetailLevel(); - scale = fabs(p1.x - p2.x) / (PATCH_SIZE-1); - mtnscale = 0; - base = sea_level; - size = p2.x - p1.x; + max_detail = Terrain::DetailLevel(); + scale = fabs(p1.x - p2.x) / (PATCH_SIZE-1); + mtnscale = 0; + base = sea_level; + size = p2.x - p1.x; - ZeroMemory(detail_levels, sizeof(detail_levels)); + ZeroMemory(detail_levels, sizeof(detail_levels)); - terrain_width = 0; + terrain_width = 0; - loc = (p1 + p2) * 0.5; - loc.y = base; + loc = (p1 + p2) * 0.5; + loc.y = base; - radius = (float) (size * 0.75); - heights = new(__FILE__,__LINE__) float[MAX_VERTS]; + radius = (float) (size * 0.75); + heights = new(__FILE__,__LINE__) float[MAX_VERTS]; - float* pHeight = heights; - int i, j; + float* pHeight = heights; + int i, j; - for (i = 0; i < PATCH_SIZE; i++) { - for (j = 0; j < PATCH_SIZE; j++) { - *pHeight++ = (float) sea_level; - } - } + for (i = 0; i < PATCH_SIZE; i++) { + for (j = 0; j < PATCH_SIZE; j++) { + *pHeight++ = (float) sea_level; + } + } - Material* mtl = new(__FILE__,__LINE__) Material; - mtl->Ka = Color::Gray; - mtl->Kd = Color::White; - mtl->Ks = Color::White; - mtl->power = 30.0f; - mtl->shadow = false; - mtl->tex_diffuse = terrain->WaterTexture(); - //strcpy(mtl->shader, "WaterReflections"); - materials.append(mtl); + Material* mtl = new(__FILE__,__LINE__) Material; + mtl->Ka = Color::Gray; + mtl->Kd = Color::White; + mtl->Ks = Color::White; + mtl->power = 30.0f; + mtl->shadow = false; + mtl->tex_diffuse = terrain->WaterTexture(); + //strcpy(mtl->shader, "WaterReflections"); + materials.append(mtl); - water = terrain->GetWater(1); + water = terrain->GetWater(1); - for (i = 0; i <= max_detail; i++) - BuildDetailLevel(i); + for (i = 0; i <= max_detail; i++) + BuildDetailLevel(i); - model = detail_levels[1]; + model = detail_levels[1]; } // +--------------------------------------------------------------------+ TerrainPatch::~TerrainPatch() { - delete [] heights; + delete [] heights; - for (int i = 0; i < MAX_LOD; i++) { - Model* m = detail_levels[i]; + for (int i = 0; i < MAX_LOD; i++) { + Model* m = detail_levels[i]; - if (m) { - m->GetMaterials().clear(); - delete m; - } - } + if (m) { + m->GetMaterials().clear(); + delete m; + } + } - materials.destroy(); + materials.destroy(); } // +--------------------------------------------------------------------+ @@ -226,447 +226,447 @@ TerrainPatch::~TerrainPatch() void TerrainPatch::SetScales(double s, double m, double b) { - scale = s; - mtnscale = m; - base = b; + scale = s; + mtnscale = m; + base = b; } // +--------------------------------------------------------------------+ static int mcomp(const void* a, const void* b) { - Poly* pa = (Poly*) a; - Poly* pb = (Poly*) b; + Poly* pa = (Poly*) a; + Poly* pb = (Poly*) b; - if (pa->sortval == pb->sortval) - return 0; + if (pa->sortval == pb->sortval) + return 0; - if (pa->sortval < pb->sortval) - return 1; + if (pa->sortval < pb->sortval) + return 1; - return -1; + return -1; } static void bisect(VertexSet* vset, int v[4]) { - double d1 = fabs(vset->loc[ v[0] ].y - - vset->loc[ v[3] ].y); + double d1 = fabs(vset->loc[ v[0] ].y - + vset->loc[ v[3] ].y); - double d2 = fabs(vset->loc[ v[1] ].y - - vset->loc[ v[2] ].y); + double d2 = fabs(vset->loc[ v[1] ].y - + vset->loc[ v[2] ].y); - if (d2 < 0.7*d1) { - int odd[4] = { v[1], v[3], v[0], v[2] }; - for (int i = 0; i < 4; i++) - v[i] = odd[i]; - } + if (d2 < 0.7*d1) { + int odd[4] = { v[1], v[3], v[0], v[2] }; + for (int i = 0; i < 4; i++) + v[i] = odd[i]; + } } bool TerrainPatch::BuildDetailLevel(int level) { - int i, j; - - int detail_size = 1 << level; - int ds1 = detail_size+1; - - if (detail_size > PATCH_SIZE) - return false; - - Model* model = new(__FILE__,__LINE__) Model; - detail_levels[level] = model; - - model->SetLuminous(luminous); - model->SetDynamic(true); - - const int NUM_STRIPS = 4; - const int NUM_INDICES_TRI = 3; - const int NUM_INDICES_QUAD = 6; - - int nverts = ds1*ds1 + ds1*2*NUM_STRIPS; - int npolys = detail_size*detail_size*2; - int strip_len = detail_size; - int total = npolys + strip_len*NUM_STRIPS; - - if (water) { - nverts = ds1*ds1; - strip_len = 0; - total = npolys; - } - - Surface* s = new(__FILE__,__LINE__) Surface; - VertexSet* vset = 0; - - if (s) { - s->SetName("default"); - s->CreateVerts(nverts); - s->CreatePolys(total); - s->AddIndices(npolys*NUM_INDICES_TRI + strip_len*NUM_STRIPS*NUM_INDICES_QUAD); - - vset = s->GetVertexSet(); - if (!water) - vset->CreateAdditionalTexCoords(); - - ZeroMemory(vset->loc, nverts * sizeof(Vec3)); - ZeroMemory(vset->diffuse, nverts * sizeof(DWORD)); - ZeroMemory(vset->specular, nverts * sizeof(DWORD)); - ZeroMemory(vset->tu, nverts * sizeof(float)); - ZeroMemory(vset->tv, nverts * sizeof(float)); - if (!water) { - ZeroMemory(vset->tu1, nverts * sizeof(float)); - ZeroMemory(vset->tv1, nverts * sizeof(float)); - } - ZeroMemory(vset->rw, nverts * sizeof(float)); - - // initialize vertices - Vec3* pVert = vset->loc; - float* pTu = vset->tu; - float* pTv = vset->tv; - float* pTu1 = vset->tu1; - float* pTv1 = vset->tv1; - DWORD* pSpec = vset->specular; - - int dscale = (PATCH_SIZE-1)/detail_size; - double dt = 0.0625 / (ds1-1); // terrain texture scale - double dtt = 2.0000 / (ds1-1); // tile texture scale - double tu0 = (double) rect.x / rect.w / 16.0 + 1.0/16.0; - double tv0 = (double) rect.y / rect.h / 16.0; - - // surface verts - for (i = 0; i < ds1; i++) { - for (j = 0; j < ds1; j++) { - *pVert = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)), - (float) (heights[i*dscale*PATCH_SIZE + j*dscale]), - (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale))); - - if (level >= 2) { - *pTu++ = (float) (-j*dtt); - *pTv++ = (float) ( i*dtt); - - if (level >= 4 && !water) { - *pTu1++ = (float) (-j*dtt*3); - *pTv1++ = (float) ( i*dtt*3); - } - - *pSpec++ = BlendValue(pVert->y); - } - - else { - *pTu++ = (float) (tu0 - j*dt); - *pTv++ = (float) (tv0 + i*dt); - } - - pVert++; - } - } - - if (!water) { - // strip 1 & 2 verts - for (i = 0; i < ds1; i += detail_size) { - for (j = 0; j < ds1; j++) { - Vec3 vl = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)), - (float) (heights[i*dscale*PATCH_SIZE + j*dscale]), - (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale))); - - *pVert++ = vl; - - DWORD blend = 0; - - if (level >= 2) { - blend = BlendValue(vl.y); - - *pSpec++ = blend; - *pTu++ = (float) (-j*dtt); - *pTv++ = (float) ( i*dtt); - } - - else { - *pTu++ = (float) (tu0 - j*dt); - *pTv++ = (float) (tv0 + i*dt); - } - - vl.y = -5000.0f; - - *pVert++ = vl; - - if (level >= 2) { - *pSpec++ = blend; - *pTu++ = (float) (-j*dtt); - *pTv++ = (float) ( i*dtt); - } - - else { - *pTu++ = (float) (tu0 - j*dt); - *pTv++ = (float) (tv0 + i*dt); - } - } - } - - // strip 3 & 4 verts - for (j = 0; j < ds1; j += detail_size) { - for (i = 0; i < ds1; i++) { - Vec3 vl = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)), - (float) (heights[i*dscale*PATCH_SIZE + j*dscale]), - (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale))); - - *pVert++ = vl; - - DWORD blend = 0; - - if (level >= 2) { - blend = BlendValue(vl.y); - - *pSpec++ = blend; - *pTu++ = (float) (-j*dtt); - *pTv++ = (float) ( i*dtt); - } - - else { - *pTu++ = (float) (tu0 - j*dt); - *pTv++ = (float) (tv0 + i*dt); - } - - vl.y = -5000.0f; - - *pVert++ = vl; - - if (level >= 2) { - *pSpec++ = blend; - *pTu++ = (float) (-j*dtt); - *pTv++ = (float) ( i*dtt); - } - - else { - *pTu++ = (float) (tu0 - j*dt); - *pTv++ = (float) (tv0 + i*dt); - } - } - } - } - - Material* m = materials.first(); - - // initialize the polys - for (i = 0; i < npolys; i++) { - Poly* p = s->GetPolys() + i; - p->nverts = 3; - p->vertex_set = vset; - p->visible = 1; - p->sortval = 0; - p->material = m; - - if (level >= 2 && !water) { - p->material = materials.at(1); - p->sortval = 1; - } - } - - for (i = npolys; i < total; i++) { - Poly* p = s->GetPolys() + i; - p->nverts = 4; - p->vertex_set = vset; - p->visible = 1; - p->sortval = 0; - p->material = m; - } - - int index = 0; - - // build main patch polys: - for (i = 0; i < detail_size; i++) { - for (j = 0; j < detail_size; j++) { - int v[4] = { - (ds1 * (i ) + (j )), - (ds1 * (i ) + (j+1)), - (ds1 * (i+1) + (j )), - (ds1 * (i+1) + (j+1)) }; - - bisect(vset, v); - - // first triangle - Poly* p = s->GetPolys() + index++; - p->verts[0] = v[0]; - p->verts[1] = v[1]; - p->verts[2] = v[3]; - - if (level >= 2 && !water) { - int layer = CalcLayer(p) + 1; - p->material = materials.at(layer); - p->sortval = layer; - } - - // second triangle - p = s->GetPolys() + index++; - p->verts[0] = v[0]; - p->verts[1] = v[3]; - p->verts[2] = v[2]; - - if (level >= 2 && !water) { - int layer = CalcLayer(p) + 1; - p->material = materials.at(layer); - p->sortval = layer; - } - } - } - - // build vertical edge strip polys: - - if (!water) { - for (i = 0; i < NUM_STRIPS; i++) { - Poly* p = s->GetPolys() + npolys + i*strip_len; - int base_index = ds1*ds1 + ds1*2*i; - - for (j = 0; j < strip_len; j++) { - int v = base_index + j * 2; - p->nverts = 4; - - if (i == 1 || i == 2) { - p->verts[0] = v; - p->verts[1] = v+2; - p->verts[2] = v+3; - p->verts[3] = v+1; - } - - else { - p->verts[0] = v; - p->verts[1] = v+1; - p->verts[2] = v+3; - p->verts[3] = v+2; - } - - if (level >= 2) { - int layer = CalcLayer(p) + 1; - p->material = materials.at(layer); - p->sortval = layer; - } - - p++; - } - } - } - - // update the poly planes: - for (i = 0; i < total; i++) { - Poly* p = s->GetPolys() + i; - Plane& plane = p->plane; - WORD* v = p->verts; - - plane = Plane(vset->loc[v[0]] + loc, - vset->loc[v[1]] + loc, - vset->loc[v[2]] + loc); - } - - s->Normalize(); - - // create continguous segments for each material: - // sort the polys by material index: - qsort((void*) s->GetPolys(), s->NumPolys(), sizeof(Poly), mcomp); - - // then assign them to cohesive segments: - Segment* segment = 0; - Poly* spolys = s->GetPolys(); - - for (int n = 0; n < s->NumPolys(); n++) { - if (segment && segment->material == spolys[n].material) { - segment->npolys++; - } - else { - segment = 0; - } - - if (!segment) { - segment = new(__FILE__,__LINE__) Segment; - - segment->npolys = 1; - segment->polys = &spolys[n]; - segment->material = segment->polys->material; - segment->model = model; - - s->GetSegments().append(segment); - } - } - - Solid::EnableCollision(false); - model->AddSurface(s); - Solid::EnableCollision(true); - - // copy vertex normals: - const Vec3B* tnorms = terrain->Normals(); - - for (i = 0; i < ds1; i++) { - for (j = 0; j < ds1; j++) { - - if (water) { - vset->nrm[i*ds1+j] = Point(0,1,0); - } - - // blend adjacent normals: - else if (dscale > 1) { - Point normal; - - // but don't blend more than 16 normals per vertex: - int step = 1; - if (dscale > 4) - step = dscale / 4; - - for (int dy = -dscale/2; dy < dscale/2; dy += step) { - for (int dx = -dscale/2; dx < dscale/2; dx += step) { - int ix = rect.x + (ds1-1-j)*dscale + dx; - int iy = rect.y + i*dscale + dy; - - if (ix < 0) ix = 0; - if (ix > terrain_width-1) ix = terrain_width-1; - if (iy < 0) iy = 0; - if (iy > terrain_width-1) iy = terrain_width-1; - - Vec3B vbn = tnorms[iy*terrain_width + ix]; - normal += Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0); - } - } - - normal.Normalize(); - vset->nrm[i*ds1+j] = normal; - } - - // just copy the one normal: - else { - Vec3B vbn = tnorms[(rect.y + i*dscale)*terrain_width + (rect.x + (ds1-1-j) * dscale)]; - Point normal = Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0); - vset->nrm[i*ds1+j] = normal; - } - } - } - - if (!water) { - pVert = &vset->nrm[ds1*ds1]; - - // strip 1 & 2 verts - for (i = 0; i < ds1; i += detail_size) { - for (j = 0; j < ds1; j++) { - Vec3 vn = vset->nrm[i*ds1 + j]; - - *pVert++ = vn; - *pVert++ = vn; - } - } - - // strip 3 & 4 verts - for (j = 0; j < ds1; j += detail_size) { - for (i = 0; i < ds1; i++) { - Vec3 vn = vset->nrm[i*ds1 + j]; - - *pVert++ = vn; - *pVert++ = vn; - } - } - } - } - - if (level > max_detail) - max_detail = level; - - return true; + int i, j; + + int detail_size = 1 << level; + int ds1 = detail_size+1; + + if (detail_size > PATCH_SIZE) + return false; + + Model* model = new(__FILE__,__LINE__) Model; + detail_levels[level] = model; + + model->SetLuminous(luminous); + model->SetDynamic(true); + + const int NUM_STRIPS = 4; + const int NUM_INDICES_TRI = 3; + const int NUM_INDICES_QUAD = 6; + + int nverts = ds1*ds1 + ds1*2*NUM_STRIPS; + int npolys = detail_size*detail_size*2; + int strip_len = detail_size; + int total = npolys + strip_len*NUM_STRIPS; + + if (water) { + nverts = ds1*ds1; + strip_len = 0; + total = npolys; + } + + Surface* s = new(__FILE__,__LINE__) Surface; + VertexSet* vset = 0; + + if (s) { + s->SetName("default"); + s->CreateVerts(nverts); + s->CreatePolys(total); + s->AddIndices(npolys*NUM_INDICES_TRI + strip_len*NUM_STRIPS*NUM_INDICES_QUAD); + + vset = s->GetVertexSet(); + if (!water) + vset->CreateAdditionalTexCoords(); + + ZeroMemory(vset->loc, nverts * sizeof(Vec3)); + ZeroMemory(vset->diffuse, nverts * sizeof(DWORD)); + ZeroMemory(vset->specular, nverts * sizeof(DWORD)); + ZeroMemory(vset->tu, nverts * sizeof(float)); + ZeroMemory(vset->tv, nverts * sizeof(float)); + if (!water) { + ZeroMemory(vset->tu1, nverts * sizeof(float)); + ZeroMemory(vset->tv1, nverts * sizeof(float)); + } + ZeroMemory(vset->rw, nverts * sizeof(float)); + + // initialize vertices + Vec3* pVert = vset->loc; + float* pTu = vset->tu; + float* pTv = vset->tv; + float* pTu1 = vset->tu1; + float* pTv1 = vset->tv1; + DWORD* pSpec = vset->specular; + + int dscale = (PATCH_SIZE-1)/detail_size; + double dt = 0.0625 / (ds1-1); // terrain texture scale + double dtt = 2.0000 / (ds1-1); // tile texture scale + double tu0 = (double) rect.x / rect.w / 16.0 + 1.0/16.0; + double tv0 = (double) rect.y / rect.h / 16.0; + + // surface verts + for (i = 0; i < ds1; i++) { + for (j = 0; j < ds1; j++) { + *pVert = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)), + (float) (heights[i*dscale*PATCH_SIZE + j*dscale]), + (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale))); + + if (level >= 2) { + *pTu++ = (float) (-j*dtt); + *pTv++ = (float) ( i*dtt); + + if (level >= 4 && !water) { + *pTu1++ = (float) (-j*dtt*3); + *pTv1++ = (float) ( i*dtt*3); + } + + *pSpec++ = BlendValue(pVert->y); + } + + else { + *pTu++ = (float) (tu0 - j*dt); + *pTv++ = (float) (tv0 + i*dt); + } + + pVert++; + } + } + + if (!water) { + // strip 1 & 2 verts + for (i = 0; i < ds1; i += detail_size) { + for (j = 0; j < ds1; j++) { + Vec3 vl = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)), + (float) (heights[i*dscale*PATCH_SIZE + j*dscale]), + (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale))); + + *pVert++ = vl; + + DWORD blend = 0; + + if (level >= 2) { + blend = BlendValue(vl.y); + + *pSpec++ = blend; + *pTu++ = (float) (-j*dtt); + *pTv++ = (float) ( i*dtt); + } + + else { + *pTu++ = (float) (tu0 - j*dt); + *pTv++ = (float) (tv0 + i*dt); + } + + vl.y = -5000.0f; + + *pVert++ = vl; + + if (level >= 2) { + *pSpec++ = blend; + *pTu++ = (float) (-j*dtt); + *pTv++ = (float) ( i*dtt); + } + + else { + *pTu++ = (float) (tu0 - j*dt); + *pTv++ = (float) (tv0 + i*dt); + } + } + } + + // strip 3 & 4 verts + for (j = 0; j < ds1; j += detail_size) { + for (i = 0; i < ds1; i++) { + Vec3 vl = Vec3((float) (j* scale * dscale - (HALF_PATCH_SIZE*scale)), + (float) (heights[i*dscale*PATCH_SIZE + j*dscale]), + (float) (i* scale * dscale - (HALF_PATCH_SIZE*scale))); + + *pVert++ = vl; + + DWORD blend = 0; + + if (level >= 2) { + blend = BlendValue(vl.y); + + *pSpec++ = blend; + *pTu++ = (float) (-j*dtt); + *pTv++ = (float) ( i*dtt); + } + + else { + *pTu++ = (float) (tu0 - j*dt); + *pTv++ = (float) (tv0 + i*dt); + } + + vl.y = -5000.0f; + + *pVert++ = vl; + + if (level >= 2) { + *pSpec++ = blend; + *pTu++ = (float) (-j*dtt); + *pTv++ = (float) ( i*dtt); + } + + else { + *pTu++ = (float) (tu0 - j*dt); + *pTv++ = (float) (tv0 + i*dt); + } + } + } + } + + Material* m = materials.first(); + + // initialize the polys + for (i = 0; i < npolys; i++) { + Poly* p = s->GetPolys() + i; + p->nverts = 3; + p->vertex_set = vset; + p->visible = 1; + p->sortval = 0; + p->material = m; + + if (level >= 2 && !water) { + p->material = materials.at(1); + p->sortval = 1; + } + } + + for (i = npolys; i < total; i++) { + Poly* p = s->GetPolys() + i; + p->nverts = 4; + p->vertex_set = vset; + p->visible = 1; + p->sortval = 0; + p->material = m; + } + + int index = 0; + + // build main patch polys: + for (i = 0; i < detail_size; i++) { + for (j = 0; j < detail_size; j++) { + int v[4] = { + (ds1 * (i ) + (j )), + (ds1 * (i ) + (j+1)), + (ds1 * (i+1) + (j )), + (ds1 * (i+1) + (j+1)) }; + + bisect(vset, v); + + // first triangle + Poly* p = s->GetPolys() + index++; + p->verts[0] = v[0]; + p->verts[1] = v[1]; + p->verts[2] = v[3]; + + if (level >= 2 && !water) { + int layer = CalcLayer(p) + 1; + p->material = materials.at(layer); + p->sortval = layer; + } + + // second triangle + p = s->GetPolys() + index++; + p->verts[0] = v[0]; + p->verts[1] = v[3]; + p->verts[2] = v[2]; + + if (level >= 2 && !water) { + int layer = CalcLayer(p) + 1; + p->material = materials.at(layer); + p->sortval = layer; + } + } + } + + // build vertical edge strip polys: + + if (!water) { + for (i = 0; i < NUM_STRIPS; i++) { + Poly* p = s->GetPolys() + npolys + i*strip_len; + int base_index = ds1*ds1 + ds1*2*i; + + for (j = 0; j < strip_len; j++) { + int v = base_index + j * 2; + p->nverts = 4; + + if (i == 1 || i == 2) { + p->verts[0] = v; + p->verts[1] = v+2; + p->verts[2] = v+3; + p->verts[3] = v+1; + } + + else { + p->verts[0] = v; + p->verts[1] = v+1; + p->verts[2] = v+3; + p->verts[3] = v+2; + } + + if (level >= 2) { + int layer = CalcLayer(p) + 1; + p->material = materials.at(layer); + p->sortval = layer; + } + + p++; + } + } + } + + // update the poly planes: + for (i = 0; i < total; i++) { + Poly* p = s->GetPolys() + i; + Plane& plane = p->plane; + WORD* v = p->verts; + + plane = Plane(vset->loc[v[0]] + loc, + vset->loc[v[1]] + loc, + vset->loc[v[2]] + loc); + } + + s->Normalize(); + + // create continguous segments for each material: + // sort the polys by material index: + qsort((void*) s->GetPolys(), s->NumPolys(), sizeof(Poly), mcomp); + + // then assign them to cohesive segments: + Segment* segment = 0; + Poly* spolys = s->GetPolys(); + + for (int n = 0; n < s->NumPolys(); n++) { + if (segment && segment->material == spolys[n].material) { + segment->npolys++; + } + else { + segment = 0; + } + + if (!segment) { + segment = new(__FILE__,__LINE__) Segment; + + segment->npolys = 1; + segment->polys = &spolys[n]; + segment->material = segment->polys->material; + segment->model = model; + + s->GetSegments().append(segment); + } + } + + Solid::EnableCollision(false); + model->AddSurface(s); + Solid::EnableCollision(true); + + // copy vertex normals: + const Vec3B* tnorms = terrain->Normals(); + + for (i = 0; i < ds1; i++) { + for (j = 0; j < ds1; j++) { + + if (water) { + vset->nrm[i*ds1+j] = Point(0,1,0); + } + + // blend adjacent normals: + else if (dscale > 1) { + Point normal; + + // but don't blend more than 16 normals per vertex: + int step = 1; + if (dscale > 4) + step = dscale / 4; + + for (int dy = -dscale/2; dy < dscale/2; dy += step) { + for (int dx = -dscale/2; dx < dscale/2; dx += step) { + int ix = rect.x + (ds1-1-j)*dscale + dx; + int iy = rect.y + i*dscale + dy; + + if (ix < 0) ix = 0; + if (ix > terrain_width-1) ix = terrain_width-1; + if (iy < 0) iy = 0; + if (iy > terrain_width-1) iy = terrain_width-1; + + Vec3B vbn = tnorms[iy*terrain_width + ix]; + normal += Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0); + } + } + + normal.Normalize(); + vset->nrm[i*ds1+j] = normal; + } + + // just copy the one normal: + else { + Vec3B vbn = tnorms[(rect.y + i*dscale)*terrain_width + (rect.x + (ds1-1-j) * dscale)]; + Point normal = Point((128-vbn.x)/127.0, (vbn.z-128)/127.0, (vbn.y-128)/127.0); + vset->nrm[i*ds1+j] = normal; + } + } + } + + if (!water) { + pVert = &vset->nrm[ds1*ds1]; + + // strip 1 & 2 verts + for (i = 0; i < ds1; i += detail_size) { + for (j = 0; j < ds1; j++) { + Vec3 vn = vset->nrm[i*ds1 + j]; + + *pVert++ = vn; + *pVert++ = vn; + } + } + + // strip 3 & 4 verts + for (j = 0; j < ds1; j += detail_size) { + for (i = 0; i < ds1; i++) { + Vec3 vn = vset->nrm[i*ds1 + j]; + + *pVert++ = vn; + *pVert++ = vn; + } + } + } + } + + if (level > max_detail) + max_detail = level; + + return true; } // +--------------------------------------------------------------------+ @@ -674,65 +674,65 @@ TerrainPatch::BuildDetailLevel(int level) DWORD TerrainPatch::BlendValue(double y) { - if (terrain && y >= 0 && !water) { - // find the proper layer: - for (int i = 0; i < terrain->GetLayers().size(); i++) { - TerrainLayer* layer = terrain->GetLayers().at(i); + if (terrain && y >= 0 && !water) { + // find the proper layer: + for (int i = 0; i < terrain->GetLayers().size(); i++) { + TerrainLayer* layer = terrain->GetLayers().at(i); - if (y >= layer->GetMinHeight() && y < layer->GetMaxHeight()) { - double scale = (y-layer->GetMinHeight()) / (layer->GetMaxHeight()-layer->GetMinHeight()); + if (y >= layer->GetMinHeight() && y < layer->GetMaxHeight()) { + double scale = (y-layer->GetMinHeight()) / (layer->GetMaxHeight()-layer->GetMinHeight()); - if (scale < 0.2) - scale = 0; - else if (scale > 0.8) - scale = 1; - else - scale = (scale - 0.2) / 0.6; + if (scale < 0.2) + scale = 0; + else if (scale > 0.8) + scale = 1; + else + scale = (scale - 0.2) / 0.6; - if ((i & 1) == 0) { - scale = 1 - scale; - } + if ((i & 1) == 0) { + scale = 1 - scale; + } - DWORD val = (DWORD) (scale*255); + DWORD val = (DWORD) (scale*255); - return val << 24; - } - } - } + return val << 24; + } + } + } - return 0; + return 0; } int TerrainPatch::CalcLayer(Poly* poly) { - if (terrain && poly) { - if (water) - return 0; + if (terrain && poly) { + if (water) + return 0; - double y = 1e6; + double y = 1e6; - for (int i = 0; i < poly->nverts; i++) { - double h = poly->vertex_set->loc[ poly->verts[i] ].y; + for (int i = 0; i < poly->nverts; i++) { + double h = poly->vertex_set->loc[ poly->verts[i] ].y; - if (h >= 0 && h < y) { - y = h; - } - } + if (h >= 0 && h < y) { + y = h; + } + } - if (y <= terrain->GetLayers().first()->GetMinHeight()) - return 0; + if (y <= terrain->GetLayers().first()->GetMinHeight()) + return 0; - for (int i = 0; i < terrain->GetLayers().size(); i++) { - TerrainLayer* layer = terrain->GetLayers().at(i); + for (int i = 0; i < terrain->GetLayers().size(); i++) { + TerrainLayer* layer = terrain->GetLayers().at(i); - if (y >= layer->GetMinHeight() && y < layer->GetMaxHeight()) { - return i; - } - } - } + if (y >= layer->GetMinHeight() && y < layer->GetMaxHeight()) { + return i; + } + } + } - return -1; + return -1; } // +--------------------------------------------------------------------+ @@ -740,16 +740,16 @@ TerrainPatch::CalcLayer(Poly* poly) void TerrainPatch::UpdateSurfaceWaves(Vec3& eyePos) { - if (water && model && model->NumVerts() > 1) { - Surface* s = model->GetSurfaces().first(); - if (s) { - VertexSet* vset = s->GetVertexSet(); - for (int i = 0; i < vset->nverts; i++) - vset->loc[i].y = 0.0f; - - water->UpdateSurface(eyePos, vset); - } - } + if (water && model && model->NumVerts() > 1) { + Surface* s = model->GetSurfaces().first(); + if (s) { + VertexSet* vset = s->GetVertexSet(); + for (int i = 0; i < vset->nverts; i++) + vset->loc[i].y = 0.0f; + + water->UpdateSurface(eyePos, vset); + } + } } // +--------------------------------------------------------------------+ @@ -757,7 +757,7 @@ TerrainPatch::UpdateSurfaceWaves(Vec3& eyePos) int TerrainPatch::CollidesWith(Graphic& o) { - return 0; + return 0; } // +--------------------------------------------------------------------+ @@ -765,38 +765,38 @@ TerrainPatch::CollidesWith(Graphic& o) void TerrainPatch::SelectDetail(Projector* projector) { - // This is where all the work is done, - // Delegate to the overall terrain to - // compute a detail level for every patch: + // This is where all the work is done, + // Delegate to the overall terrain to + // compute a detail level for every patch: - if (terrain) { - terrain->SelectDetail(projector); - } + if (terrain) { + terrain->SelectDetail(projector); + } - // Build detail levels on demand: + // Build detail levels on demand: - if (detail_levels[ndetail] == 0) - BuildDetailLevel(ndetail); + if (detail_levels[ndetail] == 0) + BuildDetailLevel(ndetail); } void TerrainPatch::SetDetailLevel(int nd) { - if (nd >= 0 && nd <= max_detail) { - if (ndetail != nd) - DeletePrivateData(); + if (nd >= 0 && nd <= max_detail) { + if (ndetail != nd) + DeletePrivateData(); - ndetail = nd; + ndetail = nd; - // build detail levels on demand: - if (detail_levels[ndetail] == 0) - BuildDetailLevel(ndetail); + // build detail levels on demand: + if (detail_levels[ndetail] == 0) + BuildDetailLevel(ndetail); - model = detail_levels[ndetail]; + model = detail_levels[ndetail]; - if (water) - water = terrain->GetWater(ndetail); - } + if (water) + water = terrain->GetWater(ndetail); + } } // +--------------------------------------------------------------------+ @@ -804,80 +804,80 @@ TerrainPatch::SetDetailLevel(int nd) void TerrainPatch::Illuminate(Color ambient, List& lights) { - if (!model || model->NumVerts() < 1) return; - Surface* s = model->GetSurfaces().first(); - if (!s) return; - - illuminating = true; - - // clear the solid lights to ambient: - VertexSet* vset = s->GetVertexSet(); - int nverts = vset->nverts; - DWORD aval = ambient.Value(); - - for (int i = 0; i < nverts; i++) { - vset->diffuse[i] = aval; - } - - TerrainRegion* trgn = terrain->GetRegion(); - bool eclipsed = false; - bool first = terrain->IsFirstPatch(this); - - if (trgn && !first) { - eclipsed = trgn->IsEclipsed(); - } - - // for sun and back lights: - ListIter iter = lights; - while (++iter) { - Light* light = iter.value(); - - if (!light->IsDirectional()) // only do sun and - continue; // back lights - - if (light->CastsShadow() && first) { - eclipsed = light->Location().y < -100 || // has sun set, or - - scene->IsLightObscured(vset->loc[0], // is sun in eclipse - light->Location(), // by orbital body - radius); // such as a moon? - } - - if (!light->CastsShadow() || !eclipsed) { - Vec3 vl = light->Location(); - vl.Normalize(); - - for (int i = 0; i < nverts; i++) { - Vec3& nrm = vset->nrm[i]; - double val = 0; - double gain = vl * nrm; - - if (gain > 0) { - val = light->Intensity() * (0.85 * gain); - - if (val > 1) - val = 1; - } - - if (val > 0.01) - vset->diffuse[i] = ((light->GetColor().dim(val)) + vset->diffuse[i]).Value(); - } - } - } - - // combine blend weights: - if (ndetail >= 2) { - for (int i = 0; i < nverts; i++) { - vset->diffuse[i] = vset->specular[i] | (vset->diffuse[i] & 0x00ffffff); - } - } - - if (trgn && first) { - trgn->SetEclipsed(eclipsed); - } - - InvalidateSurfaceData(); - illuminating = false; + if (!model || model->NumVerts() < 1) return; + Surface* s = model->GetSurfaces().first(); + if (!s) return; + + illuminating = true; + + // clear the solid lights to ambient: + VertexSet* vset = s->GetVertexSet(); + int nverts = vset->nverts; + DWORD aval = ambient.Value(); + + for (int i = 0; i < nverts; i++) { + vset->diffuse[i] = aval; + } + + TerrainRegion* trgn = terrain->GetRegion(); + bool eclipsed = false; + bool first = terrain->IsFirstPatch(this); + + if (trgn && !first) { + eclipsed = trgn->IsEclipsed(); + } + + // for sun and back lights: + ListIter iter = lights; + while (++iter) { + Light* light = iter.value(); + + if (!light->IsDirectional()) // only do sun and + continue; // back lights + + if (light->CastsShadow() && first) { + eclipsed = light->Location().y < -100 || // has sun set, or + + scene->IsLightObscured(vset->loc[0], // is sun in eclipse + light->Location(), // by orbital body + radius); // such as a moon? + } + + if (!light->CastsShadow() || !eclipsed) { + Vec3 vl = light->Location(); + vl.Normalize(); + + for (int i = 0; i < nverts; i++) { + Vec3& nrm = vset->nrm[i]; + double val = 0; + double gain = vl * nrm; + + if (gain > 0) { + val = light->Intensity() * (0.85 * gain); + + if (val > 1) + val = 1; + } + + if (val > 0.01) + vset->diffuse[i] = ((light->GetColor().dim(val)) + vset->diffuse[i]).Value(); + } + } + } + + // combine blend weights: + if (ndetail >= 2) { + for (int i = 0; i < nverts; i++) { + vset->diffuse[i] = vset->specular[i] | (vset->diffuse[i] & 0x00ffffff); + } + } + + if (trgn && first) { + trgn->SetEclipsed(eclipsed); + } + + InvalidateSurfaceData(); + illuminating = false; } // +--------------------------------------------------------------------+ @@ -885,83 +885,83 @@ TerrainPatch::Illuminate(Color ambient, List& lights) void TerrainPatch::Render(Video* video, DWORD flags) { - if (max_height < 0) - return; - - if (flags & RENDER_ADDITIVE) - return; - - if (!model) - model = detail_levels[0]; - - if (scene) { - /*** - *** TWO PASS LIGHTING FOR TERRAIN SHADOWS DOESN'T - *** WORK - IT MESSES UP THE HARDWARE FOG CALCS - *** - *** PLUS, IT'S INCREDIBLY SLOW!!! - ***/ - - if ((flags & RENDER_ADD_LIGHT) != 0) - return; - - if (water) { - UpdateSurfaceWaves(Vec3(0,0,0)); - Illuminate(scene->Ambient(), scene->Lights()); - } - else { - Illuminate(scene->Ambient(), scene->Lights()); - } - } - else { - if ((flags & RENDER_ADD_LIGHT) != 0) - return; - } - - Bitmap* details[16]; - ZeroMemory(details, sizeof(details)); - - if (ndetail < 3) { - for (int i = 0; i < 16 && i < materials.size(); i++) { - Material* mtl = materials[i]; - - if (mtl->tex_detail) { - details[i] = mtl->tex_detail; - mtl->tex_detail = 0; - } - } - } - - double visibility = terrain->GetRegion()->GetWeather().Visibility(); - FLOAT fog_density = (FLOAT) (terrain->GetRegion()->FogDensity() * 2.5e-5 * 1/visibility); - - video->SetRenderState(Video::LIGHTING_ENABLE, false); - video->SetRenderState(Video::SPECULAR_ENABLE, false); //water != 0); - video->SetRenderState(Video::FOG_ENABLE, true); - video->SetRenderState(Video::FOG_COLOR, terrain->GetRegion()->FogColor().Value()); - video->SetRenderState(Video::FOG_DENSITY, *((DWORD*) &fog_density)); - - // Too bad this doesn't work right. But it makes the - // ground mostly disappear. :-( - // - //video->SetRenderState(Video::Z_BIAS, -2); - - Solid::Render(video, flags); - - video->SetRenderState(Video::LIGHTING_ENABLE, true); - video->SetRenderState(Video::SPECULAR_ENABLE, true); - video->SetRenderState(Video::FOG_ENABLE, false); - //video->SetRenderState(Video::Z_BIAS, 0); - - if (ndetail < 3) { - for (int i = 0; i < 16 && i < materials.size(); i++) { - Material* mtl = materials[i]; - - if (details[i] && !mtl->tex_detail) { - mtl->tex_detail = details[i]; - } - } - } + if (max_height < 0) + return; + + if (flags & RENDER_ADDITIVE) + return; + + if (!model) + model = detail_levels[0]; + + if (scene) { + /*** + *** TWO PASS LIGHTING FOR TERRAIN SHADOWS DOESN'T + *** WORK - IT MESSES UP THE HARDWARE FOG CALCS + *** + *** PLUS, IT'S INCREDIBLY SLOW!!! + ***/ + + if ((flags & RENDER_ADD_LIGHT) != 0) + return; + + if (water) { + UpdateSurfaceWaves(Vec3(0,0,0)); + Illuminate(scene->Ambient(), scene->Lights()); + } + else { + Illuminate(scene->Ambient(), scene->Lights()); + } + } + else { + if ((flags & RENDER_ADD_LIGHT) != 0) + return; + } + + Bitmap* details[16]; + ZeroMemory(details, sizeof(details)); + + if (ndetail < 3) { + for (int i = 0; i < 16 && i < materials.size(); i++) { + Material* mtl = materials[i]; + + if (mtl->tex_detail) { + details[i] = mtl->tex_detail; + mtl->tex_detail = 0; + } + } + } + + double visibility = terrain->GetRegion()->GetWeather().Visibility(); + FLOAT fog_density = (FLOAT) (terrain->GetRegion()->FogDensity() * 2.5e-5 * 1/visibility); + + video->SetRenderState(Video::LIGHTING_ENABLE, false); + video->SetRenderState(Video::SPECULAR_ENABLE, false); //water != 0); + video->SetRenderState(Video::FOG_ENABLE, true); + video->SetRenderState(Video::FOG_COLOR, terrain->GetRegion()->FogColor().Value()); + video->SetRenderState(Video::FOG_DENSITY, *((DWORD*) &fog_density)); + + // Too bad this doesn't work right. But it makes the + // ground mostly disappear. :-( + // + //video->SetRenderState(Video::Z_BIAS, -2); + + Solid::Render(video, flags); + + video->SetRenderState(Video::LIGHTING_ENABLE, true); + video->SetRenderState(Video::SPECULAR_ENABLE, true); + video->SetRenderState(Video::FOG_ENABLE, false); + //video->SetRenderState(Video::Z_BIAS, 0); + + if (ndetail < 3) { + for (int i = 0; i < 16 && i < materials.size(); i++) { + Material* mtl = materials[i]; + + if (details[i] && !mtl->tex_detail) { + mtl->tex_detail = details[i]; + } + } + } } // +--------------------------------------------------------------------+ @@ -969,101 +969,101 @@ TerrainPatch::Render(Video* video, DWORD flags) int TerrainPatch::CheckRayIntersection(Point obj_pos, Point dir, double len, Point& ipt, bool ttpas) { - Point light_pos = obj_pos + dir * len; - int impact = light_pos.y < -100; + Point light_pos = obj_pos + dir * len; + int impact = light_pos.y < -100; - // Special case for illumination - - // just check if sun is above or below the horizon: + // Special case for illumination - + // just check if sun is above or below the horizon: - if (illuminating || impact) { - return impact; - } + if (illuminating || impact) { + return impact; + } - if (obj_pos.x != 0 || obj_pos.y != 0 || obj_pos.z != 0) { - return impact; - } + if (obj_pos.x != 0 || obj_pos.y != 0 || obj_pos.z != 0) { + return impact; + } - // the rest of this code is only used for eclipsing - // the solar lens flare: + // the rest of this code is only used for eclipsing + // the solar lens flare: - // check right angle spherical distance: - Point d0 = loc; - Point d1 = d0.cross(dir); - double dlen = d1.length(); // distance of point from line - - if (dlen > radius) // clean miss - return 0; // (no impact) + // check right angle spherical distance: + Point d0 = loc; + Point d1 = d0.cross(dir); + double dlen = d1.length(); // distance of point from line - // make sure some part of this patch falls between - // the camera and the sun: + if (dlen > radius) // clean miss + return 0; // (no impact) - Point closest = loc + dir * radius; + // make sure some part of this patch falls between + // the camera and the sun: - if (closest * dir < 0) - return 0; + Point closest = loc + dir * radius; - // probable hit at this point... - // test for polygon intersection: - if (!model) - return 0; + if (closest * dir < 0) + return 0; - Surface* s = model->GetSurfaces().first(); + // probable hit at this point... + // test for polygon intersection: + if (!model) + return 0; - if (!s) - return 0; + Surface* s = model->GetSurfaces().first(); + if (!s) + return 0; - // transform ray into object space: - Matrix xform(Orientation()); - Vec3 tmp = dir; + // transform ray into object space: + Matrix xform(Orientation()); - dir.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2)); - dir.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2)); - dir.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2)); + Vec3 tmp = dir; - tmp = obj_pos-loc; + dir.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2)); + dir.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2)); + dir.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2)); - obj_pos.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2)); - obj_pos.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2)); - obj_pos.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2)); - - double min = 2 * len; + tmp = obj_pos-loc; - // check each polygon: - Poly* p = s->GetPolys(); + obj_pos.x = tmp * Vec3(xform(0,0), xform(0,1), xform(0,2)); + obj_pos.y = tmp * Vec3(xform(1,0), xform(1,1), xform(1,2)); + obj_pos.z = tmp * Vec3(xform(2,0), xform(2,1), xform(2,2)); - for (int i = 0; i < s->NumPolys(); i++) { - Point v = p->plane.normal; - double d = p->plane.distance; + double min = 2 * len; - double denom = dir*v; + // check each polygon: + Poly* p = s->GetPolys(); - if (denom < -1.0e-5) { - Point P = v * d; - double ilen = ((P-obj_pos)*v)/denom; + for (int i = 0; i < s->NumPolys(); i++) { + Point v = p->plane.normal; + double d = p->plane.distance; - if (ilen > 0 && ilen < min) { - Point intersect = obj_pos + dir * ilen; + double denom = dir*v; - if (p->Contains(intersect)) { - ipt = intersect; - min = ilen; - impact = 1; - } - } - } + if (denom < -1.0e-5) { + Point P = v * d; + double ilen = ((P-obj_pos)*v)/denom; - p++; - } + if (ilen > 0 && ilen < min) { + Point intersect = obj_pos + dir * ilen; - // xform impact point back into world coordinates: + if (p->Contains(intersect)) { + ipt = intersect; + min = ilen; + impact = 1; + } + } + } - if (impact) { - ipt = (ipt * Orientation()) + loc; - } + p++; + } - return impact; + // xform impact point back into world coordinates: + + if (impact) { + ipt = (ipt * Orientation()) + loc; + } + + return impact; } // +--------------------------------------------------------------------+ @@ -1071,43 +1071,43 @@ TerrainPatch::CheckRayIntersection(Point obj_pos, Point dir, double len, Point& double TerrainPatch::Height(double x, double z) const { - if (water) return base; + if (water) return base; - double height = 0; + double height = 0; - x /= scale; - z /= scale; + x /= scale; + z /= scale; - int x0 = (int) x; - int z0 = (int) z; + int x0 = (int) x; + int z0 = (int) z; - if (x0 >= 0 && x0 < PATCH_SIZE && z0 >= 0 && z0 < PATCH_SIZE) { - double dx = x-x0; - double dz = z-z0; + if (x0 >= 0 && x0 < PATCH_SIZE && z0 >= 0 && z0 < PATCH_SIZE) { + double dx = x-x0; + double dz = z-z0; - double h[4]; + double h[4]; - h[0] = heights[(z0*PATCH_SIZE + x0)]; - h[1] = heights[((z0+1)*PATCH_SIZE + x0)]; - h[2] = heights[(z0*PATCH_SIZE + x0+1)]; - h[3] = heights[((z0+1)*PATCH_SIZE + x0+1)]; + h[0] = heights[(z0*PATCH_SIZE + x0)]; + h[1] = heights[((z0+1)*PATCH_SIZE + x0)]; + h[2] = heights[(z0*PATCH_SIZE + x0+1)]; + h[3] = heights[((z0+1)*PATCH_SIZE + x0+1)]; - // if level, just return height of one vertex: - if (h[0] == h[1] && h[1] == h[2] && h[2] == h[3]) { - height = h[0]; - } + // if level, just return height of one vertex: + if (h[0] == h[1] && h[1] == h[2] && h[2] == h[3]) { + height = h[0]; + } - // if sloped, interpolate between vertex heights: - else { - double hl = h[0]*(1-dz) + h[1]*dz; - double hr = h[2]*(1-dz) + h[3]*dz; + // if sloped, interpolate between vertex heights: + else { + double hl = h[0]*(1-dz) + h[1]*dz; + double hr = h[2]*(1-dz) + h[3]*dz; - height = hl*(1-dx) + hr*dx + 5; // fudge - } - } + height = hl*(1-dx) + hr*dx + 5; // fudge + } + } - if (height < 0) - height = 0; + if (height < 0) + height = 0; - return height; + return height; } -- cgit v1.1