Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

x_brush.cpp

Go to the documentation of this file.
00001 // OMICRON ENGINE HEADER FILE
00002 //
00003 // --------------------------------------------------------------------------
00004 // Copyright (C) 2001-2002 by Bjoern Paetzel <kolrabi@gmx.de>
00005 //
00006 // This file is part of the Omicron Engine.
00007 //
00008 // The Omicron Engine is free software; you can redistribute it and/or modify
00009 // it under the terms of the  GNU General Public License  as published by the
00010 // Free Software Foundation;  either version  2  of the License,  or (at your
00011 // option) any later version.
00012 //
00013 // The Omicron Engine  is distributed in the hope that it will be useful, but
00014 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015 // or  FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License
00016 // for more details.
00017 //
00018 // You should have  received a copy of the  GNU General Public License  along
00019 // with The Omicron Engine;  if not,  write to the  Free Software Foundation,
00020 // Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
00021 //
00022 // --------------------------------------------------------------------------
00023 // Last modified:       $Date: 2002/12/07 19:02:06 $
00024 // By           :       $Author: kolrabi $
00025 // $Id: x_brush.cpp,v 1.1.1.1 2002/12/07 19:02:06 kolrabi Exp $ 
00026 
00027 /*
00028 
00029   $Log: x_brush.cpp,v $
00030   Revision 1.1.1.1  2002/12/07 19:02:06  kolrabi
00031   initial release
00032 
00033 
00034 */
00035 
00040 #include            "omicron/internal.h"
00041 #include            "omicron/render.h"
00042 #include            "omicron/array.h"
00043 #include            "omicron/brush.h"
00044 
00045 /****************************************************************************
00046  ****************************************************************************
00047  * BRUSHFACE CLASS **********************************************************
00048  ****************************************************************************
00049  ****************************************************************************/
00050 
00051 brushface_c::brushface_c()
00052 {
00053     // init
00054     vertexcount = 0;
00055     vertices    = NULL;
00056     shader      = NULL;
00057 }
00058 
00059 brushface_c::~brushface_c()
00060 {
00061     AssertThis;
00062 
00063     SafeArrayDelete(vertices);
00064 }
00065 
00066 void
00067 brushface_c::create_from_plane
00068 (
00069     const plane_t * p                  
00070 )
00071 {
00072     AssertThis;
00073     AssertReturn1(p);
00074 
00075     SafeArrayDelete(vertices);
00076     plane = *p;
00077 
00078     scale.set(1,1);
00079     offset.set(0,0);
00080     rotation = 0;
00081 
00082     createvertices();
00083 }
00084 
00085 void
00086 brushface_c::createvertices
00087 (
00088 )
00089 {
00090     AssertThis;
00091 
00092     // reset vertices
00093     SafeArrayDelete(vertices);
00094 
00095     // create face
00096     vec3_c     vu, vv, vn, vtn;
00097 
00098     vn = plane.n;
00099 
00100     vtn.set(    (float)fabs(vn[0]),
00101                 (float)fabs(vn[1]),
00102                 (float)fabs(vn[2]) );
00103 
00104     // find u and v vectors
00105     if (vtn[0]>=vtn[1] && vtn[0]>=vtn[2])       // plane normal goes to x
00106         vu = vec3_c::vec3z;
00107     else if (vtn[1]>vtn[0] && vtn[1]>=vtn[2])   // plane normal goes to y
00108         vu = vec3_c::vec3x;
00109     else if (vtn[2]>vtn[1] && vtn[2]>vtn[0])    // plane normal goes to z
00110         vu = vec3_c::vec3y;
00111 
00112     // find a v vector
00113     vv = vu.cross(vn);
00114 
00115     // correct v vector
00116     vu = vv.cross(vu);
00117 
00118     vv = vv.normalize() * BIGPOLYSIZE;
00119     vu = vu.normalize() * BIGPOLYSIZE;
00120 
00121     // create a quad
00122     vertices = new vertex_t[4];
00123     vertexcount = 4;
00124 
00125     for (ulong i=0; i<4; i++)
00126     {
00127         // set quad vertices
00128 
00129                 (vu * QUADVERTX(i) + vv * QUADVERTY(i) + vec3_c(plane.n) * plane.d).copy(vertices[i].xyz);
00130 
00131         // set texture coordinates
00132         vec2_c(
00133             QUADVERTX(i)*BIGPOLYSIZE*scale[0]+offset[0], 
00134             QUADVERTY(i)*BIGPOLYSIZE*scale[1]+offset[1]).copy(vertices[i].uv[0]);
00135 
00136         // other vertex stuff
00137         vertices[i].diffuse = 0xFFFFFFFF;
00138         (vec3_c(plane.n)).copy(vertices[i].normal);
00139     }
00140 
00141     // done
00142 }
00143 
00144 bool
00145 brushface_c::cut
00146 (
00147     const plane_t * p                   
00148 )
00149 {
00150     AssertThisV;
00151     AssertReturnValue2(p, vertices, false);
00152 
00153     vertex_t    *tmpverts   = new vertex_t[vertexcount+2];
00154     ulong       vcount      = 0;
00155 
00156     ulong       idxthis     = vertexcount-1;
00157     ulong       idxnext     = 0;
00158 
00159     sshort      sidethis    = -_sgn(plane_pointdist(vertices[idxthis].xyz, p));
00160     sshort      sidenext    = 0;
00161     
00162     // cut the polygon as sutherland and hodgeman would :)
00163     for (idxnext=0; idxnext<vertexcount; ++idxnext)
00164     {
00165         sidenext = -_sgn(plane_pointdist(vertices[idxnext].xyz, p));
00166 
00167         // if in front of plane just add the vertex
00168         if (sidethis>=0)
00169             vertex_copy(&vertices[idxthis], &tmpverts[vcount++]);
00170 
00171         // crossed the plane?
00172         if (sidethis == -sidenext && sidethis)
00173         {
00174             vec3_c      v;
00175             vec3_t      vt;
00176             vertex_t    *vx;
00177             float       frac;
00178 
00179             vx = &tmpverts[vcount++];
00180             
00181             frac = plane_line_intersect(vertices[idxthis].xyz, 
00182                                         vertices[idxnext].xyz, p, vt);
00183 
00184             v = vt;
00185 
00186             v.copy(vx->xyz);
00187             vec3_c(plane.n).copy(vx->normal);
00188 
00189             vec2_c::linear(vertices[idxthis].uv[0], 
00190                            vertices[idxnext].uv[0], frac).copy(vx->uv[0]);
00191                            
00192             vec2_c::linear(vertices[idxthis].uv[1], 
00193                            vertices[idxnext].uv[1], frac).copy(vx->uv[1]);
00194                            
00195             vx->diffuse = vertices[idxthis].diffuse;
00196         }
00197         idxthis     = idxnext;
00198         sidethis    = sidenext;
00199     }
00200 
00201     SafeArrayDelete(vertices);
00202     vertexcount = vcount;
00203     vertices    = tmpverts;
00204 
00205     return (vertexcount==0);
00206 }
00207 
00208 void
00209 brushface_c::get_vertex
00210 (
00211     ulong           num,                
00212     vertex_t *      out                 
00213 )
00214 {
00215     AssertThis;
00216 
00217     AssertReturn2(out, vertices);
00218 
00219     vertex_copy(&vertices[num%vertexcount], out);
00220 }
00221 
00222 void
00223 brushface_c::get_edge
00224 (
00225     ulong           num,                
00226     edge_t          out                 
00227 )
00228 {
00229     AssertThis;
00230     AssertReturn2(out, vertices);
00231 
00232     (vec3_c(vertices[num%vertexcount].xyz)).copy(out[0]);
00233     (vec3_c(vertices[(num+1)%vertexcount].xyz)).copy(out[1]);
00234 }
00235 
00236 void
00237 brushface_c::set_tex_params
00238 (
00239     const vec2_t    _scale,             
00240     const vec2_t    _offset,            
00241     float           rot                 
00242 )
00243 {
00244     AssertThis;
00245 
00246     scale       = _scale;
00247     offset      = _offset;
00248     rotation    = rot;
00249 }
00250 
00251 void
00252 brushface_c::draw
00253 ()
00254 {
00255     AssertThis;
00256 
00257     AssertReturn1(vertices);
00258 
00259     gv.renderer->use_shader(shader);
00260     gv.renderer->render_verts(vertices, vertexcount, PT_TRIANGLEFAN);
00261 }
00262 
00263 /****************************************************************************
00264  ****************************************************************************
00265  * BRUSH CLASS **************************************************************
00266  ****************************************************************************
00267  ****************************************************************************/
00268 
00269 brush_c::brush_c()
00270 {
00271     faces       = new array_c<brushface_c>;
00272     edges       = NULL;
00273     edgecount   = 0;
00274 }
00275 
00276 brush_c::~brush_c()
00277 {
00278     AssertThis;
00279 
00280     for (slong i=0; i<faces->get_count(); i++)
00281     {
00282         brushface_c *f = faces->get(i);
00283         SafeDelete(f);
00284     }
00285     SafeDelete(faces);
00286     SafeArrayDelete(edges);
00287 }
00288 
00289 void
00290 brush_c::add_plane
00291 (
00292     const plane_t * p                   
00293 )
00294 {
00295     AssertThis;
00296     AssertReturn1(p);
00297 
00298     brushface_c    *face;
00299     face = new brushface_c;
00300 
00301     face->create_from_plane(p);
00302     face->set_shader(shader);
00303     faces->add(face);
00304 
00305     for (slong i=0; i<faces->get_count(); i++)
00306     {
00307         brushface_c *f = faces->get(i);
00308 
00309         if (f)
00310         {
00311             for (slong j=0; j<faces->get_count(); j++)
00312             {
00313                 if (i==j) continue;
00314 
00315                 brushface_c *f2 = faces->get(j);
00316 
00317                 if (f2)
00318                 {
00319                     if (f->cut(f2->get_plane()))
00320                     {
00321                         faces->remove(i);
00322                         SafeDelete(f);
00323                         break;
00324                     }
00325                 }
00326             }
00327         }
00328     }
00329 
00330     // create edge table
00331     find_edges();
00332 }
00333 
00334 void
00335 brush_c::set_shader
00336 (
00337     const shader_t *_shader             
00338 )
00339 {
00340     AssertThis;
00341 
00342     for (slong i=0; i<faces->get_count(); i++)
00343     {
00344         brushface_c *f = faces->get(i);
00345 
00346         if (f)
00347             f->set_shader(_shader);
00348     }
00349 
00350     shader = _shader;
00351 }
00352 
00353 void
00354 brush_c::set_face_shader
00355 (
00356     ulong           face,               
00357     const shader_t *shader              
00358 )
00359 {
00360     AssertThis;
00361 
00362     if ((slong)face>faces->get_count())
00363         return;
00364 
00365     ulong num = 0;
00366 
00367     for (slong i=0; i<faces->get_count(); i++)
00368     {
00369         brushface_c *f = faces->get(i);
00370 
00371         if (f)
00372         {
00373             if (++num = face)
00374                 f->set_shader(shader);
00375         }
00376     }
00377 }
00378 
00379 void
00380 brush_c::draw
00381 ()
00382 {
00383     AssertThis;
00384 
00385     AssertReturn1(faces);
00386 
00387     for (slong i=0; i<faces->get_count(); i++)
00388     {
00389         brushface_c *f = faces->get(i);
00390 
00391         if (f)
00392             f->draw();
00393     }
00394 }
00395 
00396 void
00397 brush_c::find_edges
00398 ()
00399 {
00400     AssertThis;
00401 
00402     SafeArrayDelete(edges);
00403 
00404     edgecount = 0;
00405 
00406     AssertReturn1(faces);
00407 
00408     slong i, edge = 0;
00409 
00410     for (i=0; i<faces->get_count(); i++)
00411     {
00412         brushface_c *f = faces->get(i);
00413 
00414         if (f)
00415             edgecount += f->get_vertex_count();
00416     }
00417 
00418     edges = new edge_t[edgecount];
00419 
00420     AssertReturn1(edges);
00421 
00422     for (i=0; i<faces->get_count(); i++)
00423     {
00424         brushface_c *f = faces->get(i);
00425 
00426         if (f)
00427             for (ulong j=0; j<f->get_vertex_count(); j++)
00428                 f->get_edge(j, edges[edge++]);
00429     }
00430 }
00431 
00432 /* experimental -->
00433 
00434 // collide brush agains ray
00435 void brush_c::ray_collide(const vec3_t p1, const vec3_t p2, collision_t *out)
00436 {
00437     AssertThis;
00438 
00439     AssertReturn3(p1, p2, out);
00440 
00441     float   t;
00442     slong   i;
00443     vec3_c  v;
00444     vec3_t  vt;
00445 
00446     out->t = 1;
00447     vec3_c(p2).copy(out->pos);
00448     vec3_c(0,0,0).copy(out->normal);
00449 
00450     for (i=0; i<faces->get_count(); i++)
00451     {
00452         brushface_c *f = faces->get(i);
00453 
00454         if (f)
00455         {
00456             t = plane_line_intersect(p1, p2, f->get_plane(), vt);
00457             v = vt;
00458 
00459             if (t>0 && t<1)
00460             {
00461                 bool broke = false;
00462 
00463                 for (slong j=0; j<(slong)f->get_vertex_count(); j++)
00464                 {
00465                     if (i==j) continue;
00466 
00467                     brushface_c *f2 = faces->get(j);
00468 
00469                     if (!f2) continue;
00470 
00471                     if (plane_pointdist(v, f2->get_plane())>0)
00472                     {
00473                         broke = true;
00474                         break;
00475                     }
00476                 }
00477 
00478                 out->t = t;
00479                 v.copy(out->pos);
00480                 f->get_normal().copy(out->normal);
00481                 return;
00482             }
00483         }
00484     }
00485 }
00486 
00487 // collide brush agains box
00488 void brush_c::box_collide(const bbox_t *bbox, collision_t *out)
00489 {
00490     AssertThis;
00491 
00492     AssertReturn2(bbox, out);
00493 
00494     ulong  k;
00495     
00496     vec3_c d;
00497 
00498     collision_t tmpout;
00499 
00500     d = vec3_c(bbox->pos1) - bbox->pos2;
00501 
00502     // check each bbox vertex for collision with faces
00503     for (k=0; k<8; k++)
00504     {
00505         vec3_c v;
00506         vec3_c p, p2;
00507 
00508         v[0] = bbox->size[(k>>0)&1][0];
00509         v[1] = bbox->size[(k>>1)&1][0];
00510         v[2] = bbox->size[(k>>2)&1][0];
00511 
00512         if (v.dot(d)>0)
00513             continue;
00514 
00515         // check
00516         p  = v + bbox->pos1;
00517         p2 = v + bbox->pos2;
00518         raycollide(p, p2, &tmpout);
00519 
00520         if (tmpout.t<1 && tmpout.t>=0)
00521         {
00522             (vec3_c(tmpout.pos) - (float*)v).copy(bbox->pos2);
00523 
00524             *out = tmpout;
00525             break;
00526         }
00527     }
00528 
00529     if (edges)
00530     // check each brush vertex for collision with bbox
00531     for (k=0; k<edgecount; k++)
00532     {
00533         vec3_c v;
00534 
00535         v = edges[k][0];
00536 
00537         vector_intersect_bbox(v, bbox, &tmpout);
00538 
00539         if (tmpout.t<1 && tmpout.t>=0)
00540         {
00541             if (tmpout.t < out->t)
00542             {
00543                 *out = tmpout;
00544                 vector_linear(bbox->pos1, bbox->pos2, out->t, bbox->pos2);
00545                 break;
00546             }
00547         }
00548     }
00549 }
00550 
00551 */
00552 

Generated on Wed Dec 18 15:48:48 2002 for omicron engine by doxygen1.2.18