void TestVectorCompareEqual(SUINT& errors, SUINT& tests) { const String title = "VectorCompareEqual"; // Count local errors and tests run SUINT tErrors = 0; SUINT tTests = 0; // Test variables Vector v1 = VectorZero(); Vector v2 = VectorZero(); SBOOL result = false; // Test case 1: Complete equality v1 = v2 = gVOne; result = VectorCompareEqual(v1, v2); if(result == false) { Test::printError(title, 1); ++tErrors; } ++tTests; // Test case 2: Partial equality v2 = VectorSet(1.0f, 1.0f, 2.0f, 2.0f); result = VectorCompareEqual(v1, v2); if(result == true) { Test::printError(title, 2); ++tErrors; } ++tTests; // Test case 3: Complete inequality v2 = VectorSet(2.0f, 2.0f, 2.0f, 2.0f); result = VectorCompareEqual(v1, v2); if(result == true) { Test::printError(title, 3); ++tErrors; } ++tTests; // Print results Test::printResult(tErrors, tTests, title); // Increase total error count errors += tErrors; tests += tTests; }
void setColoursByAcceleration() { int i; particle_t *p, *plast; particleDetail_t *pd; float d; float accMax = 0; float accCurrent; float velSpeed1; float velSpeed2; VectorNew(zero); VectorZero(zero); if (state.currentFrame == 0) return; for (i = 0; i < state.particleCount; i++) { p = getParticleCurrentFrame(i); plast = state.particleHistory + state.particleCount * (state.currentFrame-1) + i; distance(zero, p->vel, velSpeed1); distance(p->vel, plast->vel, velSpeed2); accCurrent = abs(velSpeed2 - velSpeed1); if (i == 0) { accMax = accCurrent; } else { if (accCurrent > accMax) accMax = accCurrent; } } for (i = 0; i < state.particleCount; i++) { p = getParticleCurrentFrame(i); plast = state.particleHistory + state.particleCount * (state.currentFrame-1) + i; distance(zero, p->vel, velSpeed1); distance(p->vel, plast->vel, velSpeed2); accCurrent = velSpeed2 - velSpeed1; pd = getParticleDetail(i); d = accCurrent / accMax; colourFromNormal(pd->col, (float)fabs((double)d)); pd->particleSprite = colourSprite(pd->col, pd->mass); } }
/* ==================== perpendicularVector computes one of the vectors perpendicular to the provided vector. If the vector provided is the zero vector, the zero vector is returned ==================== */ Vector Vector::perpendicularVector() { if(x == 0 && y == 0 && z == 0) { return VectorZero(); } if(x <= y && x <= z) { return this->cross(1,0,0); } else if(y <= x && y <= z) { return this->cross(0,1,0); } else return this->cross(0,0,1); }
NAMESPACE_BEGIN ParticleSystem::ParticleSystem() : m_reduceSize (false), m_reduceAlpha (false), m_maxSize (0.0f), m_spread (0.0f), m_minFade (0.0f), m_maxFade (0.0f), m_maxLife (0.0f), m_count (0), m_frame (0) { #ifdef _DEBUG SetName("psystem"); #endif ColorZero(m_color); VectorZero(m_velocity); VectorZero(m_accel); MemZero(m_aParticles, sizeof(m_aParticles)); }
int luag_spawn(lua_State *L) { particle_t *p; particleDetail_t *pd; VectorNew(pos); VectorNew(vel); float mass; int id; VectorZero(pos); VectorZero(vel); mass = lua_tonumber(L, -1); id = -1; lua_pop(L, 1); luag_TableToVector(L, vel); lua_pop(L, 1); luag_TableToVector(L, pos); lua_pop(L, 1); id = lua_tonumber(L, -1); if (id < 0 || id >= state.particleCount) { conAdd(LERR, "Particle %i out of range", id); return 0; } p = getParticleFirstFrame(id); pd = getParticleDetail(id); VectorCopy(pos, p->pos); VectorCopy(vel, p->vel); pd->mass = mass; doVideoUpdateInSpawn(); return 0; }
static trace_t Cam_DoTrace (vec3_t vec1, vec3_t vec2) { #if 0 memset (&pmove, 0, sizeof (pmove)); pmove.numphysent = 1; VectorZero (pmove.physents[0].origin); pmove.physents[0].model = cl.worldmodel; #endif VectorCopy (vec1, pmove.origin); return PM_PlayerMove (pmove.origin, vec2); }
void setColoursByKinetic() { int i; particle_t *p; particleDetail_t *pd; float d; float kinMax = 0; float kinValue; float velocity; VectorNew(zero); VectorZero(zero); for (i = 0; i < state.particleCount; i++) { p = getParticleCurrentFrame(i); pd = getParticleDetail(i); distance(zero, p->vel, velocity); velocity = fabs(velocity); kinValue = velocity * velocity * pd->mass * 0.5; if (i == 0) { kinMax = kinValue; } else { if (kinValue > kinMax) kinMax = kinValue; } } for (i = 0; i < state.particleCount; i++) { p = getParticleFirstFrame(i); pd = getParticleDetail(i); distance(zero, p->vel, velocity); kinValue = velocity * velocity * pd->mass * 0.5; d = kinValue / kinMax; colourFromNormal(pd->col, (float)fabs((double)d)); pd->particleSprite = colourSprite(pd->col, pd->mass); } }
//************************************************************************************************* // Vector initialization //************************************************************************************************* SUINT vectorInit(SUINT& tests) { SUINT errors = 0; // Test case 1 - zero vector Vector v0 = VectorZero(); if(v0.m128_f32[0] != 0.0f || v0.m128_f32[1] != 0.0f || v0.m128_f32[2] != 0.0f || v0.m128_f32[3] != 0.0f) ++errors; ++tests; // Test case 2 - set to array Vector v1 = {0.0f, 0.0f, 0.0f, 0.0f}; if(v1.m128_f32[0] != 0.0f || v1.m128_f32[1] != 0.0f || v1.m128_f32[2] != 0.0f || v1.m128_f32[3] != 0.0f) ++errors; ++tests; Test::printResult(errors, tests, "VectorInit"); return errors; }
void translateToCenter() { int i; particle_t *p; VectorNew(pos); VectorZero(pos); for (i = 0; i < state.particleCount; i++) { p = getParticleCurrentFrame(i); VectorAdd(pos, p->pos, pos); } VectorDivide(pos, state.particleCount, pos); glTranslatef(-pos[0], -pos[1], -pos[2]); VectorCopy(pos, view.lastCenter); }
void setColoursByVel() { int i; particle_t *p; particleDetail_t *pd; float d; float velMax = 0; float velSpeed; VectorNew(zero); VectorZero(zero); // works out the highest velocity for (i = 0; i < state.particleCount; i++) { p = getParticleCurrentFrame(i); distance(zero, p->vel, velSpeed); velSpeed = fabs(velSpeed); if (i == 0) { velMax = velSpeed; } else { if (velSpeed > velMax) velMax = velSpeed; } } // applies velocity based on the highest for (i = 0; i < state.particleCount; i++) { p = getParticleFirstFrame(i); pd = getParticleDetail(i); distance(zero, p->vel, velSpeed); d = velSpeed / velMax; colourFromNormal(pd->col, (float)fabs((double)d)); pd->particleSprite = colourSprite(pd->col, pd->mass); } }
winding_t * BaseWindingForPlane (const plane_t *p) { int i, x; vec_t max, v; vec3_t org, vright, vup; winding_t *w; // find the major axis max = -BOGUS; x = -1; for (i = 0; i < 3; i++) { v = fabs (p->normal[i]); if (v > max) { x = i; max = v; } } if (x == -1) Sys_Error ("BaseWindingForPlane: no axis found"); VectorZero (vup); switch (x) { case 0: case 1: vup[2] = 1; break; case 2: vup[0] = 1; break; } v = DotProduct (vup, p->normal); VectorMultSub (vup, v, p->normal, vup); _VectorNormalize (vup); VectorScale (p->normal, p->dist, org); CrossProduct (vup, p->normal, vright); VectorScale (vup, BOGUS, vup); VectorScale (vright, BOGUS, vright); // project a really big axis aligned box onto the plane w = NewWinding (4); VectorSubtract (org, vright, w->points[0]); VectorAdd (w->points[0], vup, w->points[0]); VectorAdd (org, vright, w->points[1]); VectorAdd (w->points[1], vup, w->points[1]); VectorAdd (org, vright, w->points[2]); VectorSubtract (w->points[2], vup, w->points[2]); VectorSubtract (org, vright, w->points[3]); VectorSubtract (w->points[3], vup, w->points[3]); w->numpoints = 4; return w; }
void viewInit() { #ifndef NO_GUI view.useStdout = 0; view.rot[0] = view.rot[1] = view.rot[2] = 0; view.zoom = 10000; view.zoomFitAuto = 1; view.textMode = view.textMode; memset(view.pos, 0, sizeof(view.pos)); memset(view.face, 0, sizeof(view.face)); view.pos[2] -= 30; VectorZero(view.autoRotate); VectorZero(view.lastCenter); view.tailWidth = 1.0f; view.tailLength = 32; view.tailOpacity = 0.5f; view.tailFaded = 1; view.tailSkip = 1; view.screenSaver = 0; // 50ms by default (20fps) view.recordingVideoRefreshTime = 50; view.minVideoRefreshTime = 0; view.drawAxis = 1; view.consoleMode = 0; view.mouseButtons[0] = view.mouseButtons[1] = 0; view.lastMousePosition[0] = view.currentMousePosition[0] = video.screenW / 2; view.lastMousePosition[1] = view.currentMousePosition[1] = video.screenH / 2; view.showCursor = 1; view.fps = 100; view.drawTree = 0; view.frameSkip = 0; view.frameSkipCounter = 0; view.drawOSD = 1; view.drawColourScheme = 1; view.drawSky = 1; view.drawSkyRandom = 1; view.blendMode = 1; view.particleColourMode = CM_MASS; view.particleRenderMode = 2; view.particleRenderTexture = 1; view.particleSizeMin = 4; view.particleSizeMax = 127; view.verboseMode = 0; view.screenshotLoop = 0; view.screenshotIndex = 0; view.colourSpectrumSteps = 0; view.colourSpectrum = 0; view.stereoMode = 0; view.stereoModeCurrentBit = 0; // http://www.angelfire.com/ca/erker/freeview.html view.stereoSeparation = 5; // negative for "Parallel", positive for "Cross-eyed" view.stereoOSD = 0; cmdFps(NULL); view.timed_frames=0; view.totalRenderTime=0; view.zoomTarget = view.zoom; view.zoomSpeed = 0; VectorCopy(view.rot, view.rotTarget); VectorZero(view.rotSpeed); view.dirty = 0; memset(view.keys, 0, sizeof(view.keys)); view.recordStatus = 0; view.recordParticlesDone = 0; view.recordNodes = 0; strncpy(view.popupTextMessage, "Welcome to " GRAVIT_VERSION, 255); view.popupTextStart = 0; view.popupTextLength = 6000; view.popupTextFadeTime = 2000; // ms view.autoCenter = 1; view.glow = 3; view.maxVertices = 100000; #else view.useStdout = 1; #endif }
void run() { view.firstTimeStamp = view.lastRecordFrame = view.lastVideoFrame = getMS(); view.dirty = 0; view.lastVideoFrameSkip=0; view.zoomTarget = view.zoom; view.zoomSpeed = 0; VectorCopy(view.rot, view.rotTarget); VectorZero(view.rotSpeed); while (!view.quit) { Uint32 ts_before, ts_after; Uint32 ts; ts_before = getMS(); if (state.mode & SM_RECORD) { view.frameSkipCounter = 0; //if (view.verboseMode) // conAdd(LLOW, "R frame:%5i dt:%5i fs:%2i", state.totalFrames, view.deltaVideoFrame, state.historyNFrame); setTitle(va("%s frame: %i/%i (skip:%i)", STRING_RECORD, state.totalFrames, state.historyFrames, state.historyNFrame)); processFrame(); ts = getMS(); view.deltaRecordFrame = ts - view.lastRecordFrame; view.lastRecordFrame = ts; if (state.autoSave && (state.totalFrames - state.lastSave) >= state.autoSave) { cmdSaveFrameDump(0); state.lastSave = state.totalFrames; } } else if (state.mode & SM_PLAY) { if (view.frameSkip < 0) { view.frameSkipCounter++; if (view.frameSkipCounter > -view.frameSkip) { view.frameSkipCounter = 0; state.currentFrame++; } } else { state.currentFrame++; state.currentFrame+=view.frameSkip; } if (state.currentFrame >= state.frame) { state.currentFrame = 0; view.frameSkipCounter = 0; } //if (view.verboseMode) // conAdd(LLOW, "P frame:%5i dt:%5i fs:%2i", state.currentFrame, view.deltaVideoFrame, state.historyNFrame); } timerUpdate(); runInput(); if (view.quit) return; if (state.autoRecordNext) { state.autoRecordNext = 0; cmdRecord(0); } setColours(); if (view.zoomFitAuto == 2) { cmdZoomFit(NULL); view.zoomTarget = view.zoom; view.zoomSpeed = 0; } runVideo(); /* if we are not recording or replaying, wait a bit -- helps to cool down you laptop :-)) */ if (((state.mode & (SM_RECORD|SM_PLAY) ) == 0) && (view.dirty < 1)) { ts_after = getMS(); if (ts_after < (ts_before + SMALL_NAP)) SDL_Delay( SMALL_NAP - (ts_after - ts_before)); } /* pull the break on very fast video cards - 60fps playback is enough */ if (((state.mode & SM_PLAY ) == SM_PLAY) || (state.mode == 0)) { ts_after = getMS(); if (ts_after < (ts_before + PLAY_MIN_TIME)) SDL_Delay(PLAY_MIN_TIME - (ts_after - ts_before)); } /* if minVideoRefreshTime is set, hold the current frame a bit longer*/ if (view.minVideoRefreshTime >= SDL_TIMESLICE) { ts_after = getMS(); if (ts_after < (ts_before + view.minVideoRefreshTime)) SDL_Delay(view.minVideoRefreshTime - (ts_after - ts_before)); } // if last video frame was displayed, reset dirty flag if (view.lastVideoFrameSkip==0) { view.dirty = 0; if (view.drawAxis==3) view.drawAxis=1; } } }
int pickPositions() { int gals; VectorNew(galPos[100]); VectorNew(galVel[100]); VectorNew(shit); float galSize[100]; float galMassMin[100]; float galMassMax[100]; float spawnRange; int i; int g; particle_t *p; particleDetail_t *pd; float totalMass = 0; float angle; float angle2; float radius; gals = (rand() % (1 + spawnVars.maxGalCount-spawnVars.minGalCount)) + spawnVars.minGalCount; if (gals <= 0) { conAdd(LERR, "For some reason galaxies to spawn is 0 or less. Not possible!"); return 0; } if (gals >= 100) { conAdd(LERR, "Maximum galaxies to spawn is 100"); return 0; } spawnRange = frand(spawnVars.minSpawnRange, spawnVars.maxSpawnRange); conAdd(LNORM, "Spawning new simulation..."); conAdd(LLOW, "- %i particles...", state.particleCount); conAdd(LLOW, "- %i galaxies...", gals); for (g = 0; g < gals; g++) { galMassMin[g] = frand(spawnVars.minGalMass, spawnVars.maxGalMass); galMassMax[g] = frand(spawnVars.minGalMass, spawnVars.maxGalMass); galSize[g] = frand(spawnVars.minGalSize, spawnVars.maxGalSize); setRangePosition(galPos[g], spawnRange); setRangePosition(galVel[g], frand(0,1) * frand(0,1) * frand(spawnVars.minGalVel, spawnVars.maxGalVel)); } for (i = 0; i < state.particleCount; i++) { if (!(i % 100)) { view.recordParticlesDone = i; doVideoUpdateInSpawn(); } if (state.restartSpawning) { return 0; } p = getParticleFirstFrame(i); pd = getParticleDetail(i); g = rand() % gals; pd->mass = frand(galMassMin[g], galMassMax[g]); // if (g % 2 == 0) // pd->mass = -pd->mass; totalMass += pd->mass; // position VectorCopy(galPos[g], p->pos); setRangePosition((float *)&shit, galSize[g]); VectorAdd(p->pos, shit, p->pos); // galaxy structured position angle = frand(0, PI*2); radius = frand(0, galSize[g]); VectorZero(p->pos); p->pos[0] = cos(angle) * radius; p->pos[1] = sin(angle) * radius; p->pos[2] = frand(-radius/10, radius/10); VectorAdd(galPos[g], p->pos, p->pos); angle2 = angle + PI / 2; p->vel[0] = cos(angle2) * radius * 0.05f; p->vel[1] = sin(angle2) * radius * 0.05f; p->vel[2] = 0; VectorAdd(galVel[g], p->vel, p->vel); if (g & 2) { p->vel[0] = -p->vel[0]; p->vel[1] = -p->vel[1]; p->vel[2] = -p->vel[2]; } } conAdd(LLOW, "- %f total mass...", totalMass); conAdd(LLOW, "- %f galaxy mass...", totalMass / gals); conAdd(LLOW, "- %f particle mass...", totalMass / state.particleCount); return 0; }
// Scale-bias factors for decompressing fixed48 data (both rotation and translation) static const VectorRegister BiasFix48Data = MakeVectorRegister( -32767.0f, -32767.0f, -32767.0f, -32767.0f ); static const VectorRegister ScaleRotData = MakeVectorRegister( 3.0518509475997192297128208258309e-5f, 3.0518509475997192297128208258309e-5f, 3.0518509475997192297128208258309e-5f, 1.0f ); //@TODO: Looks like fixed48 for translation is basically broken right now (using 8 bits instead of 16 bits!). The scale is omitted below because it's all 1's static const VectorRegister BiasTransData = MakeVectorRegister( -255.0f, -255.0f, -255.0f, -255.0f ); static const VectorRegister ScaleTransData = MakeVectorRegister( 1.0f, 1.0f, 1.0f, 1.0f ); /** Decompress a single translation key from a single track that was compressed with the PerTrack codec (vectorized) */ static FORCEINLINE_DEBUGGABLE VectorRegister DecompressSingleTrackTranslationVectorized(int32 Format, int32 FormatFlags, const uint8* RESTRICT TopOfStream, const uint8* RESTRICT KeyData) { if( Format == ACF_Float96NoW ) { const VectorRegister KeyJumbled = VectorLoadNPlusOneUnalignedBytes(KeyData, Float96KeyBytesMinusOne[FormatFlags]); const VectorRegister XYZ = VectorPermute(KeyJumbled, VectorZero(), Trans96OptionalFormatPermMasks[FormatFlags & 7]); return XYZ; } else if (Format == ACF_Fixed48NoW) { const VectorRegister KeyJumbled = VectorLoadNPlusOneUnalignedBytes(KeyData, Fixed48KeyBytesMinusOne[FormatFlags]); const VectorRegister Key = VectorPermute(KeyJumbled, DecompressPTCTransConstants, Fix48FormatPermMasks[FormatFlags & 7]); const VectorRegister FPKey = VectorUitof(Key); const VectorRegister BiasedData = VectorAdd(FPKey, BiasTransData); //const VectorRegister XYZ = VectorMultiply(BiasedData, ScaleTransData); const VectorRegister XYZ = BiasedData; return XYZ; }