I've been using Irrlicht for quite a long time, and after using contribution from many, i'd like to contribuate too.
I'm doing a 3D visualition tool for geographic purpose.
Here is some code too draw from 2d coordinates of a region, a mesh representing this region
There is a class triangulate, and few code to use this class in the main program.
I might be ugly code, but i'm not a programmer ...
Triangulate.cpp
Code: Select all
#include "triangulate.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
data::data* Triangulate::dt;
scene::SMeshBuffer* Triangulate::mb;
static const float EPSILON=5;
int Triangulate::debut=0;
int Triangulate::fin=0;
long int Triangulate::Area()
{
int n = fin-debut+1;
float A=0;
for(int p=fin,q=debut; q<fin+1; p=q++)
{
//std::cout<<"A="<<A<<"+"<<dt->map[p]->x*dt->map[q]->y - dt->map[q]->x*dt->map[p]->y<<std::endl;
A+= (dt->map[p]->x/1000)*(dt->map[q]->y/1000) - (dt->map[q]->x/1000)*(dt->map[p]->y/1000) ;
}
return A/2;
}
/*
InsideTriangle decides if a point P is Inside of the triangle
defined by A, B, C.
*/
bool Triangulate::InsideTriangle(long int Ax, long int Ay,
long int Bx, long int By,
long int Cx, long int Cy,
long int Px, long int Py)
{
long long int ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy;
long long int cCROSSap, bCROSScp, aCROSSbp;
ax = Cx - Bx; ay = Cy - By;
bx = Ax - Cx; by = Ay - Cy;
cx = Bx - Ax; cy = By - Ay;
apx= Px - Ax; apy= Py - Ay;
bpx= Px - Bx; bpy= Py - By;
cpx= Px - Cx; cpy= Py - Cy;
aCROSSbp = ax*bpy - ay*bpx;
cCROSSap = cx*apy - cy*apx;
bCROSScp = bx*cpy - by*cpx;
return ((aCROSSbp > 0) && (bCROSScp > 0) && (cCROSSap > 0));
};
bool Triangulate::Snip(int u,int v,int w,int n,int *V)
{
int p;
long long int Ax, Ay, Bx, By, Cx, Cy, Px, Py;
Ax = dt->map[V[u]]->x;
Ay = dt->map[V[u]]->y;
Bx = dt->map[V[v]]->x;
By = dt->map[V[v]]->y;
Cx = dt->map[V[w]]->x;
Cy = dt->map[V[w]]->y;
if ((Ax==Bx)&&(Ay==By)) return true;
if ((Ax==Cx)&&(Ay==Cy)) return true;
if ((Cx==Bx)&&(Cy==By)) return true;
//std::cout<<"0>"<<(float)(Bx-Ax)/100*(Cy-Ay)/100 - (By-Ay)/100*(Cx-Ax)/100<<std::endl; ;
if ( 0 > (float)(Bx-Ax)/100*(Cy-Ay)/100 - (By-Ay)/100*(Cx-Ax)/100 ) return false;
for (p=0;p<n;p++)
{
if( (p == u) || (p == v) || (p == w) ) continue;
Px = dt->map[V[p]]->x;
Py = dt->map[V[p]]->y;
if (InsideTriangle(Ax,Ay,Bx,By,Cx,Cy,Px,Py)) {
//std::cout<<"uvwp"<<u<<","<<v<<","<<w<<","<<p<<std::endl;
return false;
}
}
//std::cout<<"ok:"<<u<<","<<v<<","<<w<<std::endl; ;
return true;
}
bool Triangulate::Process(int deb, int fi)
{
/* allocate and initialize list of Vertices in polygon */
debut=deb;
fin=fi;
int n = fin-debut+1;
// std::cout<<"n="<<n<<std::endl;
if ( n < 3 ) return false;
int *V = new int[n];
/* we want a counter-clockwise polygon in V */
int v;
//std::cout<<"aire="<<Area()<<std::endl;
if ( 0<Area() )
for (v=0; v<n; v++) V[v] = v+debut;
else
for(v=0; v<n; v++) V[v] = fin-v;
// Decomplex(V,n);
int nv = n;
/* remove nv-2 Vertices, creating 1 triangle every time */
int count = 5*nv; /* error detection */
for(int m=0, v=nv-1; nv>2; )
{
/* if we loop, it is probably a non-simple polygon */
if (0 >= (count--))
{
std::cout<<"Triangulate: ERROR - probable bad polygon!";
return false;
}
/* three consecutive vertices in current polygon, <u,v,w> */
int u = v ; if (nv <= u) u = 0; /* previous */
v = u+1; if (nv <= v) v = 0; /* new v */
int w = v+1; if (nv <= w) w = 0; /* next */
//std::cout<<"uvw:"<<u<<","<<v<<","<<w<<","<<n<<"="<<Area(V[w],V[v])<<"<>"<<":"<<std::endl;
if ( Snip(u,v,w,nv,V) )
{
int a,b,c,s,t;
/* true names of the vertices */
a = V[u]; b = V[v]; c = V[w];
/* output Triangle */
mb->Indices.push_back(a-debut);
mb->Indices.push_back(c-debut);
mb->Indices.push_back(b-debut);
m++;
/* remove v from remaining polygon */
for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
/* resest error detection counter */
count = 5*nv;
//std::cout<<"uvw:"<<u<<","<<v<<","<<w<<","<<n<<"="<<"<>"<<":"<<std::endl;
}
}
delete V;
return true;
}
Triangulate::Triangulate(data::data* d, scene::SMeshBuffer* m){
dt=d;
mb=m;
debut=0;
fin=0;
};
Triangulate::~Triangulate(){};
/************************************************************************/
/*** END OF CODE SECTION TRIANGULATE.CPP BEGINNING OF TEST.CPP A SMALL **/
/*** TEST APPLICATION TO DEMONSTRATE THE USAGE OF THE TRIANGULATOR **/
/************************************************************************/
Code: Select all
// COTD Entry submitted by John W. Ratcliff [jratcliff@verant.com]
// ** THIS IS A CODE SNIPPET WHICH WILL EFFICIEINTLY TRIANGULATE ANY
// ** POLYGON/CONTOUR (without holes) AS A STATIC CLASS. THIS SNIPPET
// ** IS COMPRISED OF 3 FILES, TRIANGULATE.H, THE HEADER FILE FOR THE
// ** TRIANGULATE BASE CLASS, TRIANGULATE.CPP, THE IMPLEMENTATION OF
// ** THE TRIANGULATE BASE CLASS, AND TEST.CPP, A SMALL TEST PROGRAM
// ** DEMONSTRATING THE USAGE OF THE TRIANGULATOR. THE TRIANGULATE
// ** BASE CLASS ALSO PROVIDES TWO USEFUL HELPER METHODS, ONE WHICH
// ** COMPUTES THE AREA OF A POLYGON, AND ANOTHER WHICH DOES AN EFFICENT
// ** POINT IN A TRIANGLE TEST.
// ** SUBMITTED BY JOHN W. RATCLIFF (jratcliff@verant.com) July 22, 2000
/**********************************************************************/
/************ HEADER FILE FOR TRIANGULATE.H ***************************/
/**********************************************************************/
#ifndef TRIANGULATE_H
#define TRIANGULATE_H
/*****************************************************************/
/** Static class to triangulate any contour/polygon efficiently **/
/** You should replace Vector2d with whatever your own Vector **/
/** class might be. Does not support polygons with holes. **/
/** Uses STL vectors to represent a dynamic array of vertices. **/
/** This code snippet was submitted to FlipCode.com by **/
/** John W. Ratcliff (jratcliff@verant.com) on July 22, 2000 **/
/** I did not write the original code/algorithm for this **/
/** this triangulator, in fact, I can't even remember where I **/
/** found it in the first place. However, I did rework it into **/
/** the following black-box static class so you can make easy **/
/** use of it in your own code. Simply replace Vector2d with **/
/** whatever your own Vector implementation might be. **/
/*****************************************************************/
#include <irrlicht.h>
#include "data.h"
using namespace irr;
class Triangulate
{
public:
Triangulate(data::data* d, scene::SMeshBuffer* m);
virtual ~Triangulate();
// triangulate a contour/polygon, places results in STL vector
// as series of triangles.
static bool Process(int deb, int fi);
// compute area of a contour/polygon
static long int Area();
// decide if point Px/Py is inside triangle defined by
// (Ax,Ay) (Bx,By) (Cx,Cy)
static bool InsideTriangle(long int Ax, long int Ay,
long int Bx, long int By,
long int Cx, long int Cy,
long int Px, long int Py);
private:
static void Decomplex(int* V,int n);
static data::data* dt;
static scene::SMeshBuffer* mb;
static int debut;
static int fin;
static bool Snip(int u,int v,int w,int n,int *V);
};
#endif
Code: Select all
void affichage::dessinecarte()
{
if (dt->getnbpointmap()<3) return;
scene::SMesh* msh = new scene::SMesh();
core::aabbox3d<f32> Box;
std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;
scene::SMeshBuffer* mb = new scene::SMeshBuffer();
std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;
std::cout<<"index:"<<mb->getIndexCount ()<<std::endl;
std::cout<<"vertex:"<<mb->getVertexCount ()<<std::endl;
video::S3DVertex tv;
int debut=0;
Triangulate* t=new Triangulate(dt,mb);
std::cout<<dt->getminy()<<"<"<<dt->getmaxy()<<","<<dt->getminx()<<"<"<<dt->getmaxx()<<" nbpt="<<dt->getnbpointmap()<<std::endl;
//driver->setTransform(video::ETS_WORLD, core::matrix4());
for(int i=0;i<dt->getnbpointmap();i++) {
// if (i==80000) driver->draw3DLine (core::vector3df(-dt->map[i-1]->x,
// dt->map[i-1]->y,0),core::vector3df(-dt->map[i]->x,
// dt->map[i]->y,0),video::SColor(255, 255, 255, 255));
// smgr->addCubeSceneNode( 5 ,NULL,-1,core::vector3df(-dt->map[i]->x,dt->map[i]->y,100));
tv=video::S3DVertex(-dt->map[i]->x,
dt->map[i]->y,0,0,0,1, video::SColor(100,255,0,0), 0, 0);
mb->Vertices.push_back(tv);
if (i==dt->getnbpointmap()-1) {
t->Process(debut,dt->getnbpointmap()-1);
msh->recalculateBoundingBox();
msh->addMeshBuffer(mb);
mb->drop();
continue;
}
if (strcmp (dt->map[i]->dct,dt->map[i+1]->dct) != 0) {
t->Process(debut,i);
debut=i+1;
msh->recalculateBoundingBox();
msh->addMeshBuffer(mb);
mb->drop();
mb = new scene::SMeshBuffer();
t=new Triangulate(dt,mb);
std::cout<<"boulcecarte"<<i<<","<<dt->map[i]->dct<<","<<dt->map[i+1]->dct<<","<<std::endl;
}
}
scene::SAnimatedMesh *anmmesh = new scene::SAnimatedMesh;
std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;
anmmesh->addMesh(msh);
mcarte=smgr->addAnimatedMeshSceneNode(anmmesh);
std::cout<<"nb material="<<mcarte->getMaterialCount()<<std::endl;
mcarte->getMaterial(0).EmissiveColor.set(255, 200, 200, 0);
mcarte->getMaterial(0).DiffuseColor.set(255, 255, 255, 0);
if (mcarte->getMaterialCount()>1) {
mcarte->getMaterial(1).EmissiveColor.set(255, 0, 200, 0);
mcarte->getMaterial(1).DiffuseColor.set(255, 0, 255, 0);
}
if (mcarte->getMaterialCount()>2) {
mcarte->getMaterial(2).DiffuseColor.set(255, 0, 0, 255);
mcarte->getMaterial(2).EmissiveColor.set(255, 0, 0, 200);
}
if (mcarte->getMaterialCount()>3) {
mcarte->getMaterial(3).EmissiveColor.set(255, 0, 200, 200);
mcarte->getMaterial(3).DiffuseColor.set(255, 0, 255,200);
}
if (mcarte->getMaterialCount()>4) {
int nbdep=4;
while (mcarte->getMaterialCount()>nbdep){
mcarte->getMaterial(nbdep).EmissiveColor.set(255, stg->hasard(0,2565), stg->hasard(0,255), stg->hasard(0,255));
mcarte->getMaterial(nbdep).DiffuseColor.set(255, stg->hasard(0,255), stg->hasard(0,255),stg->hasard(0,255));
nbdep++;
}
}
mcarte->setMaterialFlag(video::EMF_LIGHTING, true);
mcarte->setAutomaticCulling(irr::scene::EAC_OFF);
std::cout<<"mb:"<<msh->getMeshBufferCount()<<std::endl;
std::cout<<"index:"<<mb->getIndexCount ()<<std::endl;
std::cout<<"vertex:"<<mb->getVertexCount ()<<std::endl;
}