/* ================ RemoveLinearMeshColumsRows ================ */ mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) { int i, j, k; float len, maxLength; vec3_t proj, dir; mesh_t out; /* ydnar: static for os x */ MAC_STATIC bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; out.width = in->width; out.height = in->height; for ( i = 0 ; i < in->width ; i++ ) { for ( j = 0 ; j < in->height ; j++ ) { expand[j][i] = in->verts[j*in->width+i]; } } for ( j = 1 ; j < out.width - 1; j++ ) { maxLength = 0; for ( i = 0 ; i < out.height ; i++ ) { ProjectPointOntoVector(expand[i][j].xyz, expand[i][j-1].xyz, expand[i][j+1].xyz, proj); VectorSubtract(expand[i][j].xyz, proj, dir); len = VectorLength(dir); if (len > maxLength) { maxLength = len; } } if (maxLength < 0.1) { out.width--; for ( i = 0 ; i < out.height ; i++ ) { for (k = j; k < out.width; k++) { expand[i][k] = expand[i][k+1]; } } j--; } } for ( j = 1 ; j < out.height - 1; j++ ) { maxLength = 0; for ( i = 0 ; i < out.width ; i++ ) { ProjectPointOntoVector(expand[j][i].xyz, expand[j-1][i].xyz, expand[j+1][i].xyz, proj); VectorSubtract(expand[j][i].xyz, proj, dir); len = VectorLength(dir); if (len > maxLength) { maxLength = len; } } if (maxLength < 0.1) { out.height--; for ( i = 0 ; i < out.width ; i++ ) { for (k = j; k < out.height; k++) { expand[k][i] = expand[k+1][i]; } } j--; } } // collapse the verts out.verts = &expand[0][0]; for ( i = 1 ; i < out.height ; i++ ) { memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) ); } return CopyMesh(&out); }
void CG_AddTrailToScene(trailJunc_t *trail, int iteration, int numJuncs) { #define MAX_TRAIL_VERTS 2048 polyVert_t verts[MAX_TRAIL_VERTS]; polyVert_t outVerts[MAX_TRAIL_VERTS * 3]; int k, i, n, l, numOutVerts; polyVert_t mid; float mod[4]; float sInc = 0.0f, s = 0.0f; // TTimo: init trailJunc_t *j, *jNext; vec3_t fwd, up, p, v; (void)fwd; // Ignore compiler warning -- Justasic // clipping vars #define TRAIL_FADE_CLOSE_DIST 64.0 #define TRAIL_FADE_FAR_SCALE 4.0 vec3_t viewProj; float viewDist, fadeAlpha; // add spark shader at head position if(trail->flags & TJFL_SPARKHEADFLARE) { j = trail; VectorCopy(j->pos, p); VectorMA(p, -j->width * 2, vup, p); VectorMA(p, -j->width * 2, vright, p); VectorCopy(p, verts[0].xyz); verts[0].st[0] = 0; verts[0].st[1] = 0; verts[0].modulate[0] = 255; verts[0].modulate[1] = 255; verts[0].modulate[2] = 255; verts[0].modulate[3] = (unsigned char)(j->alpha * 255.0); VectorCopy(j->pos, p); VectorMA(p, -j->width * 2, vup, p); VectorMA(p, j->width * 2, vright, p); VectorCopy(p, verts[1].xyz); verts[1].st[0] = 0; verts[1].st[1] = 1; verts[1].modulate[0] = 255; verts[1].modulate[1] = 255; verts[1].modulate[2] = 255; verts[1].modulate[3] = (unsigned char)(j->alpha * 255.0); VectorCopy(j->pos, p); VectorMA(p, j->width * 2, vup, p); VectorMA(p, j->width * 2, vright, p); VectorCopy(p, verts[2].xyz); verts[2].st[0] = 1; verts[2].st[1] = 1; verts[2].modulate[0] = 255; verts[2].modulate[1] = 255; verts[2].modulate[2] = 255; verts[2].modulate[3] = (unsigned char)(j->alpha * 255.0); VectorCopy(j->pos, p); VectorMA(p, j->width * 2, vup, p); VectorMA(p, -j->width * 2, vright, p); VectorCopy(p, verts[3].xyz); verts[3].st[0] = 1; verts[3].st[1] = 0; verts[3].modulate[0] = 255; verts[3].modulate[1] = 255; verts[3].modulate[2] = 255; verts[3].modulate[3] = (unsigned char)(j->alpha * 255.0); trap_R_AddPolyToScene(cgs.media.sparkFlareShader, 4, verts); } // if (trail->flags & TJFL_CROSSOVER && iteration < 1) { // iteration = 1; // } if(!numJuncs) { // first count the number of juncs in the trail j = trail; numJuncs = 0; sInc = 0; while(j) { numJuncs++; // check for a dead next junc if(!j->inuse && j->nextJunc && !j->nextJunc->inuse) { CG_KillTrail(j); } else if(j->nextJunc && j->nextJunc->freed) { // not sure how this can happen, but it does, and causes infinite loops j->nextJunc = NULL; } if(j->nextJunc) { sInc += VectorDistance(j->nextJunc->pos, j->pos); } j = j->nextJunc; } } if(numJuncs < 2) { return; } if(trail->sType == STYPE_STRETCH) { //sInc = ((1.0 - 0.1) / (float)(numJuncs)); // hack, the end of funnel shows a bit of the start (looping) s = 0.05; //s = 0.05; } else if(trail->sType == STYPE_REPEAT) { s = trail->sTex; } // now traverse the list j = trail; jNext = j->nextJunc; i = 0; while(jNext) { // first get the directional vectors to the next junc VectorSubtract(jNext->pos, j->pos, fwd); GetPerpendicularViewVector(cg.refdef.vieworg, j->pos, jNext->pos, up); // if it's a crossover, draw it twice if(j->flags & TJFL_CROSSOVER) { if(iteration > 0) { ProjectPointOntoVector(cg.refdef.vieworg, j->pos, jNext->pos, viewProj); VectorSubtract(cg.refdef.vieworg, viewProj, v); VectorNormalize(v); if(iteration == 1) { VectorMA(up, 0.3, v, up); } else { VectorMA(up, -0.3, v, up); } VectorNormalize(up); } } // do fading when moving towards the projection point onto the trail segment vector else if(!(j->flags & TJFL_NOCULL) && (j->widthEnd > 4 || jNext->widthEnd > 4)) { ProjectPointOntoVector(cg.refdef.vieworg, j->pos, jNext->pos, viewProj); viewDist = Distance(viewProj, cg.refdef.vieworg); if(viewDist < (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE)) { if(viewDist < TRAIL_FADE_CLOSE_DIST) { fadeAlpha = 0.0; } else { fadeAlpha = (viewDist - TRAIL_FADE_CLOSE_DIST) / (TRAIL_FADE_CLOSE_DIST * TRAIL_FADE_FAR_SCALE); } if(fadeAlpha < j->alpha) { j->alpha = fadeAlpha; } if(fadeAlpha < jNext->alpha) { jNext->alpha = fadeAlpha; } } } // now output the QUAD for this segment // 1 ---- VectorMA(j->pos, 0.5 * j->width, up, p); VectorCopy(p, verts[i].xyz); verts[i].st[0] = s; verts[i].st[1] = 1.0; for(k = 0; k < 3; k++) verts[i].modulate[k] = (unsigned char)(j->color[k] * 255.0); verts[i].modulate[3] = (unsigned char)(j->alpha * 255.0); // blend this with the previous junc if(j != trail) { VectorAdd(verts[i].xyz, verts[i - 1].xyz, verts[i].xyz); VectorScale(verts[i].xyz, 0.5, verts[i].xyz); VectorCopy(verts[i].xyz, verts[i - 1].xyz); } else if(j->flags & TJFL_FADEIN) { verts[i].modulate[3] = 0; // fade in } i++; // 2 ---- VectorMA(p, -1 * j->width, up, p); VectorCopy(p, verts[i].xyz); verts[i].st[0] = s; verts[i].st[1] = 0.0; for(k = 0; k < 3; k++) verts[i].modulate[k] = (unsigned char)(j->color[k] * 255.0); verts[i].modulate[3] = (unsigned char)(j->alpha * 255.0); // blend this with the previous junc if(j != trail) { VectorAdd(verts[i].xyz, verts[i - 3].xyz, verts[i].xyz); VectorScale(verts[i].xyz, 0.5, verts[i].xyz); VectorCopy(verts[i].xyz, verts[i - 3].xyz); } else if(j->flags & TJFL_FADEIN) { verts[i].modulate[3] = 0; // fade in } i++; if(trail->sType == STYPE_REPEAT) { s = jNext->sTex; } else { //s += sInc; s += VectorDistance(j->pos, jNext->pos) / sInc; if(s > 1.0) { s = 1.0; } } // 3 ---- VectorMA(jNext->pos, -0.5 * jNext->width, up, p); VectorCopy(p, verts[i].xyz); verts[i].st[0] = s; verts[i].st[1] = 0.0; for(k = 0; k < 3; k++) verts[i].modulate[k] = (unsigned char)(jNext->color[k] * 255.0); verts[i].modulate[3] = (unsigned char)(jNext->alpha * 255.0); i++; // 4 ---- VectorMA(p, jNext->width, up, p); VectorCopy(p, verts[i].xyz); verts[i].st[0] = s; verts[i].st[1] = 1.0; for(k = 0; k < 3; k++) verts[i].modulate[k] = (unsigned char)(jNext->color[k] * 255.0); verts[i].modulate[3] = (unsigned char)(jNext->alpha * 255.0); i++; if(i + 4 > MAX_TRAIL_VERTS) { break; } j = jNext; jNext = j->nextJunc; } if(trail->flags & TJFL_FIXDISTORT) { // build the list of outVerts, by dividing up the QUAD's into 4 Tri's each, so as to allow // any shaped (convex) Quad without bilinear distortion for(k = 0, numOutVerts = 0; k < i; k += 4) { VectorCopy(verts[k].xyz, mid.xyz); mid.st[0] = verts[k].st[0]; mid.st[1] = verts[k].st[1]; for(l = 0; l < 4; l++) { mod[l] = (float)verts[k].modulate[l]; } for(n = 1; n < 4; n++) { VectorAdd(verts[k + n].xyz, mid.xyz, mid.xyz); mid.st[0] += verts[k + n].st[0]; mid.st[1] += verts[k + n].st[1]; for(l = 0; l < 4; l++) { mod[l] += (float)verts[k + n].modulate[l]; } } VectorScale(mid.xyz, 0.25, mid.xyz); mid.st[0] *= 0.25; mid.st[1] *= 0.25; for(l = 0; l < 4; l++) { mid.modulate[l] = (unsigned char)(mod[l] / 4.0); } // now output the tri's for(n = 0; n < 4; n++) { outVerts[numOutVerts++] = verts[k + n]; outVerts[numOutVerts++] = mid; if(n < 3) { outVerts[numOutVerts++] = verts[k + n + 1]; } else { outVerts[numOutVerts++] = verts[k]; } } } if(!(trail->flags & TJFL_NOPOLYMERGE)) { trap_R_AddPolysToScene(trail->shader, 3, &outVerts[0], numOutVerts / 3); } else { int k; for(k = 0; k < numOutVerts / 3; k++) { trap_R_AddPolyToScene(trail->shader, 3, &outVerts[k * 3]); } } } else { // send the polygons // FIXME: is it possible to send a GL_STRIP here? We are actually sending 2x the verts we really need to if(!(trail->flags & TJFL_NOPOLYMERGE)) { trap_R_AddPolysToScene(trail->shader, 4, &verts[0], i / 4); } else { int k; for(k = 0; k < i / 4; k++) { trap_R_AddPolyToScene(trail->shader, 4, &verts[k * 4]); } } } // do we need to make another pass? if(trail->flags & TJFL_CROSSOVER) { if(iteration < 2) { CG_AddTrailToScene(trail, iteration + 1, numJuncs); } } }
/* ================= CG_Bleed This is the spurt of blood when a character gets hit ================= */ void CG_Bleed(vec3_t origin, int entityNum) { #define BLOOD_SPURT_COUNT 4 int i, j; centity_t *cent; if (!cg_blood.integer) { return; } #ifdef SAVEGAME_SUPPORT if (cg_reloading.integer) { // to dangerous, since we call playerangles() in here, which calls the animation system, which might not be setup yet return; } #endif // SAVEGAME_SUPPORT cent = &cg_entities[entityNum]; // Ridah, blood spurts if (entityNum != cg.snap->ps.clientNum) { vec3_t vhead, vbody, bOrigin, dir, vec, pvec, ndir; CG_GetBleedOrigin(vhead, vbody, entityNum); // project the impact point onto the vector defined by torso -> head ProjectPointOntoVector(origin, vbody, vhead, bOrigin); // if it's below the waste, or above the head, clamp VectorSubtract(vhead, vbody, vec); VectorSubtract(bOrigin, vbody, pvec); if (DotProduct(pvec, vec) < 0) { VectorCopy(vbody, bOrigin); } else { VectorSubtract(bOrigin, vhead, pvec); if (DotProduct(pvec, vec) > 0) { VectorCopy(vhead, bOrigin); } } // spawn some blood trails, heading out towards the impact point VectorSubtract(origin, bOrigin, dir); VectorNormalize(dir); { float len; vec3_t vec; VectorSubtract(bOrigin, vhead, vec); len = VectorLength(vec); if (len > 8) { VectorMA(bOrigin, 8, dir, bOrigin); } } // DHM - Nerve :: Made minor adjustments for (i = 0; i < BLOOD_SPURT_COUNT; i++) { VectorCopy(dir, ndir); for (j = 0; j < 3; j++) ndir[j] += crandom() * 0.3; VectorNormalize(ndir); CG_AddBloodTrails(bOrigin, ndir, 100, // speed 450 + (int)(crandom() * 50), // duration 2 + rand() % 2, // count 0.1); // rand scale } } }
/* ================= CG_Bleed This is the spurt of blood when a character gets hit ================= */ void CG_Bleed(vec3_t origin, int entityNum) { if (!cg_blood.integer) { return; } // blood spurts if (entityNum != cg.snap->ps.clientNum) { vec3_t vhead, vbody, bOrigin, dir, vec, pvec, ndir; int i, j; CG_GetBleedOrigin(vhead, vbody, entityNum); // project the impact point onto the vector defined by torso -> head ProjectPointOntoVector(origin, vbody, vhead, bOrigin); // if it's below the waste, or above the head, clamp VectorSubtract(vhead, vbody, vec); VectorSubtract(bOrigin, vbody, pvec); if (DotProduct(pvec, vec) < 0) { VectorCopy(vbody, bOrigin); } else { VectorSubtract(bOrigin, vhead, pvec); if (DotProduct(pvec, vec) > 0) { VectorCopy(vhead, bOrigin); } } // spawn some blood trails, heading out towards the impact point VectorSubtract(origin, bOrigin, dir); VectorNormalize(dir); { float len; vec3_t vec; VectorSubtract(bOrigin, vhead, vec); len = VectorLength(vec); if (len > 8) { VectorMA(bOrigin, 8, dir, bOrigin); } } for (i = 0; i < BLOOD_SPURT_COUNT; i++) { VectorCopy(dir, ndir); for (j = 0; j < 3; j++) { ndir[j] += crandom() * 0.3; } VectorNormalize(ndir); CG_AddBloodTrails(bOrigin, ndir, 100, // speed 450 + (int)(crandom() * 50), // duration 2 + rand() % 2, // count 0.1); // rand scale } } }
/* ============== AICast_PredictMovement Simulates movement over a number of frames, returning the end position ============== */ void AICast_PredictMovement( cast_state_t *cs, int numframes, float frametime, aicast_predictmove_t *move, usercmd_t *ucmd, int checkHitEnt ) { int frame, i; playerState_t ps; pmove_t pm; trace_t tr; vec3_t end, startHitVec, thisHitVec, lastOrg, projPoint; qboolean checkReachMarker; //int pretime = Sys_MilliSeconds(); //G_Printf("PredictMovement: %f duration, %i frames\n", frametime, numframes ); VectorCopy( vec3_origin, startHitVec ); if ( cs->bs ) { ps = cs->bs->cur_ps; } else { ps = g_entities[cs->entityNum].client->ps; } ps.eFlags |= EF_DUMMY_PMOVE; move->stopevent = PREDICTSTOP_NONE; if ( checkHitEnt >= 0 && !Q_stricmp( g_entities[checkHitEnt].classname, "ai_marker" ) ) { checkReachMarker = qtrue; VectorSubtract( g_entities[checkHitEnt].r.currentOrigin, ps.origin, startHitVec ); VectorCopy( ps.origin, lastOrg ); } else { checkReachMarker = qfalse; } // don't let the frametime be too high // while (frametime > 0.2) { // numframes *= 2; // frametime /= 2; // } for ( frame = 0; frame < numframes; frame++ ) { memset( &pm, 0, sizeof( pm ) ); pm.ps = &ps; pm.cmd = *ucmd; pm.oldcmd = *ucmd; pm.ps->commandTime = 0; pm.cmd.serverTime = (int)( 1000.0 * frametime ); pm.tracemask = g_entities[cs->entityNum].clipmask; //MASK_PLAYERSOLID; pm.trace = trap_TraceCapsule; //trap_Trace; pm.pointcontents = trap_PointContents; pm.debugLevel = qfalse; pm.noFootsteps = qtrue; // RF, not needed for prediction //pm.noWeapClips = qtrue; // (SA) AI's ignore weapon clips // perform a pmove Pmove( &pm ); if ( checkHitEnt >= 0 ) { // if we've hit the checkent, abort if ( checkReachMarker ) { VectorSubtract( g_entities[checkHitEnt].r.currentOrigin, pm.ps->origin, thisHitVec ); if ( DotProduct( startHitVec, thisHitVec ) < 0 ) { // project the marker onto the movement vec, and check distance ProjectPointOntoVector( g_entities[checkHitEnt].r.currentOrigin, lastOrg, pm.ps->origin, projPoint ); if ( VectorDistance( g_entities[checkHitEnt].r.currentOrigin, projPoint ) < 8 ) { move->stopevent = PREDICTSTOP_HITENT; goto done; } } // use this position as the base for the next test //VectorCopy( thisHitVec, startHitVec ); VectorCopy( pm.ps->origin, lastOrg ); } // if we didnt reach the marker, then check for something that blocked us for ( i = 0; i < pm.numtouch; i++ ) { if ( pm.touchents[i] == pm.ps->groundEntityNum ) { continue; } if ( pm.touchents[i] == checkHitEnt ) { move->stopevent = PREDICTSTOP_HITENT; goto done; } else if ( pm.touchents[i] < MAX_CLIENTS || ( pm.touchents[i] != ENTITYNUM_WORLD && ( g_entities[pm.touchents[i]].s.eType != ET_MOVER || g_entities[pm.touchents[i]].moverState != MOVER_POS1 ) ) ) { // we have hit another entity, so abort move->stopevent = PREDICTSTOP_HITCLIENT; goto done; } else if ( !Q_stricmp( g_entities[pm.touchents[i]].classname, "script_mover" ) ) { // avoid script_mover's move->stopevent = PREDICTSTOP_HITCLIENT; goto done; } } } } done: // hack, if we are above ground, chances are it's because we only did one frame, and gravity isn't applied until // after the frame, so try and drop us down some if ( move->groundEntityNum == ENTITYNUM_NONE ) { VectorCopy( move->endpos, end ); end[2] -= 32; trap_Trace( &tr, move->endpos, pm.mins, pm.maxs, end, pm.ps->clientNum, pm.tracemask ); if ( !tr.startsolid && !tr.allsolid && tr.fraction < 1 ) { VectorCopy( tr.endpos, pm.ps->origin ); pm.ps->groundEntityNum = tr.entityNum; } } // copy off the results VectorCopy( pm.ps->origin, move->endpos ); move->frames = numframes; //move->presencetype = cs->bs->presencetype; VectorCopy( pm.ps->velocity, move->velocity ); move->numtouch = pm.numtouch; memcpy( move->touchents, pm.touchents, sizeof( pm.touchents ) ); move->groundEntityNum = pm.ps->groundEntityNum; //G_Printf("PredictMovement: %i ms\n", -pretime + Sys_MilliSeconds() ); }
/* ================= CG_Bleed This is the spurt of blood when a character gets hit ================= */ void CG_Bleed( vec3_t origin, int entityNum ) { #define BLOOD_SPURT_COUNT 4 int i,j; // localEntity_t *ex; centity_t *cent; // vec3_t dir; if ( !cg_blood.integer ) { return; } cent = &cg_entities[entityNum]; if ( cent->currentState.aiChar == AICHAR_ZOMBIE ) { CG_ParticleBloodCloudZombie( cent, origin, vec3_origin ); return; } // Ridah, blood spurts if ( entityNum != cg.snap->ps.clientNum ) { vec3_t vhead, vlegs, vtorso, bOrigin, dir, vec, pvec, ndir; CG_GetBleedOrigin( vhead, vtorso, vlegs, entityNum ); // project the impact point onto the vector defined by torso -> head ProjectPointOntoVector( origin, vtorso, vhead, bOrigin ); // if it's below the waste, or above the head, clamp VectorSubtract( vhead, vtorso, vec ); VectorSubtract( bOrigin, vtorso, pvec ); if ( DotProduct( pvec, vec ) < 0 ) { VectorCopy( vtorso, bOrigin ); } else { VectorSubtract( bOrigin, vhead, pvec ); if ( DotProduct( pvec, vec ) > 0 ) { VectorCopy( vhead, bOrigin ); } } // spawn some blood trails, heading out towards the impact point VectorSubtract( origin, bOrigin, dir ); VectorNormalize( dir ); { float len; vec3_t vec; VectorSubtract( bOrigin, vhead, vec ); len = VectorLength( vec ); if ( len > 8 ) { VectorMA( bOrigin, 8, dir, bOrigin ); } } // DHM - Nerve :: Made minor adjustments for ( i = 0; i < BLOOD_SPURT_COUNT; i++ ) { VectorCopy( dir, ndir ); for ( j = 0; j < 3; j++ ) ndir[j] += crandom() * 0.3; VectorNormalize( ndir ); CG_AddBloodTrails( bOrigin, ndir, 100, // speed 450 + (int)( crandom() * 50 ), // duration 2 + rand() % 2, // count 0.1 ); // rand scale } } // done. }
/* * Patch_RemoveLinearColumnsRows */ void Patch_RemoveLinearColumnsRows( vec_t *verts, int comp, int *pwidth, int *pheight, int numattribs, uint8_t * const *attribs, const int *attribsizes ) { int i, j, k, l; const vec_t *v0, *v1, *v2; float len, maxLength; int maxWidth = *pwidth; int src, dst; int width = *pwidth, height = *pheight; vec3_t dir, proj; for( j = 1; j < width - 1; j++ ) { maxLength = 0; for( i = 0; i < height; i++ ) { v0 = &verts[(i * maxWidth + j - 1) * comp]; v1 = &verts[(i * maxWidth + j + 1) * comp]; v2 = &verts[(i * maxWidth + j) * comp]; VectorSubtract( v1, v0, dir ); VectorNormalize( dir ); ProjectPointOntoVector( v2, v0, dir, proj ); VectorSubtract( v2, proj, dir ); len = VectorLengthSquared( dir ); if ( len > maxLength ) maxLength = len; } if( maxLength < 0.01f ) { width--; for ( i = 0; i < height; i++ ) { dst = i * maxWidth + j; src = dst + 1; memmove( &verts[dst * comp], &verts[src * comp], ( width - j ) * sizeof( vec_t ) * comp ); for( k = 0; k < numattribs; k++ ) memmove( &attribs[k][dst * attribsizes[k]], &attribs[k][src * attribsizes[k]], ( width - j ) * attribsizes[k] ); } j--; } } for( j = 1; j < height - 1; j++ ) { maxLength = 0; for ( i = 0; i < width; i++ ) { v0 = &verts[((j - 1) * maxWidth + i) * comp]; v1 = &verts[((j + 1) * maxWidth + i) * comp]; v2 = &verts[(j * maxWidth + i) * comp]; VectorSubtract( v1, v0, dir ); VectorNormalize( dir ); ProjectPointOntoVector( v2, v0, dir, proj ); VectorSubtract( v2, proj, dir ); len = VectorLengthSquared( dir ); if ( len > maxLength ) maxLength = len; } if( maxLength < 0.01f ) { height--; for( i = 0; i < width; i++ ) { for ( k = j; k < height; k++ ) { src = ( k + 1 ) * maxWidth + i; dst = k * maxWidth + i; memcpy( &verts[dst * comp], &verts[src * comp], sizeof( vec_t ) * comp ); for( l = 0; l < numattribs; l++ ) memcpy( &attribs[l][dst * attribsizes[l]], &attribs[l][src * attribsizes[l]], attribsizes[l] ); } } j--; } } if ( maxWidth != width ) { for ( i = 0; i < height; i++ ) { src = i * maxWidth; dst = i * width; memmove( &verts[dst * comp], &verts[src * comp], width * sizeof( vec_t ) * comp ); for( j = 0; j < numattribs; j++ ) memmove( &attribs[j][dst * attribsizes[j]], &attribs[j][src * attribsizes[j]], width * attribsizes[j] ); } } *pwidth = width; *pheight = height; }