00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00040 #include <string.h>
00041 #include "omicron/internal.h"
00042
00043 #include "omicron/render.h"
00044 #include "omicron/landscape.h"
00045 #include "omicron/array.h"
00046 #include "omicron/image.h"
00047 #include "omicron/texture.h"
00048
00049
00050
00051
00052
00053
00054
00055 landscape_c::landscape_c()
00056 {
00057 nodes = NULL;
00058 shaders = NULL;
00059 deinit();
00060 }
00061
00062 landscape_c::~landscape_c()
00063 {
00064 AssertThis;
00065
00066 deinit();
00067 }
00068
00069 void landscape_c::deinit()
00070 {
00071 SafeArrayDelete(nodes);
00072 SafeDelete(shaders);
00073
00074 width =
00075 height = 0;
00076 shaders = NULL;
00077 nodes = NULL;
00078 init = false;
00079
00080 pos.set ( 0, 0, 0 );
00081 scale.set ( 1, 1, 1 );
00082 }
00083
00084
00085
00086
00087 void landscape_c::create
00088 (
00089 ulong _width,
00090 ulong _height
00091 )
00092 {
00093
00094 deinit();
00095
00096
00097 width = _width;
00098 height = _height;
00099
00100
00101 nodes = new node_s[width*height];
00102
00103
00104 nodes[0].value = 0;
00105
00106 ulong i;
00107
00108 for (i=0; i<4; i++)
00109 {
00110 vec3_c(0,0,1).copy(nodes[0].verts[i].normal);
00111 nodes[0].verts[i].diffuse = 0xFFFFFFFF;
00112 nodes[0].shader = 0;
00113 }
00114
00115 nodes[0].flags = 0;
00116
00117
00118 for (i=1; i<width*height; i++)
00119 nodes[i] = nodes[0];
00120
00121
00122 scale.set(1,1,1);
00123
00124
00125 shaders = new array_c<shader_t>;
00126
00127
00128 init = true;
00129 update_verts();
00130 }
00131
00132
00133
00134
00135
00136
00137 void landscape_c::create_from_texture
00138 (
00139 sshort tex
00140 )
00141 {
00142 image_c *img;
00143
00144
00145 deinit();
00146
00147
00148 img = gv.texman->get_image(tex);
00149
00150 create_from_image(img);
00151
00152 SafeDelete(img);
00153
00154 update_verts();
00155 }
00156
00157
00158
00159
00160 void landscape_c::create_from_image
00161 (
00162 image_c *img
00163 )
00164 {
00165 ulong x,y;
00166
00167
00168 AssertReturn2(img, img->get_pixels());
00169 deinit();
00170
00171 create(img->get_width(), img->get_height());
00172
00173 AssertReturn1(init);
00174
00175 const char *buf = img->get_pixels();
00176
00177 for (x=0; x<width; x++)
00178 for (y=0; y<height; y++)
00179 {
00180 nodes[x+y*width].value =
00181 (uchar)buf[4*(x+y*width)];
00182 nodes[x+y*width].flags = 0;
00183 }
00184
00185 normalize();
00186 create_normals();
00187 scale.set(1,1,1);
00188
00189 update_verts();
00190 }
00191
00192
00193
00194
00195
00196 void landscape_c::create_from_raw
00197 (
00198 uchar *raw,
00199 ulong width,
00200 ulong height
00201 )
00202 {
00203 ulong x,y;
00204
00205 AssertReturn1(raw);
00206
00207 create(width, height);
00208
00209 AssertReturn1(init);
00210
00211 for (x=0; x<width; x++)
00212 for (y=0; y<height; y++)
00213 {
00214 nodes[x+y*width].value = raw[(x+y*width)];
00215 nodes[x+y*width].flags = 0;
00216 }
00217
00218 normalize();
00219 create_normals();
00220 scale.set(1,1,1);
00221 }
00222
00223
00224
00225
00226
00227 void landscape_c::prelight()
00228 {
00229 ulong x, y, idx, i;
00230 vec3_c p;
00231 float l;
00232
00233 for (x=0; x<width; x++)
00234 for (y=0; y<height; y++)
00235 {
00236 vec4_c col;
00237 idx = x+y*width;
00238
00239 col.clear();
00240
00241 for (i = 0; i<gv.lightcount; i++)
00242 {
00243 vec4_t colvec;
00244
00245 color_to_vec(gv.lights[i].color, colvec);
00246
00247 p = vec3_c(gv.lights[i].pos).normalize();
00248
00249 l = p.dot(nodes[idx].verts[0].normal);
00250 if (l<0) l = 0;
00251
00252 col = col.ma(l, colvec);
00253 }
00254
00255 nodes[idx].verts[0].diffuse = color_from_floats(V3TOFS(col), 1);
00256 }
00257
00258 update_verts();
00259 }
00260
00261
00262
00263
00264
00265 void landscape_c::draw()
00266 {
00267 ulong x,y;
00268 shader_t *shad = NULL;
00269
00270 gv.renderer->set_blending(BT_OPAQUE);
00271
00272 for (y=0; y<height; y++)
00273 {
00274 for (x=0; x<width; x++)
00275 {
00276 if (!is_node_visible(x,y))
00277 continue;
00278
00279 drawntiles++;
00280
00281 int idx = x+y*width;
00282
00283 vertex_t *verts = nodes[idx].verts;
00284
00285 shad = shaders->get(nodes[idx].shader);
00286
00287 gv.renderer->use_shader(shad);
00288 gv.renderer->render_verts(verts,4,PT_QUADS);
00289
00290
00291
00292
00293
00294
00295 }
00296 }
00297 }
00298
00299
00300
00301
00302
00303
00304 void landscape_c::create_normals()
00305 {
00306 plane_t p;
00307
00308 ulong x,y,i;
00309
00310 for (i=0; i<width*height; ++i)
00311 vec3_c(0,0,0).copy(nodes[i].verts[0].normal);
00312
00313 for (x=0; x<width; x++)
00314 for (y=0; y<height; y++)
00315 {
00316 ulong idx[4];
00317 vec3_c v[4];
00318
00319 idx[0] = x+y*width;
00320 idx[1] = (x+1)%width+y*width;
00321 idx[2] = (x+1)%width+((y+1)%height)*width;
00322 idx[3] = x+((y+1)%height)*width;
00323
00324 for (i=0; i<4; ++i)
00325 v[i].set( (x+((i+3)%4)/2)*scale[0],
00326 (y+ (i/2) )*scale[1],
00327 nodes[idx[i]].value*scale[2]);
00328
00329 for (i=0; i<4; ++i)
00330 {
00331 p = plane_frompoints(v[i+0], v[(i+1)%4], v[(i+3)%4]);
00332
00333
00334 (vec3_c(nodes[idx[i]].verts[0].normal)+p.n).copy(nodes[idx[i]].verts[0].normal);
00335 }
00336 }
00337
00338 for (i=0; i<width*height; ++i)
00339 {
00340 ((vec3_c(nodes[i].verts[0].normal)).normalize()).copy(nodes[i].verts[0].normal);
00341 nodes[i].verts[0].normal[2] *= -1;
00342 }
00343
00344 update_verts();
00345 }
00346
00347
00348
00349
00350
00351
00352 float landscape_c::get_height
00353 (
00354 float x,
00355 float y
00356 )
00357 {
00358
00359 ulong xx = (ulong)((x-pos[0])/scale[0]);
00360 ulong yy = (ulong)((y-pos[1])/scale[1]);
00361 ulong side = 0;
00362
00363 float rx = (x-pos[0])/scale[0]-xx;
00364 float ry = (y-pos[1])/scale[0]-yy;
00365
00366 if (rx<ry)
00367 side = 1;
00368
00369 float hh[4];
00370 ulong idx[4];
00371
00372 idx[0] = xx%width+(yy%height)*width;
00373 idx[1] = (xx+1)%width+(yy%height)*width;
00374 idx[2] = (xx+1)%width+((yy+1)%height)*width;
00375 idx[3] = xx+((yy+1)%height)*width;
00376
00377 for (ulong i=0; i<4; i++)
00378 hh[i] = nodes[idx[i]].value;
00379
00380 float hpx, hpy;
00381
00382 if (!side)
00383 {
00384 hpx = hh[1]-hh[0];
00385 hpy = hh[2]-hh[1];
00386 }
00387 else
00388 {
00389 hpx = hh[2]-hh[3];
00390 hpy = hh[3]-hh[0];
00391 }
00392
00393 return (hh[0]+hpx*rx+hpy*ry)*scale[2]+pos[2];
00394 }
00395
00396
00397
00398
00399
00400 void landscape_c::set_height(ulong x, ulong y, float value)
00401 {
00402 if (x<0 || x>=width || y<0 || y>=height)
00403 return;
00404
00405 nodes[x+y*width].value = value;
00406 update_verts();
00407 }
00408
00409
00410
00411
00412
00413 void landscape_c::set_uv(ulong x, ulong y, ushort corner, float u, float v)
00414 {
00415 if (x<0 || x>=width || y<0 || y>=height)
00416 return;
00417
00418 vec2_c(u,v).copy(nodes[x+y*width].verts[corner].uv[0]);
00419 update_verts();
00420 }
00421
00422
00423
00424
00425
00426 void landscape_c::get_slope
00427 (
00428 float x,
00429 float y,
00430 vec2_t out
00431 )
00432 {
00433
00434 ulong xx = (ulong)(x/scale[0]);
00435 ulong yy = (ulong)(y/scale[2]);
00436 ulong side = 0;
00437
00438 float rx = x/scale[0]-xx;
00439 float ry = y/scale[0]-yy;
00440
00441 if (rx<ry)
00442 side = 1;
00443
00444 float hh[4];
00445 ulong idx[4];
00446
00447 idx[0] = xx%width+(yy%height)*width;
00448 idx[1] = (xx+1)%width+(yy%height)*width;
00449 idx[2] = (xx+1)%width+((yy+1)%height)*width;
00450 idx[3] = xx+((yy+1)%height)*width;
00451
00452 for (ulong i=0; i<4; i++)
00453 hh[i] = nodes[idx[i]].value;
00454
00455 if (!side)
00456 {
00457 out[0] = hh[1]-hh[0];
00458 out[1] = hh[2]-hh[1];
00459 }
00460 else
00461 {
00462 out[0] = hh[2]-hh[3];
00463 out[1] = hh[3]-hh[0];
00464 }
00465 }
00466
00467
00468
00469
00470
00471
00472 void landscape_c::normalize()
00473 {
00474 float highest = 0;
00475 float lowest = 0;
00476 ulong x;
00477
00478 for (x=0; x<width*height; x++)
00479 if (nodes[x].value<lowest)
00480 lowest = nodes[x].value;
00481
00482 for (x=0; x<width*height; x++)
00483 nodes[x].value -= lowest;
00484
00485 for (x=0; x<width*height; x++)
00486 if (nodes[x].value>highest)
00487 highest = nodes[x].value;
00488
00489 if (highest)
00490 for (x=0; x<width*height; x++)
00491 nodes[x].value /= highest;
00492
00493 update_verts();
00494 }
00495
00496
00497
00498
00499
00500
00501 void landscape_c::circles
00502 (
00503 ulong iter
00504 )
00505 {
00506 for (ulong i=0; i<iter; i++)
00507 {
00508 float xx = (rand()%100)*0.01f*width;
00509 float yy = (rand()%100)*0.01f*height;
00510
00511 for (slong x=(slong)(xx-64); x<(slong)(xx+64); x++)
00512 {
00513 if (x<0 || x>=width) continue;
00514 for (slong y=(slong)(yy-64); y<(slong)(yy+64); y++)
00515 {
00516 if (y<0 || y>=height) continue;
00517
00518 float dx = (xx-x);
00519 float dy = (yy-y);
00520 float d = dx*dx+dy*dy;
00521
00522 if (d<100)
00523 nodes[x+y*width].value += 1-(d/100);
00524 }
00525 }
00526 }
00527
00528 update_verts();
00529 }
00530
00531
00532
00533
00534 void landscape_c::erode
00535 (
00536 float power
00537 )
00538 {
00539 for (ulong i=0; i<width*height; i++)
00540 {
00541 nodes[i].value = (float)pow(nodes[i].value, power);
00542 }
00543
00544 update_verts();
00545 }
00546
00547
00548
00549
00550 void landscape_c::tile_shader(shader_t *shader)
00551 {
00552 if (!shaders)
00553 return;
00554
00555 long num;
00556
00557 if ((num = shaders->find(shader)) == INVALID_INDEX)
00558 num = shaders->add(shader);
00559
00560 ulong i;
00561
00562 for (i=0; i<width*height; ++i)
00563 {
00564 nodes[i].shader = num;
00565 vec2_c(0,0).copy(nodes[i].verts[0].uv[0]);
00566 vec2_c(1,0).copy(nodes[i].verts[1].uv[0]);
00567 vec2_c(1,1).copy(nodes[i].verts[2].uv[0]);
00568 vec2_c(0,1).copy(nodes[i].verts[3].uv[0]);
00569 }
00570 update_verts();
00571 }
00572
00573
00574
00575
00576 void landscape_c::stretch_shader(shader_t *shader)
00577 {
00578 if (!shaders)
00579 return;
00580
00581 slong num;
00582
00583 if ((num = shaders->find(shader)) == INVALID_INDEX)
00584 num = shaders->add(shader);
00585
00586 ulong i,x,y;
00587 float upx,vpy;
00588
00589 upx = 1/(float)width;
00590 vpy = 1/(float)height;
00591
00592 for (i=0; i<width*height; ++i)
00593 {
00594 x = i%width;
00595 y = i/width;
00596
00597
00598
00599 vec2_c(upx*x, vpy*y ).copy(nodes[i].verts[0].uv[0]);
00600 vec2_c(upx*(x+1), vpy*y ).copy(nodes[i].verts[1].uv[0]);
00601 vec2_c(upx*(x+1), vpy*(y+1)).copy(nodes[i].verts[2].uv[0]);
00602 vec2_c(upx*x, vpy*(y+1)).copy(nodes[i].verts[3].uv[0]);
00603 }
00604
00605 update_verts();
00606 }
00607
00608
00609
00610
00611
00612 void landscape_c::set_shader(shader_t *shader, ulong x, ulong y, bool setuv)
00613 {
00614 if (!shaders)
00615 return;
00616
00617 if (x<0 || x>=width || y<0 || y>=height)
00618 return;
00619
00620 slong num;
00621
00622 if ((num = shaders->find(shader)) == INVALID_INDEX)
00623 num = shaders->add(shader);
00624
00625 ulong i;
00626 float upx,vpy;
00627
00628 upx = 1/(float)width;
00629 vpy = 1/(float)height;
00630
00631 i = x+y*width;
00632
00633 nodes[i].shader = num;
00634
00635 if (setuv)
00636 {
00637 vec2_c(upx*x, vpy*y ).copy(nodes[i].verts[0].uv[0]);
00638 vec2_c(upx*(x+1), vpy*y ).copy(nodes[i].verts[1].uv[0]);
00639 vec2_c(upx*(x+1), vpy*(y+1)).copy(nodes[i].verts[2].uv[0]);
00640 vec2_c(upx*x, vpy*(y+1)).copy(nodes[i].verts[3].uv[0]);
00641 }
00642
00643 update_verts();
00644 }
00645
00646
00647
00648
00649 bool landscape_c::is_node_visible(ulong x, ulong y)
00650 {
00651 int i,j;
00652
00653
00654 if (x<0 || x>=width-1)
00655 return false;
00656
00657 if (y<0 || y>=height-1)
00658 return false;
00659
00660 ulong idx[4];
00661
00662
00663 for (j=0; j<4; j++)
00664 idx[j] = ((int)NQUADVERTX(j)+x)%width+((y+(int)NQUADVERTY(j))%height)*width;
00665
00666
00667 if (nodes[idx[0]].flags & LSNFLAG_INVISIBLE)
00668 return false;
00669
00670 vec3_c v[4];
00671 bool allhidden;
00672
00673 allhidden = true;
00674
00675 for (i=0; i<4; i++)
00676 {
00677 v[i].set( (float)(x+NQUADVERTX(i))*scale[0],
00678 (float)(y+NQUADVERTY(i))*scale[1],
00679 (float)(nodes[idx[i]].value)*scale[2]);
00680
00681 v[i] = v[i] + pos;
00682 }
00683
00684
00685
00686
00687 const plane_t *frust = gv.renderer->get_viewfrustum();
00688
00689 for (i=0; i<6; i++)
00690 {
00691 allhidden=true;
00692
00693 for (int j=0; j<4; j++)
00694 {
00695 if (plane_pointside(v[j], &frust[i])>0)
00696 {
00697 allhidden = false;
00698 break;
00699 }
00700 }
00701
00702 if (allhidden)
00703 return false;
00704 }
00705
00706 return true;
00707 }
00708
00709 void landscape_c::update_verts()
00710 {
00711 ulong x,y;
00712 ulong idx[4];
00713
00714 for (y=0; y<height; y++)
00715 {
00716 for (x=0; x<width; x++)
00717 {
00718 idx[0] = (x%width)+(y%height)*width;
00719 idx[1] = ((x+1)%width)+(y%height)*width;
00720 idx[2] = ((x+1)%width)+((y+1)%height)*width;
00721 idx[3] = (x%width)+((y+1)%height)*width;
00722
00723 vertex_t *verts = nodes[idx[0]].verts;
00724
00725 vertex_set(&verts[0],
00726 x *scale[0]+pos[0],
00727 y *scale[1]+pos[1],
00728 nodes[idx[0]].value *scale[2]+pos[2],
00729 nodes[idx[0]].verts[0].uv[0][0], nodes[idx[0]].verts[0].uv[0][1]);
00730
00731 vertex_set(&verts[1],
00732 (x+1) *scale[0]+pos[0],
00733 (y+0) *scale[1]+pos[1],
00734 nodes[idx[1]].value *scale[2]+pos[2],
00735 nodes[idx[0]].verts[1].uv[0][0], nodes[idx[0]].verts[1].uv[0][1]);
00736
00737 vertex_set(&verts[2],
00738 (x+1) *scale[0]+pos[0],
00739 (y+1) *scale[1]+pos[1],
00740 nodes[idx[2]].value *scale[2]+pos[2],
00741 nodes[idx[0]].verts[2].uv[0][0], nodes[idx[0]].verts[2].uv[0][1]);
00742
00743 vertex_set(&verts[3],
00744 (x+0) *scale[0]+pos[0],
00745 (y+1) *scale[1]+pos[1],
00746 nodes[idx[3]].value *scale[2]+pos[2],
00747 nodes[idx[0]].verts[3].uv[0][0], nodes[idx[0]].verts[3].uv[0][1]);
00748
00749 nodes[idx[0]].verts[0].diffuse = nodes[idx[0]].verts[0].diffuse;
00750 nodes[idx[0]].verts[1].diffuse = nodes[idx[1]].verts[0].diffuse;
00751 nodes[idx[0]].verts[2].diffuse = nodes[idx[2]].verts[0].diffuse;
00752 nodes[idx[0]].verts[3].diffuse = nodes[idx[3]].verts[0].diffuse;
00753
00754 (vec3_c(nodes[idx[0]].verts[0].normal)).copy(nodes[idx[0]].verts[0].normal);
00755 (vec3_c(nodes[idx[1]].verts[0].normal)).copy(nodes[idx[0]].verts[1].normal);
00756 (vec3_c(nodes[idx[2]].verts[0].normal)).copy(nodes[idx[0]].verts[2].normal);
00757 (vec3_c(nodes[idx[3]].verts[0].normal)).copy(nodes[idx[0]].verts[3].normal);
00758
00759 if (!nodes[idx[0]].displist)
00760 {
00761 nodes[idx[0]].displist = glGenLists(1);
00762 }
00763
00764 glNewList(nodes[idx[0]].displist, GL_COMPILE);
00765
00766 gv.renderer->use_shader(shaders->get(nodes[idx[0]].shader));
00767
00768
00769
00770 gv.renderer->render_quad(nodes[idx[0]].verts);
00771
00772 glEndList();
00773 }
00774 }
00775 }