void CEntityMiscModel::Rotate( const vec3_t pivot, const vec3_t rotation ){ m4x4_t rotation_matrix; m4x4_identity( rotation_matrix ); m4x4_pivoted_rotate_by_vec3( rotation_matrix, rotation, eXYZ, pivot ); m4x4_transform_point( rotation_matrix, m_translate ); VectorIncrement( rotation, m_euler ); UpdateCachedData(); }
void aabb_orthogonal_transform(aabb_t* dst, const aabb_t* src, const m4x4_t transform) { VectorCopy(src->origin, dst->origin); m4x4_transform_point(transform, dst->origin); dst->extents[0] = (vec_t)(fabs(transform[0] * src->extents[0]) + fabs(transform[4] * src->extents[1]) + fabs(transform[8] * src->extents[2])); dst->extents[1] = (vec_t)(fabs(transform[1] * src->extents[0]) + fabs(transform[5] * src->extents[1]) + fabs(transform[9] * src->extents[2])); dst->extents[2] = (vec_t)(fabs(transform[2] * src->extents[0]) + fabs(transform[6] * src->extents[1]) + fabs(transform[10] * src->extents[2])); }
void bbox_for_oriented_aabb(bbox_t *bbox, const aabb_t *aabb, const m4x4_t matrix, const vec3_t euler, const vec3_t scale) { double rad[3]; double pi_180 = Q_PI / 180; double A, B, C, D, E, F, AD, BD; VectorCopy(aabb->origin, bbox->aabb.origin); m4x4_transform_point(matrix, bbox->aabb.origin); bbox->aabb.extents[0] = aabb->extents[0] * scale[0]; bbox->aabb.extents[1] = aabb->extents[1] * scale[1]; bbox->aabb.extents[2] = aabb->extents[2] * scale[2]; rad[0] = euler[0] * pi_180; rad[1] = euler[1] * pi_180; rad[2] = euler[2] * pi_180; A = cos(rad[0]); B = sin(rad[0]); C = cos(rad[1]); D = sin(rad[1]); E = cos(rad[2]); F = sin(rad[2]); AD = A * -D; BD = B * -D; bbox->axes[0][0] = (vec_t)(C*E); bbox->axes[0][1] = (vec_t)(-BD*E + A*F); bbox->axes[0][2] = (vec_t)(AD*E + B*F); bbox->axes[1][0] = (vec_t)(-C*F); bbox->axes[1][1] = (vec_t)(BD*F + A*E); bbox->axes[1][2] = (vec_t)(-AD*F + B*E); bbox->axes[2][0] = (vec_t)D; bbox->axes[2][1] = (vec_t)(-B*C); bbox->axes[2][2] = (vec_t)(A*C); bbox_update_radius(bbox); }
void aabb_for_transformed_aabb(aabb_t* dst, const aabb_t* src, const m4x4_t transform) { if(src->extents[0] < 0 || src->extents[1] < 0 || src->extents[2] < 0) { aabb_clear(dst); return; } VectorCopy(src->origin, dst->origin); m4x4_transform_point(transform, dst->origin); dst->extents[0] = (vec_t)(fabs(transform[0] * src->extents[0]) + fabs(transform[4] * src->extents[1]) + fabs(transform[8] * src->extents[2])); dst->extents[1] = (vec_t)(fabs(transform[1] * src->extents[0]) + fabs(transform[5] * src->extents[1]) + fabs(transform[9] * src->extents[2])); dst->extents[2] = (vec_t)(fabs(transform[2] * src->extents[0]) + fabs(transform[6] * src->extents[1]) + fabs(transform[10] * src->extents[2])); }
void ray_transform( ray_t *ray, const m4x4_t matrix ){ m4x4_transform_point( matrix, ray->origin ); m4x4_transform_normal( matrix, ray->direction ); }
static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform ){ int i, j, x, y, pw[ 5 ], r, nodeNum; bspDrawSurface_t *ds; surfaceInfo_t *info; bspDrawVert_t *verts; int *indexes; mesh_t srcMesh, *mesh, *subdivided; traceInfo_t ti; traceWinding_t tw; /* dummy check */ if ( model == NULL || transform == NULL ) { return; } /* walk the list of surfaces in this model and fill out the info structs */ for ( i = 0; i < model->numBSPSurfaces; i++ ) { /* get surface and info */ ds = &bspDrawSurfaces[ model->firstBSPSurface + i ]; info = &surfaceInfos[ model->firstBSPSurface + i ]; if ( info->si == NULL ) { continue; } /* no shadows */ if ( !info->castShadows ) { continue; } /* patchshadows? */ if ( ds->surfaceType == MST_PATCH && patchShadows == qfalse ) { continue; } /* some surfaces in the bsp might have been tagged as nodraw, with a bogus shader */ if ( ( bspShaders[ ds->shaderNum ].contentFlags & noDrawContentFlags ) || ( bspShaders[ ds->shaderNum ].surfaceFlags & noDrawSurfaceFlags ) ) { continue; } /* translucent surfaces that are neither alphashadow or lightfilter don't cast shadows */ if ( ( info->si->compileFlags & C_NODRAW ) ) { continue; } if ( ( info->si->compileFlags & C_TRANSLUCENT ) && !( info->si->compileFlags & C_ALPHASHADOW ) && !( info->si->compileFlags & C_LIGHTFILTER ) ) { continue; } /* setup trace info */ ti.si = info->si; ti.castShadows = info->castShadows; ti.surfaceNum = model->firstBSPBrush + i; ti.skipGrid = ( ds->surfaceType == MST_PATCH ); /* choose which node (normal or skybox) */ if ( info->parentSurfaceNum >= 0 ) { nodeNum = skyboxNodeNum; /* sky surfaces in portal skies are ignored */ if ( info->si->compileFlags & C_SKY ) { continue; } } else{ nodeNum = headNodeNum; } /* setup trace winding */ memset( &tw, 0, sizeof( tw ) ); tw.infoNum = AddTraceInfo( &ti ); tw.numVerts = 3; /* switch on type */ switch ( ds->surfaceType ) { /* handle patches */ case MST_PATCH: /* subdivide the surface */ srcMesh.width = ds->patchWidth; srcMesh.height = ds->patchHeight; srcMesh.verts = &bspDrawVerts[ ds->firstVert ]; //% subdivided = SubdivideMesh( srcMesh, 8, 512 ); subdivided = SubdivideMesh2( srcMesh, info->patchIterations ); /* fit it to the curve and remove colinear verts on rows/columns */ PutMeshOnCurve( *subdivided ); mesh = RemoveLinearMeshColumnsRows( subdivided ); FreeMesh( subdivided ); /* set verts */ verts = mesh->verts; /* subdivide each quad to place the models */ for ( y = 0; y < ( mesh->height - 1 ); y++ ) { for ( x = 0; x < ( mesh->width - 1 ); x++ ) { /* set indexes */ pw[ 0 ] = x + ( y * mesh->width ); pw[ 1 ] = x + ( ( y + 1 ) * mesh->width ); pw[ 2 ] = x + 1 + ( ( y + 1 ) * mesh->width ); pw[ 3 ] = x + 1 + ( y * mesh->width ); pw[ 4 ] = x + ( y * mesh->width ); /* same as pw[ 0 ] */ /* set radix */ r = ( x + y ) & 1; /* make first triangle */ VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz ); Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st ); VectorCopy( verts[ pw[ r + 1 ] ].xyz, tw.v[ 1 ].xyz ); Vector2Copy( verts[ pw[ r + 1 ] ].st, tw.v[ 1 ].st ); VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 2 ].xyz ); Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 2 ].st ); m4x4_transform_point( transform, tw.v[ 0 ].xyz ); m4x4_transform_point( transform, tw.v[ 1 ].xyz ); m4x4_transform_point( transform, tw.v[ 2 ].xyz ); FilterTraceWindingIntoNodes_r( &tw, nodeNum ); /* make second triangle */ VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz ); Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st ); VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 1 ].xyz ); Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 1 ].st ); VectorCopy( verts[ pw[ r + 3 ] ].xyz, tw.v[ 2 ].xyz ); Vector2Copy( verts[ pw[ r + 3 ] ].st, tw.v[ 2 ].st ); m4x4_transform_point( transform, tw.v[ 0 ].xyz ); m4x4_transform_point( transform, tw.v[ 1 ].xyz ); m4x4_transform_point( transform, tw.v[ 2 ].xyz ); FilterTraceWindingIntoNodes_r( &tw, nodeNum ); } } /* free the subdivided mesh */ FreeMesh( mesh ); break; /* handle triangle surfaces */ case MST_TRIANGLE_SOUP: case MST_PLANAR: /* set verts and indexes */ verts = &bspDrawVerts[ ds->firstVert ]; indexes = &bspDrawIndexes[ ds->firstIndex ]; /* walk the triangle list */ for ( j = 0; j < ds->numIndexes; j += 3 ) { VectorCopy( verts[ indexes[ j ] ].xyz, tw.v[ 0 ].xyz ); Vector2Copy( verts[ indexes[ j ] ].st, tw.v[ 0 ].st ); VectorCopy( verts[ indexes[ j + 1 ] ].xyz, tw.v[ 1 ].xyz ); Vector2Copy( verts[ indexes[ j + 1 ] ].st, tw.v[ 1 ].st ); VectorCopy( verts[ indexes[ j + 2 ] ].xyz, tw.v[ 2 ].xyz ); Vector2Copy( verts[ indexes[ j + 2 ] ].st, tw.v[ 2 ].st ); m4x4_transform_point( transform, tw.v[ 0 ].xyz ); m4x4_transform_point( transform, tw.v[ 1 ].xyz ); m4x4_transform_point( transform, tw.v[ 2 ].xyz ); FilterTraceWindingIntoNodes_r( &tw, nodeNum ); } break; /* other surface types do not cast shadows */ default: break; } } }
static void PopulateWithPicoModel( int castShadows, picoModel_t *model, m4x4_t transform ){ int i, j, k, numSurfaces, numIndexes; picoSurface_t *surface; picoShader_t *shader; picoVec_t *xyz, *st; picoIndex_t *indexes; traceInfo_t ti; traceWinding_t tw; /* dummy check */ if ( model == NULL || transform == NULL ) { return; } /* get info */ numSurfaces = PicoGetModelNumSurfaces( model ); /* walk the list of surfaces in this model and fill out the info structs */ for ( i = 0; i < numSurfaces; i++ ) { /* get surface */ surface = PicoGetModelSurface( model, i ); if ( surface == NULL ) { continue; } /* only handle triangle surfaces initially (fixme: support patches) */ if ( PicoGetSurfaceType( surface ) != PICO_TRIANGLES ) { continue; } /* get shader (fixme: support shader remapping) */ shader = PicoGetSurfaceShader( surface ); if ( shader == NULL ) { continue; } ti.si = ShaderInfoForShaderNull( PicoGetShaderName( shader ) ); if ( ti.si == NULL ) { continue; } /* translucent surfaces that are neither alphashadow or lightfilter don't cast shadows */ if ( ( ti.si->compileFlags & C_NODRAW ) ) { continue; } if ( ( ti.si->compileFlags & C_TRANSLUCENT ) && !( ti.si->compileFlags & C_ALPHASHADOW ) && !( ti.si->compileFlags & C_LIGHTFILTER ) ) { continue; } /* setup trace info */ ti.castShadows = castShadows; ti.surfaceNum = -1; ti.skipGrid = qtrue; // also ignore picomodels when skipping patches /* setup trace winding */ memset( &tw, 0, sizeof( tw ) ); tw.infoNum = AddTraceInfo( &ti ); tw.numVerts = 3; /* get info */ numIndexes = PicoGetSurfaceNumIndexes( surface ); indexes = PicoGetSurfaceIndexes( surface, 0 ); /* walk the triangle list */ for ( j = 0; j < numIndexes; j += 3, indexes += 3 ) { for ( k = 0; k < 3; k++ ) { xyz = PicoGetSurfaceXYZ( surface, indexes[ k ] ); st = PicoGetSurfaceST( surface, 0, indexes[ k ] ); VectorCopy( xyz, tw.v[ k ].xyz ); Vector2Copy( st, tw.v[ k ].st ); m4x4_transform_point( transform, tw.v[ k ].xyz ); } FilterTraceWindingIntoNodes_r( &tw, headNodeNum ); } } }