absence_thelab

diff src/3deng/3dgeom.cpp @ 0:1cffe3409164

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 23 Oct 2014 01:46:07 +0300
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/3deng/3dgeom.cpp	Thu Oct 23 01:46:07 2014 +0300
     1.3 @@ -0,0 +1,478 @@
     1.4 +#include <cassert>
     1.5 +#include "3dgeom.h"
     1.6 +#include "3dengine.h"
     1.7 +
     1.8 +using std::vector;
     1.9 +
    1.10 +TexCoord::TexCoord(float u, float v) {
    1.11 +	this->u = u;
    1.12 +	this->v = v;
    1.13 +}
    1.14 +
    1.15 +// Vertex class implementation
    1.16 +
    1.17 +Vertex::Vertex() {
    1.18 +	color = 0x00ffffff;
    1.19 +	memset(tex, 0, 4*sizeof(TexCoord));
    1.20 +}
    1.21 +
    1.22 +Vertex::Vertex(const Vector3 &position, float tu, float tv, dword color) {
    1.23 +	pos = position;
    1.24 +	tex[0].u = tex[1].u = tex[2].u = tex[3].u = tu;
    1.25 +	tex[0].v = tex[1].v = tex[2].v = tex[3].v = tv;
    1.26 +	this->color = color;
    1.27 +}
    1.28 +
    1.29 +void Vertex::CalculateNormal(const Vertex *vbuffer, const Triangle *triangles, long trinum) {
    1.30 +
    1.31 +	// find the position of the curent vertex in the vertex buffer
    1.32 +	dword index = (dword)(this - vbuffer);
    1.33 +	
    1.34 +	normal = Vector3(0, 0, 0);
    1.35 +	const Triangle *tri = triangles;
    1.36 +	for(int i=0; i<trinum; i++, tri++) {
    1.37 +		if(tri->vertices[0] == index || tri->vertices[1] == index || tri->vertices[2] == index) {
    1.38 +			normal += tri->normal;
    1.39 +		}
    1.40 +	}
    1.41 +
    1.42 +	normal.Normalize();
    1.43 +}
    1.44 +
    1.45 +/////////// Edge class implementation ///////////
    1.46 +
    1.47 +Edge::Edge() {
    1.48 +	vertices[0] = vertices[1] = adjfaces[0] = adjfaces[1] = 0;
    1.49 +}
    1.50 +
    1.51 +Edge::Edge(Index v1, Index v2, Index af1, Index af2) {
    1.52 +	vertices[0] = v1;
    1.53 +	vertices[1] = v2;
    1.54 +	adjfaces[0] = af1;
    1.55 +	adjfaces[1] = af2;
    1.56 +}
    1.57 +
    1.58 +/////////// Triangle class implementation /////////////
    1.59 +Triangle::Triangle(Index v1, Index v2, Index v3) {
    1.60 +	vertices[0] = v1;
    1.61 +	vertices[1] = v2;
    1.62 +	vertices[2] = v3;
    1.63 +}
    1.64 +
    1.65 +void Triangle::CalculateNormal(Vertex *vbuffer, bool normalize) {
    1.66 +	Vector3 v1 = vbuffer[vertices[1]].pos - vbuffer[vertices[0]].pos;
    1.67 +	Vector3 v2 = vbuffer[vertices[2]].pos - vbuffer[vertices[0]].pos;
    1.68 +	normal = v1.CrossProduct(v2);
    1.69 +	if(normalize) normal.Normalize();
    1.70 +}
    1.71 +
    1.72 +
    1.73 +/////////////// Triangular Mesh implementation /////////////
    1.74 +
    1.75 +TriMesh::TriMesh(byte LODLevels, GraphicsContext *gc) {
    1.76 +	memset(this, 0, sizeof(TriMesh));
    1.77 +	this->gc = gc;
    1.78 +	Levels = LODLevels;
    1.79 +
    1.80 +	varray = new Vertex*[Levels];
    1.81 +	memset(varray, 0, Levels * sizeof(Vertex*));
    1.82 +	
    1.83 +	triarray = new Triangle*[Levels];
    1.84 +	memset(triarray, 0, Levels * sizeof(Triangle*));
    1.85 +	
    1.86 +	vbuffer = new VertexBuffer*[Levels];
    1.87 +	memset(vbuffer, 0, Levels * sizeof(VertexBuffer*));
    1.88 +
    1.89 +	ibuffer = new IndexBuffer*[Levels];
    1.90 +	memset(ibuffer, 0, Levels * sizeof(IndexBuffer*));
    1.91 +
    1.92 +	AdjTriangles = new std::vector<dword>*[Levels];
    1.93 +	memset(AdjTriangles, 0, Levels * sizeof(std::vector<dword>*));
    1.94 +
    1.95 +	VertexCount = new dword[Levels];
    1.96 +	TriCount = new dword[Levels];
    1.97 +
    1.98 +	BuffersValid = new bool[Levels];
    1.99 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.100 +
   1.101 +	AdjValid = new bool[Levels];
   1.102 +	memset(AdjValid, 0, Levels * sizeof(bool));
   1.103 +}
   1.104 +
   1.105 +TriMesh::TriMesh(const TriMesh &mesh) {
   1.106 +
   1.107 +	memcpy(this, &mesh, sizeof(TriMesh));
   1.108 +
   1.109 +	BuffersValid = new bool[Levels];
   1.110 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.111 +    
   1.112 +	varray = new Vertex*[Levels];
   1.113 +	triarray = new Triangle*[Levels];
   1.114 +	vbuffer = new VertexBuffer*[Levels];
   1.115 +	ibuffer = new IndexBuffer*[Levels];
   1.116 +
   1.117 +	VertexCount = new dword[Levels];
   1.118 +	TriCount = new dword[Levels];
   1.119 +
   1.120 +	for(int i=0; i<Levels; i++) {
   1.121 +		
   1.122 +		VertexCount[i] = mesh.VertexCount[i];
   1.123 +		TriCount[i] = mesh.TriCount[i];
   1.124 +		
   1.125 +        varray[i] = new Vertex[VertexCount[i]];
   1.126 +		triarray[i] = new Triangle[TriCount[i]];
   1.127 +		
   1.128 +		memcpy(varray[i], mesh.varray[i], VertexCount[i] * sizeof(Vertex));
   1.129 +		memcpy(triarray[i], mesh.triarray[i], TriCount[i] * sizeof(Triangle));
   1.130 +
   1.131 +		vbuffer[i] = 0;
   1.132 +		ibuffer[i] = 0;
   1.133 +
   1.134 +		UpdateSystemBuffers(i);
   1.135 +	}
   1.136 +}
   1.137 +
   1.138 +TriMesh::~TriMesh() {
   1.139 +	if(varray) {
   1.140 +		for(int i=0; i<Levels; i++) {
   1.141 +            delete [] varray[i];
   1.142 +		}
   1.143 +		delete [] varray;
   1.144 +	}
   1.145 +
   1.146 +	if(triarray) {
   1.147 +		for(int i=0; i<Levels; i++) {
   1.148 +			delete [] triarray[i];
   1.149 +		}
   1.150 +		delete triarray;
   1.151 +	}
   1.152 +	
   1.153 +	if(vbuffer) {
   1.154 +		for(int i=0; i<Levels; i++) {
   1.155 +			if(vbuffer[i]) vbuffer[i]->Release();
   1.156 +		}
   1.157 +	}
   1.158 +	if(ibuffer) {
   1.159 +		for(int i=0; i<Levels; i++) {
   1.160 +			if(ibuffer[i]) ibuffer[i]->Release();
   1.161 +		}
   1.162 +	}
   1.163 +
   1.164 +	if(AdjTriangles) {
   1.165 +		for(int i=0; i<Levels; i++) {
   1.166 +			delete [] AdjTriangles[i];
   1.167 +		}
   1.168 +		delete AdjTriangles;
   1.169 +	}
   1.170 +}
   1.171 +
   1.172 +const TriMesh &TriMesh::operator =(const TriMesh &mesh) {
   1.173 +	memcpy(this, &mesh, sizeof(TriMesh));
   1.174 +
   1.175 +	BuffersValid = new bool[Levels];
   1.176 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.177 +    
   1.178 +	varray = new Vertex*[Levels];
   1.179 +	triarray = new Triangle*[Levels];
   1.180 +	vbuffer = new VertexBuffer*[Levels];
   1.181 +	ibuffer = new IndexBuffer*[Levels];
   1.182 +
   1.183 +	VertexCount = new dword[Levels];
   1.184 +	TriCount = new dword[Levels];
   1.185 +
   1.186 +	for(int i=0; i<Levels; i++) {
   1.187 +		
   1.188 +		VertexCount[i] = mesh.VertexCount[i];
   1.189 +		TriCount[i] = mesh.TriCount[i];
   1.190 +		
   1.191 +        varray[i] = new Vertex[VertexCount[i]];
   1.192 +		triarray[i] = new Triangle[TriCount[i]];
   1.193 +		
   1.194 +		memcpy(varray[i], mesh.varray[i], VertexCount[i] * sizeof(Vertex));
   1.195 +		memcpy(triarray[i], mesh.triarray[i], TriCount[i] * sizeof(Triangle));
   1.196 +
   1.197 +		vbuffer[i] = 0;
   1.198 +		ibuffer[i] = 0;
   1.199 +
   1.200 +		UpdateSystemBuffers(i);
   1.201 +	}
   1.202 +	return mesh;
   1.203 +}
   1.204 +
   1.205 +
   1.206 +const Vertex *TriMesh::GetVertexArray(byte level) const {
   1.207 +	if(level >= Levels) return 0;
   1.208 +	return varray[level];
   1.209 +}
   1.210 +
   1.211 +const Triangle *TriMesh::GetTriangleArray(byte level) const {
   1.212 +	if(level >= Levels) return 0;
   1.213 +	return triarray[level];
   1.214 +}
   1.215 +	
   1.216 +
   1.217 +Vertex *TriMesh::GetModVertexArray() {
   1.218 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.219 +	return varray[0];
   1.220 +}
   1.221 +
   1.222 +Triangle *TriMesh::GetModTriangleArray() {
   1.223 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.224 +	memset(AdjValid, 0, Levels * sizeof(bool));
   1.225 +	return triarray[0];
   1.226 +}
   1.227 +
   1.228 +const VertexBuffer *TriMesh::GetVertexBuffer(byte level) const {
   1.229 +	if(level >= Levels) return 0;
   1.230 +
   1.231 +	if(!BuffersValid[level]) {
   1.232 +		const_cast<TriMesh*>(this)->UpdateSystemBuffers(level);
   1.233 +	}
   1.234 +	return vbuffer[level];
   1.235 +}
   1.236 +
   1.237 +const IndexBuffer *TriMesh::GetIndexBuffer(byte level) const {
   1.238 +	if(level >= Levels) return 0;
   1.239 +
   1.240 +	if(!BuffersValid[level]) {
   1.241 +		const_cast<TriMesh*>(this)->UpdateSystemBuffers(level);
   1.242 +	}
   1.243 +
   1.244 +	return ibuffer[level];
   1.245 +}
   1.246 +
   1.247 +		
   1.248 +dword TriMesh::GetVertexCount(byte level) const {
   1.249 +	if(level >= Levels) return 0xdeadbeef;
   1.250 +	return VertexCount[level];
   1.251 +}
   1.252 +
   1.253 +dword TriMesh::GetTriangleCount(byte level) const {
   1.254 +	if(level >= Levels) return 0xdeadbeef;
   1.255 +	return TriCount[level];
   1.256 +}
   1.257 +
   1.258 +byte TriMesh::GetLevelCount() const {
   1.259 +	return Levels;
   1.260 +}
   1.261 +
   1.262 +void TriMesh::SetGraphicsContext(GraphicsContext *gc) {
   1.263 +	this->gc = gc;
   1.264 +	memset(BuffersValid, 0, Levels * sizeof(bool));	// invalidate all system buffers in all levels
   1.265 +}
   1.266 +
   1.267 +void TriMesh::SetData(const Vertex *vdata, const Triangle *tridata, dword vcount, dword tricount) {
   1.268 +
   1.269 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.270 +	memset(AdjValid, 0, Levels * sizeof(bool));
   1.271 +	
   1.272 +	if(varray[0]) delete [] varray[0];
   1.273 +	if(triarray[0]) delete [] triarray[0];
   1.274 +	varray[0] = new Vertex[vcount];
   1.275 +	triarray[0] = new Triangle[tricount];
   1.276 +
   1.277 +	if(vdata) memcpy(varray[0], vdata, vcount * sizeof(Vertex));
   1.278 +	if(tridata) memcpy(triarray[0], tridata, tricount * sizeof(Triangle));
   1.279 +	VertexCount[0] = vcount;
   1.280 +	TriCount[0] = tricount;
   1.281 +
   1.282 +	UpdateLODChain();
   1.283 +}
   1.284 +
   1.285 +bool TriMesh::UpdateSystemBuffers(byte level) {
   1.286 +
   1.287 +	if(!gc || level >= Levels) return false;
   1.288 +
   1.289 +	if(vbuffer[level]) {
   1.290 +		D3DVERTEXBUFFER_DESC vbdesc;
   1.291 +		vbuffer[level]->GetDesc(&vbdesc);
   1.292 +		if(vbdesc.Size / sizeof(Vertex) != VertexCount[level]) {
   1.293 +			vbuffer[level]->Release();
   1.294 +
   1.295 +			if(gc->D3DDevice->CreateVertexBuffer(VertexCount[level] * sizeof(Vertex), dynamic ? D3DUSAGE_DYNAMIC : 0, VertexFormat, D3DPOOL_DEFAULT, &vbuffer[level]) != D3D_OK) {
   1.296 +				return false;
   1.297 +			}
   1.298 +		}
   1.299 +	} else {
   1.300 +		if(gc->D3DDevice->CreateVertexBuffer(VertexCount[level] * sizeof(Vertex), dynamic ? D3DUSAGE_DYNAMIC : 0, VertexFormat, D3DPOOL_DEFAULT, &vbuffer[level]) != D3D_OK) {
   1.301 +			return false;
   1.302 +		}
   1.303 +	}
   1.304 +	
   1.305 +	Vertex *vbdata;
   1.306 +	Lock(vbuffer[level], &vbdata);
   1.307 +	memcpy(vbdata, varray[level], VertexCount[level] * sizeof(Vertex));
   1.308 +	Unlock(vbuffer[level]);
   1.309 +
   1.310 +	if(ibuffer[level]) {
   1.311 +		D3DINDEXBUFFER_DESC ibdesc;
   1.312 +		ibuffer[level]->GetDesc(&ibdesc);
   1.313 +		if(ibdesc.Size / IndexSize != TriCount[level] * 3) {
   1.314 +			ibuffer[level]->Release();
   1.315 +
   1.316 +			if(gc->D3DDevice->CreateIndexBuffer(TriCount[level] * 3 * IndexSize, dynamic ? D3DUSAGE_DYNAMIC : 0, IndexFormat, D3DPOOL_DEFAULT, &ibuffer[level]) != D3D_OK) {
   1.317 +				return false;
   1.318 +			}
   1.319 +		}
   1.320 +	} else {
   1.321 +		if(gc->D3DDevice->CreateIndexBuffer(TriCount[level] * 3 * IndexSize, dynamic ? D3DUSAGE_DYNAMIC : 0, IndexFormat, D3DPOOL_DEFAULT, &ibuffer[level]) != D3D_OK) {
   1.322 +			return false;
   1.323 +		}
   1.324 +	}
   1.325 +
   1.326 +
   1.327 +	Index *ibdata;
   1.328 +	Lock(ibuffer[level], &ibdata);
   1.329 +	for(dword i=0; i<TriCount[level]; i++) {
   1.330 +		*ibdata++ = triarray[level][i].vertices[0];
   1.331 +		*ibdata++ = triarray[level][i].vertices[1];
   1.332 +		*ibdata++ = triarray[level][i].vertices[2];
   1.333 +	}
   1.334 +	Unlock(ibuffer[level]);
   1.335 +
   1.336 +	BuffersValid[level] = true;
   1.337 +	return true;
   1.338 +}
   1.339 +
   1.340 +void TriMesh::UpdateLODChain() {
   1.341 +	for(byte i=1; i<Levels; i++) {
   1.342 +		// TODO: apply mesh optimization, for now, just copy as it is
   1.343 +		VertexCount[i] = VertexCount[0];
   1.344 +		TriCount[i] = TriCount[0];
   1.345 +		
   1.346 +		if(!varray[i]) varray[i] = new Vertex[VertexCount[i]];
   1.347 +		memcpy(varray[i], varray[0], VertexCount[i] * sizeof(Vertex));
   1.348 +
   1.349 +		if(!triarray[i]) triarray[i] = new Triangle[TriCount[i]];
   1.350 +		memcpy(triarray[i], triarray[0], TriCount[i] * sizeof(Triangle));
   1.351 +
   1.352 +		UpdateSystemBuffers(i);
   1.353 +	}
   1.354 +
   1.355 +	if(!BuffersValid[0]) UpdateSystemBuffers(0);
   1.356 +}
   1.357 +
   1.358 +// TODO: this will brake currently with multiple LOD levels, revise LOD normal calculation
   1.359 +// and revise UpdateLODChain() too
   1.360 +void TriMesh::CalculateNormals() {
   1.361 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.362 +
   1.363 +	Triangle *tri = triarray[0];
   1.364 +	Triangle *tend = tri + TriCount[0];
   1.365 +
   1.366 +	while(tri != tend) {
   1.367 +		(*tri++).CalculateNormal(varray[0], false);
   1.368 +	}
   1.369 +
   1.370 +	/*
   1.371 +	Vertex *vert = varray[0];
   1.372 +	Vertex *vend = vert + VertexCount[0];
   1.373 +
   1.374 +	while(vert != vend) {
   1.375 +		(*vert++).CalculateNormal(varray[0], triarray[0], TriCount[0]);
   1.376 +	}
   1.377 +	*/
   1.378 +
   1.379 +	if(!AdjValid[0]) {
   1.380 +        if(AdjTriangles[0]) delete [] AdjTriangles[0];
   1.381 +		AdjTriangles[0] = new std::vector<dword>[VertexCount[0]];
   1.382 +	}
   1.383 +
   1.384 +	for(dword i=0; i<VertexCount[0]; i++) {
   1.385 +		if(AdjValid[0]) {
   1.386 +			assert(AdjTriangles[0]);
   1.387 +			Vector3 normal(0.0f, 0.0f, 0.0f);
   1.388 +			for(dword j=0; j<AdjTriangles[0][i].size(); j++) {
   1.389 +				normal += triarray[0][AdjTriangles[0][i][j]].normal;
   1.390 +			}
   1.391 +			normal.Normalize();
   1.392 +			varray[0][i].normal = normal;
   1.393 +		} else {
   1.394 +
   1.395 +			AdjTriangles[0][i].erase(AdjTriangles[0][i].begin(), AdjTriangles[0][i].end());
   1.396 +			Vector3 normal(0.0f, 0.0f, 0.0f);
   1.397 +			for(dword j=0; j<TriCount[0]; j++) {
   1.398 +				if(triarray[0][j].vertices[0] == i || triarray[0][j].vertices[1] == i || triarray[0][j].vertices[2] == i) {
   1.399 +					AdjTriangles[0][i].push_back(j);
   1.400 +					normal += triarray[0][j].normal;
   1.401 +				}
   1.402 +			}
   1.403 +			normal.Normalize();
   1.404 +			varray[0][i].normal = normal;
   1.405 +		}
   1.406 +	}
   1.407 +
   1.408 +	AdjValid[0] = true;
   1.409 +	
   1.410 +	UpdateLODChain();
   1.411 +}
   1.412 +
   1.413 +void TriMesh::CalculateNormalsFast() {
   1.414 +	memset(BuffersValid, 0, Levels * sizeof(bool));
   1.415 +
   1.416 +	Triangle *tri = triarray[0];
   1.417 +	Triangle *tend = tri + TriCount[0];
   1.418 +
   1.419 +	while(tri != tend) {
   1.420 +		tri->CalculateNormal(varray[0], true);
   1.421 +		varray[0][tri->vertices[0]].normal = tri->normal;
   1.422 +		varray[0][tri->vertices[1]].normal = tri->normal;
   1.423 +		varray[0][tri->vertices[2]].normal = tri->normal;
   1.424 +		tri++;
   1.425 +	}
   1.426 +
   1.427 +	UpdateLODChain();
   1.428 +}
   1.429 +
   1.430 +void TriMesh::ChangeMode(TriMeshMode mode) {
   1.431 +	dynamic = mode == TriMeshDynamic;
   1.432 +}
   1.433 +
   1.434 +/*
   1.435 +
   1.436 +void TriMesh::CalculateEdges() {
   1.437 +
   1.438 +	//build a list of triangles that share each vertex
   1.439 +	std::list<Triangle*> *ShareTris = new std::list<Triangle*>[VertexCount[0]];
   1.440 +
   1.441 +	for(dword i=0; i<VertexCount[0]; i++) {
   1.442 +        for(dword j=0; j<TriCount[0]; j++) {
   1.443 +			Index VertexIndex = (Index)((Vertex*)&varray[0][i] - (Vertex*)&varray[0][0]);
   1.444 +			if(triarray[0][j].vertices[0] == VertexIndex || triarray[0][j].vertices[1] == VertexIndex || triarray[0][j].vertices[2] == VertexIndex) {
   1.445 +				ShareTris[i].push_back(&triarray[0][j]);	// if it references this vertex add it
   1.446 +			}
   1.447 +		}
   1.448 +	}
   1.449 +
   1.450 +	// find the adjacent triangles of each edge
   1.451 +	for(dword i=0; i<TriCount[0]; i++) {
   1.452 +		Triangle *tri = &triarray[0][i];
   1.453 +
   1.454 +		for(int j=0; j<3; j++) {
   1.455 +			tri->edges[j].vertices[0] = tri->vertices[j];
   1.456 +			tri->edges[j].vertices[1] = tri->vertices[(j+1) % 3];
   1.457 +			tri->edges[j].adjfaces[0] = (Index)i;
   1.458 +		}
   1.459 +
   1.460 +		for(int j=0; j<3; j++) {
   1.461 +			Index v0 = (Index)((Vertex*)&varray[0][tri->edges[j].vertices[0]] - (Vertex*)&varray[0][0]);
   1.462 +			Index v1 = (Index)((Vertex*)&varray[0][tri->edges[j].vertices[1]] - (Vertex*)&varray[0][0]);
   1.463 +
   1.464 +			std::list<Triangle*>::iterator iter = ShareTris[v0].begin();
   1.465 +			while(iter != ShareTris[v0].end()) {
   1.466 +				Index TriIndex = (Index)(*iter - &triarray[0][0]);
   1.467 +				
   1.468 +				if((TriIndex != i) && ((*iter)->vertices[0] == v1 || (*iter)->vertices[1] == v1 || (*iter)->vertices[2] == v1)) {
   1.469 +					tri->edges[j].adjfaces[1] = TriIndex;
   1.470 +					break;
   1.471 +				}
   1.472 +				iter++;
   1.473 +			}
   1.474 +			if(iter == ShareTris[v0].end()) tri->edges[j].adjfaces[1] = (Index)0xffffffff;
   1.475 +		}
   1.476 +	}
   1.477 +
   1.478 +	// TODO: wield duplicate edges
   1.479 +}
   1.480 +
   1.481 +*/
   1.482 \ No newline at end of file