⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mesh.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / 3D rendering module * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include "mesh.h"#include "visual_surface.h"/*size alloc for meshes doubles memory at each realloc rather than using a fix-size increment  (this really speeds up large meshes constructing). Final memory usage is adjusted when updating mesh bounds*/#define MESH_CHECK_VERTEX(m)		\	if (m->v_count == m->v_alloc) {	\		m->v_alloc *= 2;	\		m->vertices = (GF_Vertex *)realloc(m->vertices, sizeof(GF_Vertex)*m->v_alloc);	\	}	\#define MESH_CHECK_IDX(m)		\	if (m->i_count == m->i_alloc) {	\		m->i_alloc *= 2;	\		m->indices = (IDX_TYPE*)realloc(m->indices, sizeof(IDX_TYPE)*m->i_alloc);	\	}	\static void del_aabb_node(AABBNode *node){	if (node->pos) del_aabb_node(node->pos);	if (node->neg) del_aabb_node(node->neg);	free(node);}void mesh_reset(GF_Mesh *mesh){	mesh->v_count = 0;	mesh->i_count = 0;	mesh->flags = 0;	mesh->mesh_type = 0;	memset(&mesh->bounds.min_edge, 0, sizeof(SFVec3f));	memset(&mesh->bounds.max_edge, 0, sizeof(SFVec3f));	if (mesh->aabb_root) del_aabb_node(mesh->aabb_root);	mesh->aabb_root = NULL;	if (mesh->aabb_indices) free(mesh->aabb_indices);	mesh->aabb_indices = NULL;}void mesh_free(GF_Mesh *mesh){	if (mesh->vertices) free(mesh->vertices);	if (mesh->indices) free(mesh->indices);	if (mesh->aabb_root) del_aabb_node(mesh->aabb_root);	mesh->aabb_root = NULL;	if (mesh->aabb_indices) free(mesh->aabb_indices);	free(mesh);}GF_Mesh *new_mesh(){	GF_Mesh *mesh = (GF_Mesh *)malloc(sizeof(GF_Mesh));	if (mesh) {		memset(mesh, 0, sizeof(GF_Mesh));		mesh->v_alloc = 8;		mesh->vertices = (GF_Vertex*)malloc(sizeof(GF_Vertex)*mesh->v_alloc);		mesh->i_alloc = 8;		mesh->indices = (IDX_TYPE*)malloc(sizeof(IDX_TYPE)*mesh->i_alloc);	}	return mesh;}static void mesh_fit_alloc(GF_Mesh *m){	if (m->v_count && (m->v_count < m->v_alloc)) {		m->v_alloc = m->v_count;		m->vertices = (GF_Vertex *)realloc(m->vertices, sizeof(GF_Vertex)*m->v_alloc);	}	if (m->i_count && (m->i_count  < m->i_alloc)) {		m->i_alloc = m->i_count;		m->indices = (IDX_TYPE*)realloc(m->indices, sizeof(IDX_TYPE)*m->i_alloc);	}}void mesh_update_bounds(GF_Mesh *mesh){	u32 i;	Fixed mx, my, mz, Mx, My, Mz;	mx = my = mz = FIX_MAX;	Mx = My = Mz = FIX_MIN;	mesh_fit_alloc(mesh);	for (i=0; i<mesh->v_count; i++) {		SFVec3f *v = &mesh->vertices[i].pos;		if (mx>v->x) mx=v->x;		if (my>v->y) my=v->y;		if (mz>v->z) mz=v->z;		if (Mx<v->x) Mx=v->x;		if (My<v->y) My=v->y;		if (Mz<v->z) Mz=v->z;	}	mesh->bounds.min_edge.x = mx; mesh->bounds.min_edge.y = my; mesh->bounds.min_edge.z = mz;	mesh->bounds.max_edge.x = Mx; mesh->bounds.max_edge.y = My; mesh->bounds.max_edge.z = Mz;	gf_bbox_refresh(&mesh->bounds);}void mesh_clone(GF_Mesh *dest, GF_Mesh *orig){	if (dest->v_alloc<orig->v_alloc) {		dest->v_alloc = orig->v_alloc;		dest->vertices = (GF_Vertex *)realloc(dest->vertices, sizeof(GF_Vertex)*dest->v_alloc);	}	dest->v_count = orig->v_count;	memcpy(dest->vertices, orig->vertices, sizeof(GF_Vertex)*dest->v_count);	if (dest->i_alloc < orig->i_alloc) {		dest->i_alloc = orig->i_alloc;		dest->indices = (IDX_TYPE*)realloc(dest->indices, sizeof(IDX_TYPE)*dest->i_alloc);	}	dest->i_count = orig->i_count;	memcpy(dest->indices, orig->indices, sizeof(IDX_TYPE)*dest->i_count);	dest->mesh_type = orig->mesh_type;	dest->flags = orig->flags;	dest->bounds = orig->bounds;	/*and reset AABB*/	if (dest->aabb_root) del_aabb_node(dest->aabb_root);	dest->aabb_root = NULL;	if (dest->aabb_indices) free(dest->aabb_indices);	dest->aabb_indices = NULL;}static GFINLINE GF_Vertex set_vertex(Fixed x, Fixed y, Fixed z, Fixed nx, Fixed ny, Fixed nz, Fixed u, Fixed v){	GF_Vertex res;	res.pos.x = x; res.pos.y = y; res.pos.z = z;	res.normal.x = nx; res.normal.y = ny; res.normal.z = nz;	gf_vec_norm(&res.normal);	res.texcoords.x = u; res.texcoords.y = v;	res.color.blue = res.color.red = res.color.green = res.color.alpha = FIX_ONE;	return res;}void mesh_set_vertex(GF_Mesh *mesh, Fixed x, Fixed y, Fixed z, Fixed nx, Fixed ny, Fixed nz, Fixed u, Fixed v){	MESH_CHECK_VERTEX(mesh);	mesh->vertices[mesh->v_count] = set_vertex(x, y, z, nx, ny, nz, u, v);	mesh->v_count++;}void mesh_set_vertex_v(GF_Mesh *mesh, SFVec3f pt, SFVec3f nor, SFVec2f tx, SFColorRGBA col){	MESH_CHECK_VERTEX(mesh);	mesh->vertices[mesh->v_count].pos = pt;	mesh->vertices[mesh->v_count].texcoords = tx;	mesh->vertices[mesh->v_count].color = col;	gf_vec_norm(&nor);	mesh->vertices[mesh->v_count].normal = nor;	mesh->v_count++;}void mesh_set_vertex_vx(GF_Mesh *mesh, GF_Vertex *vx){	MESH_CHECK_VERTEX(mesh);	mesh->vertices[mesh->v_count] = *vx;	mesh->v_count++;}void mesh_set_point(GF_Mesh *mesh, Fixed x, Fixed y, Fixed z, SFColorRGBA col){	MESH_CHECK_VERTEX(mesh);	mesh->vertices[mesh->v_count].pos.x = x;	mesh->vertices[mesh->v_count].pos.y = y;	mesh->vertices[mesh->v_count].pos.z = z;	mesh->vertices[mesh->v_count].normal.x = mesh->vertices[mesh->v_count].normal.y = mesh->vertices[mesh->v_count].normal.z = 0;	mesh->vertices[mesh->v_count].texcoords.x = mesh->vertices[mesh->v_count].texcoords.y = 0;	mesh->vertices[mesh->v_count].color = col;	mesh->v_count++;}void mesh_set_index(GF_Mesh *mesh, u32 idx){	MESH_CHECK_IDX(mesh);	mesh->indices[mesh->i_count] = (IDX_TYPE) idx;	mesh->i_count++;}void mesh_set_triangle(GF_Mesh *mesh, u32 v1_idx, u32 v2_idx, u32 v3_idx){	mesh_set_index(mesh, v1_idx);	mesh_set_index(mesh, v2_idx);	mesh_set_index(mesh, v3_idx);}void mesh_set_line(GF_Mesh *mesh, u32 v1_idx, u32 v2_idx){	mesh_set_index(mesh, v1_idx);	mesh_set_index(mesh, v2_idx);}void mesh_recompute_normals(GF_Mesh *mesh){	u32 i;	if (mesh->mesh_type) return;	for (i=0; i<mesh->i_count; i+=3) {		SFVec3f v1, v2, v3;		gf_vec_diff(v1, mesh->vertices[mesh->indices[i+1]].pos, mesh->vertices[mesh->indices[i]].pos);		gf_vec_diff(v2, mesh->vertices[mesh->indices[i+2]].pos, mesh->vertices[mesh->indices[i]].pos);		v3 = gf_vec_cross(v1, v2);		gf_vec_norm(&v3);		mesh->vertices[mesh->indices[i]].normal = v3;		mesh->vertices[mesh->indices[i+1]].normal = v3;		mesh->vertices[mesh->indices[i+2]].normal = v3;	}}void mesh_generate_tex_coords(GF_Mesh *mesh, GF_Node *__texCoords){	u32 i;	X_TextureCoordinateGenerator *txgen = (X_TextureCoordinateGenerator *)__texCoords;	if (!strcmp(txgen->mode.buffer, "SPHERE-LOCAL")) {		for (i=0; i<mesh->v_count; i++) {			GF_Vertex *vx = &mesh->vertices[i];			vx->texcoords.x = (vx->normal.x+FIX_ONE) / 2;			vx->texcoords.y = (vx->normal.y+FIX_ONE) / 2;		}	}	else if (!strcmp(txgen->mode.buffer, "COORD")) {		for (i=0; i<mesh->v_count; i++) {			GF_Vertex *vx = &mesh->vertices[i];			vx->texcoords.x = vx->pos.x;			vx->texcoords.y = vx->pos.y;		}	}}void mesh_new_box(GF_Mesh *mesh, SFVec3f size){	Fixed hx = size.x / 2;	Fixed hy = size.y / 2;	Fixed hz = size.z / 2;	mesh_reset(mesh);	/*back face (horiz flip of texcoords)*/	mesh_set_vertex(mesh,  hx, -hy, -hz,  0,  0, -FIX_ONE, 0, 0);	mesh_set_vertex(mesh, -hx, -hy, -hz,  0,  0, -FIX_ONE, FIX_ONE, 0);	mesh_set_vertex(mesh, -hx,  hy, -hz,  0,  0, -FIX_ONE, FIX_ONE, FIX_ONE);	mesh_set_vertex(mesh,  hx,  hy, -hz,  0,  0, -FIX_ONE, 0, FIX_ONE);	mesh_set_triangle(mesh, 0, 1, 2); mesh_set_triangle(mesh, 0, 2, 3);	/*top face*/	mesh_set_vertex(mesh, -hx,  hy,  hz,  0,  FIX_ONE,  0, 0, 0);	mesh_set_vertex(mesh,  hx,  hy,  hz,  0,  FIX_ONE,  0, FIX_ONE, 0);	mesh_set_vertex(mesh,  hx,  hy, -hz,  0,  FIX_ONE,  0, FIX_ONE, FIX_ONE);	mesh_set_vertex(mesh, -hx,  hy, -hz,  0,  FIX_ONE,  0, 0, FIX_ONE);	mesh_set_triangle(mesh, 4, 5, 6); mesh_set_triangle(mesh, 4, 6, 7);	/*front face*/	mesh_set_vertex(mesh, -hx, -hy,  hz,  0,  0,  FIX_ONE, 0, 0);	mesh_set_vertex(mesh,  hx, -hy,  hz,  0,  0,  FIX_ONE, FIX_ONE, 0);	mesh_set_vertex(mesh,  hx,  hy,  hz,  0,  0,  FIX_ONE, FIX_ONE, FIX_ONE);	mesh_set_vertex(mesh, -hx,  hy,  hz,  0,  0,  FIX_ONE, 0, FIX_ONE);	mesh_set_triangle(mesh, 8, 9, 10); mesh_set_triangle(mesh, 8, 10, 11);	/*left face*/	mesh_set_vertex(mesh, -hx, -hy, -hz, -FIX_ONE,  0,  0, 0, 0);	mesh_set_vertex(mesh, -hx, -hy,  hz, -FIX_ONE,  0,  0, FIX_ONE, 0);	mesh_set_vertex(mesh, -hx,  hy,  hz, -FIX_ONE,  0,  0, FIX_ONE, FIX_ONE);	mesh_set_vertex(mesh, -hx,  hy, -hz, -FIX_ONE,  0,  0, 0, FIX_ONE);	mesh_set_triangle(mesh, 12, 13, 14); mesh_set_triangle(mesh, 12, 14, 15);	/*bottom face*/	mesh_set_vertex(mesh, -hx, -hy, -hz,  0, -FIX_ONE,  0, 0, 0);	mesh_set_vertex(mesh,  hx, -hy, -hz,  0, -FIX_ONE,  0, FIX_ONE, 0);	mesh_set_vertex(mesh,  hx, -hy,  hz,  0, -FIX_ONE,  0, FIX_ONE, FIX_ONE);	mesh_set_vertex(mesh, -hx, -hy,  hz,  0, -FIX_ONE,  0, 0, FIX_ONE);	mesh_set_triangle(mesh, 16, 17, 18); mesh_set_triangle(mesh, 16, 18, 19);	/*right face*/	mesh_set_vertex(mesh,  hx, -hy,  hz,  FIX_ONE,  0,  0, 0, 0);	mesh_set_vertex(mesh,  hx, -hy, -hz,  FIX_ONE,  0,  0, FIX_ONE, 0);	mesh_set_vertex(mesh,  hx,  hy, -hz,  FIX_ONE,  0,  0, FIX_ONE, FIX_ONE);	mesh_set_vertex(mesh,  hx,  hy,  hz,  FIX_ONE,  0,  0, 0, FIX_ONE);	mesh_set_triangle(mesh, 20, 21, 22); mesh_set_triangle(mesh, 20, 22, 23);    mesh->flags |= MESH_IS_SOLID;	mesh->bounds.min_edge.x = -hx; mesh->bounds.min_edge.y = -hy; mesh->bounds.min_edge.z = -hz;	mesh->bounds.max_edge.x = hx; mesh->bounds.max_edge.y = hy; mesh->bounds.max_edge.z = hz;	gf_bbox_refresh(&mesh->bounds);	gf_mesh_build_aabbtree(mesh);}void mesh_new_unit_bbox(GF_Mesh *mesh){	SFColorRGBA col;	Fixed s = FIX_ONE/2;	memset(&col, 0, sizeof(SFColor));	col.alpha = 1;	mesh_reset(mesh);	mesh->mesh_type = MESH_LINESET;	mesh_set_point(mesh, -s, -s, -s,  col);	mesh_set_point(mesh, s, -s, -s,  col);	mesh_set_point(mesh, s, s, -s,  col);	mesh_set_point(mesh, -s, s, -s,  col);	mesh_set_point(mesh, -s, -s, s,  col);	mesh_set_point(mesh, s, -s, s,  col);	mesh_set_point(mesh, s, s, s,  col);	mesh_set_point(mesh, -s, s, s,  col);	mesh_set_line(mesh, 0, 1); mesh_set_line(mesh, 1, 2); mesh_set_line(mesh, 2, 3); mesh_set_line(mesh, 3, 0);	mesh_set_line(mesh, 4, 5); mesh_set_line(mesh, 5, 6); mesh_set_line(mesh, 6, 7); mesh_set_line(mesh, 7, 4);	mesh_set_line(mesh, 0, 4); 	mesh_set_line(mesh, 1, 5); 	mesh_set_line(mesh, 2, 6); 	mesh_set_line(mesh, 3, 7);	gf_bbox_refresh(&mesh->bounds);}static void compute_cylinder(Fixed height, Fixed radius, s32 numFacets, SFVec3f *coords, SFVec2f *texcoords){	Fixed angle, t, u;	s32 i;	t = height / 2;	for (i=0; i<numFacets; ++i) {		angle = i*GF_2PI / numFacets - GF_PI2;		coords[i].y = t;		coords[i].x = gf_mulfix(radius, gf_cos(angle));		coords[i].z = gf_mulfix(radius , gf_sin(angle));		u = FIX_ONE - i*FIX_ONE/numFacets;		texcoords[i].x = u;		texcoords[i].y = FIX_ONE;	}}#define CYLINDER_SUBDIV	24void mesh_new_cylinder(GF_Mesh *mesh, Fixed height, Fixed radius, Bool bottom, Bool side, Bool top, Bool low_res){	u32 nfacets, i, c_idx;	SFVec3f *coords;	SFVec2f *texcoords;	mesh_reset(mesh);	if (!bottom && !side && !top) return;	nfacets = CYLINDER_SUBDIV;	if (low_res) nfacets /= HIGH_SPEED_RATIO;	coords = (SFVec3f*) malloc(sizeof(SFVec3f) * nfacets);	texcoords = (SFVec2f*)malloc(sizeof(SFVec2f) * nfacets);	compute_cylinder(height, radius, nfacets, coords, texcoords);	if (side) {		for (i=0; i<nfacets; ++i) {			/*top*/			mesh_set_vertex(mesh, coords[i].x, coords[i].y, coords[i].z,								coords[i].x, 0, coords[i].z, 								texcoords[i].x, FIX_ONE);			/*bottom*/			mesh_set_vertex(mesh, coords[i].x, -1*coords[i].y, coords[i].z,								coords[i].x, 0, coords[i].z, 								texcoords[i].x, 0);			/*top circle is counterclockwise, reverse coords*/			if (i) {				mesh_set_triangle(mesh, mesh->v_count-4, mesh->v_count-1, mesh->v_count-3); 				mesh_set_triangle(mesh, mesh->v_count-4, mesh->v_count-2, mesh->v_count-1); 			}		}		/*top*/		mesh_set_vertex(mesh, coords[0].x, coords[0].y, coords[0].z,							coords[0].x, 0, coords[0].z, 							texcoords[0].x - FIX_ONE, FIX_ONE);		/*bottom*/		mesh_set_vertex(mesh, coords[0].x, -1*coords[0].y, coords[0].z,							coords[0].x, 0, coords[0].z, 							texcoords[0].x - FIX_ONE, 0);		mesh_set_triangle(mesh, mesh->v_count-4, mesh->v_count-1, mesh->v_count-3); 		mesh_set_triangle(mesh, mesh->v_count-4, mesh->v_count-2, mesh->v_count-1); 	}	if (bottom) {		Fixed angle = 0;		Fixed aincr = GF_2PI / nfacets;		mesh_set_vertex(mesh, 0, -height/2, 0, 0, -FIX_ONE, 0, FIX_ONE/2, FIX_ONE/2);		c_idx = mesh->v_count-1;		for (i=0; i<nfacets; ++i, angle += aincr) {			mesh_set_vertex(mesh, coords[i].x, -1*coords[i].y, coords[i].z,							0, -FIX_ONE, 0, 							(FIX_ONE + gf_sin(angle))/2, FIX_ONE - (FIX_ONE + gf_cos(angle))/2);			if (i) mesh_set_triangle(mesh, c_idx, mesh->v_count-2, mesh->v_count-1);		}		mesh_set_vertex(mesh, coords[0].x, -1*coords[0].y, coords[0].z,						0, -FIX_ONE, 0, 						(FIX_ONE + gf_sin(angle))/2, FIX_ONE - (FIX_ONE + gf_cos(angle))/2);		mesh_set_triangle(mesh, c_idx, mesh->v_count-2, mesh->v_count-1);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -