Level of Detail
-
- Competition winner
- Posts: 1123
- Joined: Sun Jun 10, 2007 11:14 pm
-
- Competition winner
- Posts: 1123
- Joined: Sun Jun 10, 2007 11:14 pm
Ok, here is an update of code. Please post any comments.
I'm having some problems with the vertices. When I load a model with 42 vertices, in irrlicht it says it has 174! Is this intentional? If so, what can I do to change it?[/code]
Code: Select all
class CSampleSceneNode : public scene::ISceneNode
{
class Vertex;
class Triangle;
class Triangle {
public:
Vertex* vertex[3];
Triangle(Vertex* v1, Vertex* v2, Vertex* v3) {
vertex[0] = v1;
vertex[1] = v2;
vertex[2] = v3;
for (int x = 0; x < 3; x++) {
vertex[x]->face.push_back(this);
for (int y = 0; y < 3; y++) {
bool add = true;
for(int i = 0; i < vertex[x]->neighbors.size(); i++) {
if (vertex[y]->position == vertex[x]->neighbors[i]->position) {
add = false;
}
}
if (add) {
vertex[x]->neighbors.push_back(vertex[y]);
}
}
}
}
bool HasVertex(Vertex* v) { return (v->position == vertex[0]->position || v->position == vertex[1]->position || v->position == vertex[2]->position); };
void ReplaceVertex(Vertex* target, Vertex* v) {
for (int x = 0; x < 3; x++)
if (vertex[x]->position == target->position) {
vertex[x] = v;
std::cout << "REPLACE" << std::endl;
}
}
bool CheckAndRemove(int num, array<Triangle*> *list) {
if (vertex[0]->position == vertex[1]->position || vertex[1]->position == vertex[2]->position || vertex[2]->position == vertex[0]->position) {
list->erase(num);
return true;
}
}
};
class Vertex {
public:
vector3df position;
array<Vertex*> neighbors;
array<Triangle*> face;
int id;
};
class TriangleMesh {
public:
array<Triangle> mesh;
void AddTriangle(Triangle tri) {
mesh.push_back(tri);
}
void Remove(short num) {
mesh.erase(num,1);
}
};
IMeshBuffer* BuildMeshBufferFromTriangles(IMeshBuffer* oldmb, array<Triangle*> arr, array<Vertex*>ver) {
SMeshBuffer* newm = new SMeshBuffer();
newm->Material = oldmb->getMaterial();
u16* indices = new u16[arr.size()*3];
for (int x = 0; x < arr.size(); x++) {
for (int y = 0; y < 3; y++) {
indices[x*3+y] = arr[x]->vertex[y]->id;
}
}
newm->append(oldmb->getVertices(),oldmb->getVertexCount(),indices,arr.size()*3);
return newm;
}
IMesh* DefaultMesh;
IMesh** LODMesh;
IMesh* CurrentMesh;
IMeshBuffer* test;
char CurrentLevel;
char LevelCount;
float LODBegin;
float LODLast;
bool LODOn;
array<Vertex*> Verts[8];
array<Triangle*> Tris[8];
public:
CSampleSceneNode(IMesh* mesh, scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, int numOfCollapseOnLast, char numOfLevels = 4, float LODBeginDist = 10, float LODLastDist = 30)
: scene::ISceneNode(parent, mgr, id)
{
DefaultMesh = mesh;
CurrentMesh = mesh;
CurrentMesh->getMeshBuffer(0)->getMaterial().Wireframe = true;
LODBegin = LODBeginDist;
LODLast = LODLastDist;
LevelCount = numOfLevels;
CurrentLevel = 0;
LODMesh = new IMesh*[numOfLevels];
LODOn = true;
for (int x = 0; x < mesh->getMeshBufferCount(); x++) {
S3DVertex* verts = (S3DVertex*)mesh->getMeshBuffer(x)->getVertices();
std::cout << mesh->getMeshBuffer(x)->getVertexCount() << std::endl;
for (int y = 0; y < mesh->getMeshBuffer(x)->getVertexCount(); y++) {
Vertex* vert = new Vertex();
vert->position = verts[y].Pos;
vert->id = y;
Verts[x].push_back(vert);
}
}
for (int x = 0; x < mesh->getMeshBufferCount(); x++) {
u16* indices = mesh->getMeshBuffer(x)->getIndices();
std::cout << mesh->getMeshBuffer(x)->getIndexCount() << std::endl;
for (int y = 0; y < mesh->getMeshBuffer(x)->getIndexCount(); y += 3) {
Triangle *tri = new Triangle(Verts[x][indices[y]],Verts[x][indices[y+1]],Verts[x][indices[y+2]]);
Tris[x].push_back(tri);
}
}
array<int> nr;
for (int x = 0; x < 80; x++) {
if (Tris[0][x]->HasVertex(Verts[0][0])) {
Tris[0][x]->ReplaceVertex(Verts[0][0],Verts[0][10]);
nr.push_back(x);
}
}
for (int x = 0; x < nr.size(); x++) {
if (Tris[0][nr[x]]->CheckAndRemove(nr[x],&Tris[0])) {
x--;
std::cout << "REMOVED" << std::endl;
}
}
test = BuildMeshBufferFromTriangles(mesh->getMeshBuffer(0),Tris[0],Verts[0]);
}
virtual void OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
virtual void render()
{
if (LODOn) {
vector3df cameraPos = SceneManager->getActiveCamera()->getPosition();
f32 dist = AbsoluteTransformation.getTranslation().getDistanceFrom(cameraPos);
CurrentLevel = 0;
float increment = (LODLast-LODBegin)/LevelCount;
for (int x = 0; x < LevelCount; x++) {
if (dist >= (LODBegin+increment*x)*(LODBegin+increment*x))
CurrentLevel = x;
}
}
else
CurrentMesh = DefaultMesh;
IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
for (int x = 0; x < CurrentMesh->getMeshBufferCount(); x++) {
driver->setMaterial(CurrentMesh->getMeshBuffer(x)->getMaterial());
driver->drawMeshBuffer(test);
}
}
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return CurrentMesh->getBoundingBox();
}
void setLODOn(bool on) { LODOn = on; };
bool getLODOn() { return LODOn; };
};