fp_t TriMesh_CalcTriDistortion_old( trimesh_knot_t *k1, trimesh_knot_t *k2, trimesh_knot_t *k3 ) { trimesh_vertex_t *v1, *v2, *v3; vec3d_t norm; vec3d_t cross; vec3d_t d1, d2; fp_t d; v1 = k1->vertex_ref; v2 = k2->vertex_ref; v3 = k3->vertex_ref; if ( !v1 || !v2 || !v3 ) Error( "not all vertex_refs are vaild\n" ); Vec3dCopy( norm, v1->norm ); Vec3dAdd( norm, norm, v2->norm ); Vec3dAdd( norm, norm, v3->norm ); Vec3dUnify( norm ); Vec3dSub( d1, v1->vec, v2->vec ); Vec3dSub( d2, v3->vec, v2->vec ); Vec3dUnify( d1 ); Vec3dUnify( d2 ); Vec3dCrossProduct( cross, d1, d2 ); Vec3dUnify( cross ); d = (Vec3dDotProduct( norm, cross )+1.0)*0.5; return d; }
/* ============================== U_VANormalize ============================== */ void U_VANormalize( vec3d_t inout[], int num ) { int i; vec3d_t min, max; vec3d_t delta; vec3d_t center; fp_t scale; Vec3dInitBB( min, max, 999999.9 ); for ( i = 0; i < num; i++ ) { Vec3dAddToBB( min, max, inout[i] ); } Vec3dSub( delta, max, min ); scale = 1.0; if ( delta[0] >= delta[1] && delta[0] >= delta[2] ) scale = delta[0]; else if ( delta[1] >= delta[0] && delta[1] >= delta[2] ) scale = delta[1]; else if ( delta[2] >= delta[0] && delta[2] >= delta[1] ) scale = delta[2]; Vec3dMA( center, 0.5, delta, min ); scale = 1.0 / scale; for ( i = 0; i < num; i++ ) { Vec3dSub( inout[i], center, inout[i] ); Vec3dScale( inout[i], scale, inout[i] ); } }
bool_t Vec3dInitPlane( vec3d_t norm, fp_t *dist, vec3d_t in1, vec3d_t in2, vec3d_t in3 ) { bool_t good; vec3d_t delta1, delta2; fp_t len; Vec3dSub( delta1, in2, in1 ); Vec3dSub( delta2, in3, in1 ); Vec3dCrossProduct( norm, delta1, delta2 ); len = norm[0]*norm[0] + norm[1]*norm[1] + norm[2]*norm[2]; if ( len < ON_EPSILON ) good = false; else good = true; len = 1.0/sqrt(len); norm[0]*=len; norm[1]*=len; norm[2]*=len; *dist = Vec3dDotProduct( in1, norm ); return good; }
surface_points_t* EvalSurfaceNormals( surface_points_t *in ) { vec3d_t un, vn; vec3d_t center; vec3d_t tmp; int unum, vnum; int u, v; vec3d_t norm; surface_points_t *nmesh; unum = in->upointnum; vnum = in->vpointnum; nmesh = NewSurfacePoints( unum, vnum ); for ( u = 0; u < unum; u++ ) for ( v = 0; v < vnum; v++ ) { GetSurfacePoint( in, u, v, center ); Vec3dInit( vn, 0, 0, 0 ); Vec3dInit( un, 0, 0, 0 ); if ( IsPointValid( u-1, v, unum, vnum ) ) { GetSurfacePoint( in, u-1, v, tmp ); Vec3dSub( tmp, center, tmp ); Vec3dAdd( un, tmp, un ); } if ( IsPointValid( u+1, v, unum, vnum ) ) { GetSurfacePoint( in, u+1, v, tmp ); Vec3dSub( tmp, tmp, center ); Vec3dAdd( un, tmp, un ); } if ( IsPointValid( u, v-1, unum, vnum ) ) { GetSurfacePoint( in, u, v-1, tmp ); Vec3dSub( tmp, center, tmp ); Vec3dAdd( vn, tmp, vn ); } if ( IsPointValid( u, v+1, unum, vnum ) ) { GetSurfacePoint( in, u, v+1, tmp ); Vec3dSub( tmp, tmp, center ); Vec3dAdd( vn, tmp, vn ); } Vec3dCrossProduct( norm, un, vn ); Vec3dUnify( norm ); SetSurfacePoint( nmesh, u, v, norm ); } return nmesh; }
// // colinear check // bool_t Vec3dCheckColinear( vec3d_t p1, vec3d_t p2, vec3d_t t ) { vec3d_t v1, v2; Vec3dSub( v1, p1, t ); Vec3dSub( v2, t, p2 ); if ( Vec3dUnify( v1 ) < 0.01 ) return true; if ( Vec3dUnify( v2 ) < 0.01 ) return true; if ( Vec3dDotProduct( v1, v2 ) > 0.999 ) return true; return false; }
void Vec3dInitPlane( plane_t *p, vec3d_t v0, vec3d_t v1, vec3d_t v2 ) { vec3d_t tv1, tv2; Vec3dSub( tv1, v1, v0 ); Vec3dSub( tv2, v2, v0 ); Vec3dCrossProduct( p->norm, tv1, tv2 ); Vec3dUnify( p->norm ); p->dist = Vec3dDotProduct( v0, p->norm ); }
polygon_t* BasePolygonForPlane( vec3d_t norm, fp_t dist ) { int i; vec3d_t absnorm; vec3d_t org, vup, vright; fp_t d; polygon_t *p; Vec3dInit( vup, 0,0,0 ); p = NewPolygon( 4 ); for ( i=0; i<3; i++ ) absnorm[i] = fabs( norm[i] ); if ( absnorm[0] >= absnorm[1] && absnorm[0] >= absnorm[2] ) vup[2] = 1.0; else if ( absnorm[1] >= absnorm[0] && absnorm[1] >= absnorm[2] ) vup[2] = 1.0; else if ( absnorm[2] >= absnorm[0] && absnorm[2] >= absnorm[1] ) vup[0] = 1.0; d = Vec3dDotProduct( vup, norm ); Vec3dMA( vup, -d, norm, vup ); Vec3dUnify( vup ); Vec3dScale( org, dist, norm ); Vec3dCrossProduct( vright, norm, vup ); Vec3dScale( vup, BASE_POLYGON_SIZE, vup ); Vec3dScale( vright, BASE_POLYGON_SIZE, vright ); Vec3dSub( p->p[0], org, vright ); Vec3dSub( p->p[0], p->p[0], vup ); Vec3dSub( p->p[1], org, vright ); Vec3dAdd( p->p[1], p->p[1], vup ); Vec3dAdd( p->p[2], org, vright ); Vec3dAdd( p->p[2], p->p[2], vup ); Vec3dAdd( p->p[3], org, vright ); Vec3dSub( p->p[3], p->p[3], vup ); p->pointnum = 4; return p; }
// // PolygonArea // fp_t PolygonArea( polygon_t *in ) { int i; vec3d_t v1, v2, norm; fp_t area; area = 0; for ( i = 2; i < in->pointnum; i++ ) { Vec3dSub( v1, in->p[i-1], in->p[0] ); Vec3dSub( v2, in->p[i], in->p[0] ); Vec3dCrossProduct( norm, v1, v2 ); area += 0.5 * Vec3dLen( norm ); } return area; }
bool IntersectSpheredSphered(const Point3d center1, F64 radius1, const Point3d center2, F64 radius2) { Vec3d d; Vec3dSub(center1.point, center2.point, &d); F64 dist2; dist2 = Vec3dDot(d,d); //intersect if squared distance is less than squared sum of radius F64 radiusSum = radius1 + radius2; return dist2 <= radiusSum * radiusSum; }
// Compute indices to the two most separated points of the points defining the AABB encompassing the point set. // return these ad outMin and outMax void MostDistantPoints3d(Point3d* ptList, int ptCount, int* outMin, int* outMax) { int minX = 0; int maxX = 0; int minY = 0; int maxY = 0; int minZ = 0; int maxZ = 0; for(int i = 1; i<ptCount; ++i) { if (ptList[i].point.x < ptList[minX].point.x) minX = i; if (ptList[i].point.x > ptList[maxX].point.x) maxX = i; if (ptList[i].point.y < ptList[minY].point.y) minY = i; if (ptList[i].point.y > ptList[maxY].point.y) maxY = i; if (ptList[i].point.z < ptList[minZ].point.z) minZ = i; if (ptList[i].point.z > ptList[maxZ].point.z) maxZ = i; } Vec3d tempVec1; Vec3dSub( ptList[maxX].point, ptList[minX].point, &tempVec1 ); F64 dist2X = Vec3dDot( tempVec1 , tempVec1 ); Vec3dSub( ptList[maxY].point, ptList[minY].point, &tempVec1 ); F64 dist2Y = Vec3dDot( tempVec1 , tempVec1 ); Vec3dSub( ptList[maxZ].point, ptList[minZ].point, &tempVec1 ); F64 dist2Z = Vec3dDot( tempVec1 , tempVec1 ); int tempMin = minX; int tempMax = maxX; if (dist2Y > dist2X && dist2Y > dist2Z) { tempMax = maxY; tempMin = minY; } if (dist2Z > dist2X && dist2Z > dist2Y) { tempMax = maxZ; tempMin = minZ; } *outMax = tempMax; *outMin = tempMin; }
/* ============================== Trify_SetupPlane ============================== */ void Trify_SetupPlane( vec3d_t norm, fp_t *dist, vec3d_t p1, vec3d_t p2 ) { vec3d_t v1; Vec3dSub( v1, p2, p1 ); Vec3dUnify( v1 ); Vec3dCrossProduct( norm, v1, t_norm ); *dist = Vec3dDotProduct( norm, p1 ); // Vec3dPrint( norm ); }
bool_t CheckCollinearEdge_old( vec3d_t p1, vec3d_t p2, vec3d_t t ) { vec3d_t v; fp_t d, d1, d2; Vec3dSub( v, p2, p1 ); d = Vec3dLen( v ); Vec3dSub( v, t, p1 ); d1 = Vec3dLen( v ); Vec3dSub( v, t, p2 ); d2 = Vec3dLen( v ); if ( fabs( (d1+d2) - d ) < 0.5 ) return true; return false; }
void MergeSpheredSphered3d(const Sphered& a, const Sphered& b, Sphered* outSphered) { //Optimize checking if included Vec3d tempVec; Vec3dSum( a.center.point, b.center.point, &tempVec ); Vec3dMultScalarInplace( 0.5, &tempVec ); outSphered->center.point = tempVec; Vec3dSub(a.center.point, b.center.point, &tempVec); F64 distBwCenters = Vec3dGetLenght(tempVec); outSphered->radius = Div2d( a.radius + b.radius + distBwCenters ); }
void FixPolygon2( polygon_t *inout, vec3d_t center ) { vec3d_t vright = { 1, 0, 0 }; int i, j; vec3d_t v; fp_t t; fp_t dx, dy, ax, ay; int best; fp_t min; vec3d_t tmp; for ( j = 0; j < inout->pointnum; j++ ) { min = 999999.9; best = -1; for ( i = j; i < inout->pointnum; i++ ) { Vec3dSub( v, inout->p[i], center ); Vec3dUnify( v ); dx = v[0]; dy = v[2]; ax = fabs( dx ); ay = fabs( dy ); t = (ax+ay == 0) ? 0 : (dy/(ax+ay)); if ( dx < 0.0 ) t = 2-t; else if ( dy < 0 ) t = 4+t; t *= 90.0; printf( "%f\n", t ); if ( t < min ) { min = t; best = i; } } printf( "best: %d %f\n ", best, min ); // SWAP Vec3dCopy( tmp, inout->p[j] ); Vec3dCopy( inout->p[j], inout->p[best] ); Vec3dCopy( inout->p[best], tmp ); } printf( "\n" ); }
/* ============================== TriMesh_CalcAllTriNormals ============================== */ static void CalcTriNormalFunc( void *obj ) { trimesh_tri_t *tri = obj; trimesh_vertex_t *v1, *v2, *v3; vec3d_t d1, d2; v1 = tri->knot_refs[0]->vertex_ref; v2 = tri->knot_refs[1]->vertex_ref; v3 = tri->knot_refs[2]->vertex_ref; if ( !v1 || !v2 || !v3 ) Error( "not all knots have valid vertex_refs\n" ); Vec3dSub( d1, v1->vec, v2->vec ); Vec3dSub( d2, v3->vec, v2->vec ); Vec3dUnify( d1 ); Vec3dUnify( d2 ); Vec3dCrossProduct( tri->norm, d1, d2 ); Vec3dUnify( tri->norm ); // printf( "tri_norm: %f\n", Vec3dLen( tri->norm ) ); }
void *WayNetFindBest( vec3d_t origin ) { ati_t *best; ati_t *ati; u_list_iter_t iter; fp_t bestlen; U_ListIterInit( &iter, waynet ); best = NULL; for( ;( ati = ( ati_t * )U_ListIterNext( &iter )); ) { vec3d_t lenvec1, vec; fp_t len; if( !best ) { best = ati; ati->ftbl->GetOrigin( ati, vec ); Vec3dSub( lenvec1, origin, vec ); bestlen = Vec3dLen( lenvec1 ); continue; } ati->ftbl->GetOrigin( ati, vec ); Vec3dSub( lenvec1, origin, vec ); len = Vec3dLen( lenvec1 ); if( len <= bestlen ) { best = ati; bestlen = len; } } return ( void * )best; }
/* ============================== TriMesh_CalcTriArea ============================== */ fp_t TriMesh_CalcTriArea( trimesh_tri_t *tri ) { trimesh_vertex_t *v1, *v2, *v3; vec3d_t cross; fp_t area; vec3d_t d1, d2; v1 = tri->knot_refs[0]->vertex_ref; v2 = tri->knot_refs[1]->vertex_ref; v3 = tri->knot_refs[2]->vertex_ref; if ( !v1 || !v2 || !v3 ) Error( "not all knots have valid vertex_refs\n" ); Vec3dSub( d1, v2->vec, v1->vec ); Vec3dSub( d2, v3->vec, v1->vec ); Vec3dCrossProduct( cross, d1, d2 ); area = Vec3dLen( cross ) * 0.5; return area; }
bool_t Trify_TestTri( vec3d_t p1, vec3d_t p2, vec3d_t p3, vec3d_t t ) { vec3d_t sum; vec3d_t v1, v2, v3, norm; Vec3dSub( v1, p1, t ); Vec3dSub( v2, p2, t ); Vec3dSub( v3, p3, t ); Vec3dCrossProduct( sum, v1, v2 ); Vec3dUnify( sum ); Vec3dCrossProduct( norm, v2, v3 ); Vec3dUnify( norm ); Vec3dAdd( sum, sum, norm ); Vec3dCrossProduct( norm, v3, v1 ); Vec3dUnify( norm ); Vec3dAdd( sum, sum, norm ); // printf( "len: %f\n", Vec3dLen( sum ) ); if ( Vec3dLen( sum ) < 2.9 ) return false; return true; }
// Bounding Sphered from a set of points void BoundingSphered( Point3d* ptList, int ptCount, Sphered* outSphered) { int min; int max; Vec3d tempVec; MostDistantPoints3d( ptList , ptCount , &min , &max ); Vec3dSum( ptList[min].point , ptList[max].point, &tempVec ); Vec3dMultScalarInplace( 0.5 , &tempVec ); outSphered->center.point = tempVec; Vec3dSub( ptList[max].point , outSphered->center.point , &tempVec ); outSphered->radius = Vec3dDot( tempVec , tempVec ); outSphered->radius = Sqrtd( outSphered->radius ); }
fp_t ApproxCurveLength( int num, vec3d_t pts[] ) { int i; vec3d_t v; fp_t l; l = 0; for( i = 0; i < num-1; i++ ) { Vec3dSub( v, pts[i], pts[i+1] ); l += Vec3dLen( v ); } return l; }
/* ============================== NormalizePolygonList ============================== */ void NormalizePolygonList( u_list_t *poly_list ) { int i; u_list_iter_t iter; polygon_t *p; vec3d_t min, max; vec3d_t scale; Vec3dInitBB( min, max, 999999.9 ); U_ListIterInit( &iter, poly_list ); for ( ; ( p = U_ListIterNext( &iter ) ) ; ) { for ( i = 0; i < p->pointnum; i++ ) { Vec3dAddToBB( min, max, p->p[i] ); } } // shift to (0,0,0) U_ListIterInit( &iter, poly_list ); for ( ; ( p = U_ListIterNext( &iter ) ) ; ) { for ( i = 0; i < p->pointnum; i++ ) { Vec3dSub( p->p[i], p->p[i], min ); } } // scale to (0,0,0)-(1,1,1) scale[0] = 1.0/(max[0]-min[0]); scale[1] = 1.0/(max[1]-min[1]); scale[2] = 1.0/(max[2]-min[2]); U_ListIterInit( &iter, poly_list ); for ( ; ( p = U_ListIterNext( &iter ) ) ; ) { for ( i = 0; i < p->pointnum; i++ ) { p->p[i][0] *= scale[0]; p->p[i][1] *= scale[1]; p->p[i][2] *= scale[2]; } } }
/* ============================== TriMesh_AddFreeVertex ============================== */ unique_t TriMesh_AddFreeVertex( trimesh_t *mesh, vec3d_t v, fp_t merge_dist ) { u_list_iter_t iter; fp_t len, best_len; trimesh_vertex_t *vertex, *best_vertex; vec3d_t delta; best_len = 9999999.9; best_vertex = NULL; U_ListIterInit( &iter, &mesh->vertex_list ); for ( ; ( vertex = U_ListIterNext( &iter ) ) ; ) { Vec3dSub( delta, v, vertex->vec ); len = Vec3dLen( delta ); if ( len <= merge_dist ) { if ( len < best_len ) { best_len = len; best_vertex = vertex; } } } if ( !best_vertex ) { // create a new vertex best_vertex = NEWTYPE( trimesh_vertex_t ); best_vertex->id = HManagerGetFreeID(); Vec3dCopy( best_vertex->vec, v ); U_ListInsertAtHead( &mesh->vertex_list, best_vertex ); } return best_vertex->id; }
bool IntersectRaySphered( const Point3d& origin, const Direction3d& direction, const Point3d& centerSph, F64 radius, F64& t, Point3d& q ) { Vec3d m; Vec3dSub( origin.point , centerSph.point, &m ); F64 b = Vec3dDot( m , direction.dir ); F64 c = Vec3dDot( m , m ) - radius * radius; // Exit if rís origin outside s (c > 0) and r pointing away from s (b > 0) if(c > 0.0 && b > 0.0) return false; F64 discr = b * b - c; // A negative discriminant corresponds to ray missing sphere if (discr < 0.0) return false; // Ray now found to intersect sphere, compute smallest t value of intersection t = -b - Sqrtd(discr); // If t is negative, ray started inside sphere so clamp t to zero if (t < 0.0) t = 0.0; Vec3d tempRes = direction.dir; Vec3dMultScalarInplace( t , &tempRes ); Vec3dSumInplace( origin.point , &tempRes ); q.point = tempRes; return true; }
/* ============================== RunRocket ============================== */ static void RunRocket( cl_ati_t *atif ) { cl_at_rocket_t *rocket; rocket = ADDR_OF_BASE( cl_at_rocket_t, atif, atif ); if ( !rocket->init ) { int i; vec3d_t axis[3] = { {1,0,0}, {0,1,0}, {0,0,1} }; rocket->init = true; rocket->ri_model.md = CL_CreateModelFromResourceName( "rocket1" ); for ( i = 0; i < 3; i++ ) Vec3dCopy( rocket->ri_model.ref_axis[i], axis[i] ); } if ( rocket->u_ipo_mask ) { rocket->u_ipo_mask = false; Vec3dCopy( rocket->ipo1, rocket->u_ipo1 ); Vec3dCopy( rocket->ipo2, rocket->u_ipo2 ); { cl_ati_t *expl; expl = CL_CreateExplosion( rocket->ipo1, explosionStyle_smoke1 ); U_ListInsertAtHead( &cl_ati_wakeup_list, expl ); } } if ( rocket->u_angles_mask ) { rocket->u_angles_mask = false; rocket->lon = rocket->u_lon; rocket->lat = rocket->u_lat; } if ( rocket->u_style_mask ) { rocket->u_style_mask = false; rocket->style = rocket->u_style; } // do spin { Matrix3SetupRotate( rocket->ri_model.ref_axis, rocket->u_lat*D2R, (cl_time_begin_frame/3.6)*D2R, rocket->u_lon*D2R ); } // // do ipo // { fp_t scale; vec3d_t delta; // Vec3dPrint( view->ipo1 ); // Vec3dPrint( view->ipo2 ); scale = (cl_sv_time)/(cl_sv_time_delta); // printf( "scale: %f\n", scale ); Vec3dSub( delta, rocket->ipo2, rocket->ipo1 ); Vec3dMA( rocket->origin, scale, delta, rocket->ipo1 ); } if ( rocket->style == rocketStyle_fly ) { // model Vec3dCopy( rocket->ri_model.ref_origin, rocket->origin ); g_api.Render_Model( &rocket->ri_model ); // nozzle { Vec3dMA( rocket->ri_sprite.origin, -16.0, rocket->ri_model.ref_axis[0], rocket->origin ); } rocket->ri_sprite.rgba[0] = 0xaf; rocket->ri_sprite.rgba[1] = 0xaf; rocket->ri_sprite.rgba[2] = 0xff; rocket->ri_sprite.rgba[3] = 255; rocket->ri_sprite.width = 2.0; rocket->ri_sprite.height = 2.0; rocket->ri_sprite.rotate = cl_time_begin_frame; rocket->ri_sprite.gltex_res = g_api.GI_ResourceSearch( "gltex.fx.halo1" ); g_api.Render_Sprite( &rocket->ri_sprite ); // local light { vec3d_t rel_min = { -128, -128, -128 }; vec3d_t rel_max = { 128, 128, 128 }; // // set a local light // Vec3dCopy( rocket->ri_llight.origin, rocket->origin ); Vec3dInit( rocket->ri_llight.color, 1.0, 0.7, 0.0 ); rocket->ri_llight.value = 100; Vec3dAdd( rocket->ri_llight.min, rocket->origin, rel_min ); Vec3dAdd( rocket->ri_llight.max, rocket->origin, rel_max ); g_api.Render_LocalLight( &rocket->ri_llight ); } } if ( rocket->style == rocketStyle_impact ) { { cl_ati_t *expl; vec3d_t fly_dir; vec3d_t expl_pos; Vec3dSub( fly_dir, rocket->ipo2, rocket->ipo1 ); Vec3dUnify( fly_dir ); Vec3dMA( expl_pos, -64.0, fly_dir, rocket->ipo2 ); expl = CL_CreateExplosion( expl_pos, explosionStyle_hot1 ); U_ListInsertAtHead( &cl_ati_wakeup_list, expl ); // Util_SpawnTmpObject( expl ); } rocket->style = rocketStyle_none; } }
void TriMesh_RemoveKnotAndFix( trimesh_t *mesh, trimesh_knot_t *rm_knot ) { int i; int num; trimesh_knot_t *start, *knot, *prev, *next; trimesh_knot_t *best_knot, *best_prev, *best_next; unique_t knot_ids[3]; static unique_t tri_id_count = 1000000; fp_t d, e; fp_t best_v, v; bool_t hack; if ( rm_knot->id == 31486 ) hack = true; else hack = false; hack = false; U_InitRing( &g_knot_ring ); U_InitRing( &g_tri_ring ); if ( !TriMesh_VisitKnotTrisInOrder( rm_knot, VisitKnotFunc ) ) { // there is a hole in the mesh, can't remove this knot ... return; } // test knot_ring num = U_RingSize( &g_knot_ring ); // printf( "knot_ring size: %d\n", num ); for ( i = 0; i < num; i++ ) { knot = U_RingGetCurrent( &g_knot_ring ); // printf( "knot_ring: #%u\n", knot->id ); U_RingWalk( &g_knot_ring, 1 ); } // remove all tris in tri_ring from trimesh GLD_BeginList( g_gldbg, "remove", "fill" ); GLD_Color3f( g_gldbg, 1.0, 0.0, 0.0 ); num = U_RingSize( &g_tri_ring ); for ( i = 0; i < num; i++ ) { trimesh_tri_t *tri; tri = U_RingGetCurrent( &g_tri_ring ); // printf( "remove: #%u\n", tri->id ); if ( !hack ) TriMesh_GLDBG_tri( tri ); TriMesh_RemoveTri( mesh, tri ); U_RingWalk( &g_tri_ring, 1 ); } GLD_Color3f( g_gldbg, 1.0, 1.0, 1.0 ); GLD_EndList( g_gldbg ); for (;;) { num = U_RingSize( &g_knot_ring ); if ( num > 3 ) { best_v = -999999; best_knot = NULL; for ( i = 0; i < num; i++, U_RingWalk( &g_knot_ring, 1 ) ) { trimesh_vertex_t *v1, *v2, *v3; vec3d_t d1, d2; prev = U_RingGetCurrentPrev( &g_knot_ring ); knot = U_RingGetCurrent( &g_knot_ring ); next = U_RingGetCurrentNext( &g_knot_ring ); // check tri's orientation if ( TriMesh_DoEdgeExist( prev, knot ) || TriMesh_DoEdgeExist( knot, next ) || TriMesh_DoEdgeExist( next, prev ) ) { // printf( "orientation check failed\n" ); continue; } v1 = prev->vertex_ref; v2 = knot->vertex_ref; v3 = next->vertex_ref; if ( !v1 || !v2 || !v3 ) Error( "not all knots have valid vertex_refs\n" ); Vec3dSub( d1, v1->vec, v2->vec ); Vec3dSub( d2, v3->vec, v2->vec ); Vec3dUnify( d1 ); Vec3dUnify( d2 ); d = (Vec3dDotProduct( d1, d2 )+1.0)*0.5; e = TriMesh_CalcTriDistortion( prev, knot, next ); // printf( "ring: #%u-#%u-#%u, d %f, e %f\n", prev->id, knot->id, next->id, d, e ); v = e*1.0 + d*0.0; if ( 1 ) { if ( v > best_v ) { best_v = v; best_prev = prev; best_knot = knot; best_next = next; } } } if ( !best_knot || !best_prev || !best_next ) Error( "can't find knot to remove\n" ); if ( !U_RingSearchObj( &g_knot_ring, best_knot ) ) Error( "? missing best_knot\n" ); U_RingRemoveGoPrev( &g_knot_ring ); // printf( "new tri #%u: #%u-#%u-#%u\n", tri_id_count, best_prev->id, best_knot->id, best_next->id ); knot_ids[0] = best_prev->id; knot_ids[1] = best_knot->id; knot_ids[2] = best_next->id; // printf( "tri distortion: %.2f\n", TriMesh_CalcTriDistortion( best_prev, best_knot, best_next ) ); if ( !hack ) { TriMesh_AddTri( mesh, tri_id_count++, knot_ids ); } else { TriMesh_GLDBG_knots( best_prev, best_knot, best_next ); } } else if ( num == 3 ) { prev = U_RingGetCurrentPrev( &g_knot_ring ); knot = U_RingGetCurrent( &g_knot_ring ); next = U_RingGetCurrentNext( &g_knot_ring ); U_CleanUpRing( &g_knot_ring, NULL ); // printf( "last new tri #%u: #%u-#%u-#%u\n", tri_id_count, prev->id, knot->id, next->id ); // printf( "tri distortion: %.2f\n", TriMesh_CalcTriDistortion( prev, knot, next ) ); knot_ids[0] = prev->id; knot_ids[1] = knot->id; knot_ids[2] = next->id; if ( !hack ) { TriMesh_AddTri( mesh, tri_id_count++, knot_ids ); } else { TriMesh_GLDBG_knots( prev, knot, next ); } break; } else { Error( "less than 3 knots\n" ); } } if ( hack ) { GLD_Color3f( g_gldbg, 1.0, 1.0, 1.0 ); GLD_EndList( g_gldbg ); } }
planeSlope TryMove( vec3d_t pos, vec3d_t trypos ) { int i; g_trace_t *tr; planeSlope slope; vec3d_t min; vec3d_t max; vec3d_t trymin; vec3d_t trymax; fp_t dist; vec3d_t norm; vec3d_t p1, p2, vec; vec3d_t minspace = { 16, 64, 16 }; vec3d_t maxspace = { 16, 0, 16 }; Vec3dSub( min, pos, minspace ); Vec3dAdd( max, pos, maxspace ); Vec3dSub( trymin, trypos, minspace ); Vec3dAdd( trymax, trypos, maxspace ); #if 0 for ( i = 0; i < 3; i++ ) { min[i] = pos[i] - 16.0; max[i] = pos[i] + 16.0; trymin[i] = trypos[i] - 16.0; trymax[i] = trypos[i] + 16.0; } #endif slope = PlaneSlope_none; tr = li.TraceBB( min, max, trymin, trymax ); if ( tr->plane ) { Vec3dCopy( norm, tr->plane->norm ); slope = GetPlaneSlope( norm ); dist = tr->plane->dist; Vec3dProjectOnPlane( p1, norm, dist, min ); Vec3dProjectOnPlane( p2, norm, dist, trymin ); Vec3dSub( vec, p2, p1 ); Vec3dAdd( trymin, vec, min ); Vec3dAdd( trymax, vec, max ); tr = li.TraceBB( min, max, trymin, trymax ); if ( tr->plane ) { printf( "bounce again\n" ); Vec3dCopy( trypos, pos ); return GetPlaneSlope( tr->plane->norm );; } } Vec3dCopy( min, trymin ); Vec3dCopy( max, trymax ); // Vec3dAdd( vec, min, max ); // Vec3dScale( trypos, 0.5, vec ); Vec3dAdd( trypos, trymin, minspace ); return slope; }
planeSlope TryMoveVolume( move_volume_t *vol ) { int i; g_trace_t *tr; planeSlope slope; vec3d_t min; vec3d_t max; vec3d_t trymin; vec3d_t trymax; vec3d_t pos, trypos; fp_t dist; vec3d_t norm; vec3d_t p1, p2, vec; vec3d_t minspace; vec3d_t maxspace; slope = PlaneSlope_none; L_MoveVolumeGetFromBoundBox( vol, min, max ); L_MoveVolumeGetToBoundBox( vol, trymin, trymax ); L_MoveVolumeGetFromPos( vol, pos ); L_MoveVolumeGetToPos( vol, trypos ); tr = li.TraceBB( min, max, trymin, trymax ); if ( tr->plane ) { Vec3dCopy( norm, tr->plane->norm ); slope = GetPlaneSlope( norm ); dist = tr->plane->dist; Vec3dProjectOnPlane( p1, norm, dist, min ); Vec3dProjectOnPlane( p2, norm, dist, trymin ); Vec3dSub( vec, p2, p1 ); Vec3dAdd( trymin, vec, min ); Vec3dAdd( trymax, vec, max ); tr = li.TraceBB( min, max, trymin, trymax ); if ( tr->plane ) { printf( "bounce again\n" ); // Vec3dCopy( trypos, pos ); // L_MoveVolumeSetToPos( vol, pos ); L_MoveVolumeStay( vol ); return GetPlaneSlope( tr->plane->norm ); } } Vec3dCopy( min, trymin ); Vec3dCopy( max, trymax ); L_MoveVolumeGetRelativeBoundBox( vol, minspace, maxspace ); Vec3dSub( trypos, trymin, minspace ); L_MoveVolumeSetToPos( vol, trypos ); return slope; }
int main( int argc, char *argv[] ) { char *in_brush_name; char *out_shape_name; char *out_glmesh_name; char *in_plane_name; char *in_texdef_name; char *in_texture_name; char *in_tm_name; char *path_name; hobj_t *brush_root; hmanager_t *plane_hm; hmanager_t *texdef_hm; hmanager_t *texture_hm; hobj_t *tm_root; hobj_t *meshtile_root; hobj_search_iterator_t brush_iter; hobj_search_iterator_t surf_iter; hobj_search_iterator_t surf2_iter; hobj_t *brush; hobj_t *surf; hobj_t *surf2; hobj_t *shape_root; hobj_t *shape; FILE *h; int num_total_tris; char tt[256]; gld = GLD_BeginSession( "xxx" ); GLD_StartRecord( gld ); GLD_BeginList( gld, "polys", "line" ); puts( "===== meshtile1 - create meshtiles from surfaces =====" ); SetCmdArgs( argc, argv ); if ( argc == 1 ) { puts( "usage:" ); puts( " -i : input bspbrush class" ); puts( " -o : output shape class" ); puts( " -obin : output glmesh binary" ); puts( " -pl : input plane class" ); puts( " -td : input texdef class" ); puts( " -tx : input texture class" ); puts( " -tm : input texture material class" ); puts( " -path : config path to ./shape_config and ./meshtiles" ); exit(-1); } in_brush_name = GetCmdOpt2( "-i" ); out_shape_name = GetCmdOpt2( "-o" ); out_glmesh_name = GetCmdOpt2( "-obin" ); in_plane_name = GetCmdOpt2( "-pl" ); in_texdef_name = GetCmdOpt2( "-td" ); in_texture_name = GetCmdOpt2( "-tx" ); in_tm_name = GetCmdOpt2( "-tm" ); path_name = GetCmdOpt2( "-path" ); if ( !in_brush_name ) Error( "no input bspbrush class\n" ); if ( !out_shape_name ) Error( "no output shape class\n" ); if ( !out_glmesh_name ) Error( "no output glmesh binary\n" ); if ( !in_plane_name ) Error( "no input plane class\n" ); if ( !in_texdef_name ) Error( "no input texdef class\n" ); if ( !in_texture_name ) Error( "no input texture class\n" ); if ( !in_tm_name ) Error( "no input texture material class\n" ); if ( !path_name ) Error( "no config path\n" ); brush_root = ReadClassFile( in_brush_name ); if ( !brush_root ) Error( "can't read bspbrush class\n" ); texdef_hm = NewHManagerLoadClass( in_texdef_name ); if ( !texdef_hm ) Error( "can't read texdef class\n" ); plane_hm = ReadPlaneClass( in_plane_name ); texture_hm = NewHManagerLoadClass( in_texture_name ); if ( !texture_hm ) Error( "can't read texture class\n" ); tm_root = ReadClassFile( in_tm_name ); if ( !tm_root ) Error( "can't read texture material class" ); sprintf( tt, "%s/shape_config/meshtile.hobj", path_name ); meshtile_root = ReadClassFile( tt ); if ( !meshtile_root ) Error( "can't read meshtile class ( %s )\n", tt ); shape_root = NewClass( "shapes", "meshtiles0" ); // // for all c5 brushes // num_total_tris = 0; InitClassSearchIterator( &brush_iter, brush_root, "bspbrush" ); for ( ; ( brush = SearchGetNextClass( &brush_iter ) ) ; ) { int b_contents; int num_surf; vec3d_t v; hobj_t *surf_poly_obj; polygon_t *surf_poly; EasyFindInt( &b_contents, brush, "content" ); if ( b_contents != 5 ) { continue; } // // for all surfaces // InitClassSearchIterator( &surf_iter, brush, "surface" ); for ( num_surf = 0; ( surf = SearchGetNextClass( &surf_iter ) ) ; num_surf++ ) { int s_contents; hobj_t *plane; hobj_t *texdef; hobj_t *texture; hobj_t *meshtile; hpair_t *pair; hpair_t *mat_pair; #if 1 EasyFindInt( &s_contents, surf, "content" ); if ( !(s_contents & 32) ) { // no substructur flag continue; } #endif // GenerateMeshtile( surf, plane_hm, texdef_hm, plane = EasyLookupClsref( surf, "plane", plane_hm ); texdef = EasyLookupClsref( surf, "texdef", texdef_hm ); texture = EasyLookupClsref( texdef, "texture", texture_hm ); pair = FindHPair( texture, "ident" ); if ( !pair ) Error( "missing key 'ident'\n" ); meshtile = FindClass( meshtile_root, pair->value ); if ( !meshtile ) { Error( "no meshtile defs for ident '%s'\n", pair->value ); } mat_pair = FindHPair( tm_root, pair->value ); { int i, j; vec3d_t norm; fp_t dist; hobj_t *plane2; vec3d_t norm2; fp_t dist2; fp_t rotate; vec2d_t shift; vec2d_t scale; vec2d_t vec0, vec1; fp_t u_size, v_size, height; u_list_t *raw_poly_list; u_list_t *base_tile_mesh; surf_poly_obj = FindClassType( surf, "polygon" ); surf_poly = CreatePolygonFromClass( surf_poly_obj ); EasyFindVec3d( norm, plane, "norm" ); EasyFindFloat( &dist, plane, "dist" ); EasyFindVec2d( shift, texdef, "shift" ); EasyFindVec2d( vec0, texdef, "vec0" ); EasyFindVec2d( vec1, texdef, "vec1" ); if ( vec0[0] == 0.0 && vec0[1] == 0.0 ) { vec0[0] = 1.0; } if ( vec1[0] == 0.0 && vec1[1] == 0.0 ) { vec1[1] = 1.0; } EasyFindVec2d( scale, texdef, "scale" ); EasyFindFloat( &rotate, texdef, "rotate" ); EasyFindFloat( &u_size, meshtile, "u_size" ); EasyFindFloat( &v_size, meshtile, "v_size" ); EasyFindFloat( &height, meshtile, "height" ); pair = FindHPair( meshtile, "raw_path" ); if ( !pair ) Error( "missing key 'raw_path'\n" ); sprintf( tt, "%s/%s", path_name, pair->value ); raw_poly_list = ReadPolygonList( tt ); if ( !raw_poly_list ) Error( "can't load raw polygons\n" ); printf( "%s: %d raw polygons/tile \n", pair->value, U_ListLength( raw_poly_list ) ); NormalizePolygonList( raw_poly_list ); { vec3d_t scl; scl[0] = u_size; scl[1] = v_size; scl[2] = height; ScalePolygonList( raw_poly_list, scl ); } { vec3d_t shf; shf[0] = 0.0; shf[1] = 0.0; shf[2] = -height; ShiftPolygonList( raw_poly_list, shf ); } base_tile_mesh = GenBaseTileMesh( surf_poly, norm, dist, vec0, vec1, shift, raw_poly_list, u_size, v_size, rotate, scale ); // // clip base by all surface planes // InitClassSearchIterator( &surf2_iter, brush, "surface" ); for ( ; ( surf2 = SearchGetNextClass( &surf2_iter ) ) ; ) { if ( surf2 == surf ) continue; EasyFindInt( &s_contents, surf2, "content" ); if ( !(s_contents & 32) ) { // no substructur flag continue; } plane2 = EasyLookupClsref( surf2, "plane", plane_hm ); EasyFindVec3d( norm2, plane2, "norm" ); EasyFindFloat( &dist2, plane2, "dist" ); ClipPolygonList( base_tile_mesh, norm2, dist2 ); } for ( i = 0; i < surf_poly->pointnum; i++ ) { j = (i+1==surf_poly->pointnum)?0:(i+1); // search surf, which the edge is on InitClassSearchIterator( &surf2_iter, brush, "surface" ); for ( ; ( surf2 = SearchGetNextClass( &surf2_iter ) ) ; ) { if ( surf2 == surf ) continue; plane2 = EasyLookupClsref( surf2, "plane", plane_hm ); EasyFindVec3d( norm2, plane2, "norm" ); EasyFindFloat( &dist2, plane2, "dist" ); if ( fabs(Vec3dDotProduct( surf_poly->p[i], norm2 )-dist2 ) < 0.1 && fabs(Vec3dDotProduct( surf_poly->p[j], norm2 )-dist2 ) < 0.1 ) { // that's the surf vec3d_t delta1, delta2; vec3d_t cross; Vec3dSub( delta1, surf_poly->p[j], surf_poly->p[i] ); Vec3dAdd( delta2, norm, norm2 ); Vec3dUnify( delta1 ); Vec3dUnify( delta2 ); Vec3dCrossProduct( cross, delta1, delta2 ); Vec3dUnify( cross ); dist2 = Vec3dInitPlane2( cross, surf_poly->p[i] ); ClipPolygonList( base_tile_mesh, cross, dist2 ); break; } } } // DrawPolygonList( base_tile_mesh ); // // build meshtile shape // plane = EasyLookupClsref( surf, "plane", plane_hm ); shape = BuildMeshTileShape( surf_poly_obj, plane, texdef, mat_pair, base_tile_mesh ); BuildTriMesh( shape, base_tile_mesh ); InsertClass( shape_root, shape ); num_total_tris += U_ListLength( base_tile_mesh ); } } } printf( " generated %d triangles\n", num_total_tris ); GLD_EndList( gld ); GLD_Update( gld ); GLD_Pause( gld ); GLD_EndSession( gld ); h = fopen( out_shape_name, "w" ); if ( !h ) Error( "can't write shape class\n" ); WriteClass( shape_root, h ); fclose( h ); h = fopen( out_glmesh_name, "w" ); if ( !h ) Error( "can't write glmesh binary\n" ); fwrite( glmesh_base, glmesh_ofs, 1, h ); fclose( h ); HManagerSaveID(); exit(0); }
bool IntersectRayTriangle3d(const Ray3d& ray, const Triangle3d& tr) { //reference: Essential Mathematics for Games and Interactive pag. 585 // test ray direction against triangle //triangle' s point: v1=a,v0=b,v2=c Vec3d v0 = Vec3d(tr.b.point.x, tr.b.point.y, tr.b.point.z); Vec3d v1 = Vec3d(tr.a.point.x, tr.a.point.y, tr.a.point.z); Vec3d v2 = Vec3d(tr.c.point.x, tr.c.point.y, tr.c.point.z); //e1 = v1 - v0; Vec3d e1; Vec3dSub(v1, v0, &e1); //e2 = v2 - v0; Vec3d e2; Vec3dSub(v2, v0, &e2); //p = ray.mDirection.Cross(e2); Vec3d p; Vec3dCross(ray.direction.dir, e2, &p); //float a = e1.Dot(p); F64 a = Vec3dDot(e1, p); // if result zero, no intersection or infinite intersections // (ray parallel to triangle plane) //if ( IsZerod(a) ) if (IsZerod(a)) return false; // compute denominator F64 f = 1.0/a; // compute barycentric coordinates //IvVector3 s = ray.mOrigin - v0; Vec3d s; Vec3d mOrigin = Vec3d(ray.origin.point.x, ray.origin.point.y, ray.origin.point.z); Vec3dSub(mOrigin, v0, &s); //u = f*s.Dot(p) F64 u = f * Vec3dDot(s, p); if (u < 0.0 || u > 1.0) return false; //q = s.Cross(e1); Vec3d q; Vec3dCross(s, e1, &q); //v = f*ray.mDirection.Dot(q); F64 v = f * Vec3dDot(ray.direction.dir, q); if (v < 0.0 || u+v > 1.0) return false; // compute line parameter //t = f*e2.Dot(q); F64 t = f * Vec3dDot(e2, q); return (t >= 0.0); }
//to do: try this... bool IntersectRayOBB3d(const Ray3d& ray, const OBB3d& obb) { //intersect ray-obb reference: http://www.geometrictools.com/LibMathematics/Intersection/Intersection.html intersect box ray //bool IntrRay3Box3<Real>::Test () //{ //Real WdU[3], AWdU[3], DdU[3], ADdU[3], AWxDdU[3], RHS; F64 WdU[3], AWdU[3], DdU[3], ADdU[3], AWxDdU[3], RHS; //Vector3<Real> diff = mRay->Origin - mBox->Center; Vec3d diff; Vec3dSub(ray.origin.point, obb.center.point, &diff); //WdU[0] = mRay->Direction.Dot(mBox->Axis[0]); WdU[0] = Vec3dDot(ray.direction.dir, obb.orientX); //AWdU[0] = Math<Real>::FAbs(WdU[0]); AWdU[0] = Absd(WdU[0]); //DdU[0] = diff.Dot(mBox->Axis[0]); DdU[0] = Vec3dDot(diff, obb.orientX); //ADdU[0] = Math<Real>::FAbs(DdU[0]); ADdU[0] = Absd(DdU[0]); //if (ADdU[0] > mBox->Extent[0] && DdU[0]*WdU[0] >= (Real)0) if ( ADdU[0] > obb.halfWidths.x && DdU[0]*WdU[0] >= 0.0) { return false; } //WdU[1] = mRay->Direction.Dot(mBox->Axis[1]); WdU[1] = Vec3dDot(ray.direction.dir, obb.orientY); //AWdU[1] = Math<Real>::FAbs(WdU[1]); AWdU[1] = Absd(WdU[1]); //DdU[1] = diff.Dot(mBox->Axis[1]); DdU[1] = Vec3dDot(diff, obb.orientY); //ADdU[1] = Math<Real>::FAbs(DdU[1]); ADdU[1] = Absd(DdU[1]); //if (ADdU[1] > mBox->Extent[1] && DdU[1]*WdU[1] >= (Real)0) if ( ADdU[1] > obb.halfWidths.y && DdU[1]*WdU[1] >= 0.0) { return false; } //WdU[2] = mRay->Direction.Dot(mBox->Axis[2]); WdU[2] = Vec3dDot(ray.direction.dir, obb.orientZ); //AWdU[2] = Math<Real>::FAbs(WdU[2]); AWdU[2] = Absd(WdU[2]); //DdU[2] = diff.Dot(mBox->Axis[2]); DdU[2] = Vec3dDot(diff, obb.orientZ); //ADdU[2] = Math<Real>::FAbs(DdU[2]); ADdU[2] = Absd(DdU[2]); //if (ADdU[2] > mBox->Extent[2] && DdU[2]*WdU[2] >= (Real)0) if ( ADdU[2] > obb.halfWidths.z && DdU[2]*WdU[2] >= 0.0) { return false; } //Vector3<Real> WxD = mRay->Direction.Cross(diff); Vec3d WxD; Vec3dCross(ray.direction.dir, diff, &WxD); //AWxDdU[0] = Math<Real>::FAbs(WxD.Dot(mBox->Axis[0])); AWxDdU[0] = Absd(Vec3dDot(WxD, obb.orientX)); //RHS = mBox->Extent[1]*AWdU[2] + mBox->Extent[2]*AWdU[1]; RHS = obb.halfWidths.y * AWdU[2] + obb.halfWidths.z * AWdU[1]; if (AWxDdU[0] > RHS) { return false; } //AWxDdU[1] = Math<Real>::FAbs(WxD.Dot(mBox->Axis[1])); AWxDdU[1] = Absd(Vec3dDot(WxD, obb.orientY)); //RHS = mBox->Extent[0]*AWdU[2] + mBox->Extent[2]*AWdU[0]; RHS = obb.halfWidths.x * AWdU[2] + obb.halfWidths.z * AWdU[0]; if (AWxDdU[1] > RHS) { return false; } //AWxDdU[2] = Math<Real>::FAbs(WxD.Dot(mBox->Axis[2])); AWxDdU[2] = Absd(Vec3dDot(WxD, obb.orientZ)); //RHS = mBox->Extent[0]*AWdU[1] + mBox->Extent[1]*AWdU[0]; RHS = obb.halfWidths.x * AWdU[1] + obb.halfWidths.y * AWdU[0]; if (AWxDdU[2] > RHS) { return false; } return true; }