END_CLASS void hhSlots::Spawn() { int ix; fruitTextures[FRUIT_CHERRY] = spawnArgs.GetString("mtr_cherry"); fruitTextures[FRUIT_ORANGE] = spawnArgs.GetString("mtr_orange"); fruitTextures[FRUIT_LEMON] = spawnArgs.GetString("mtr_lemon"); fruitTextures[FRUIT_APPLE] = spawnArgs.GetString("mtr_apple"); fruitTextures[FRUIT_GRAPE] = spawnArgs.GetString("mtr_grape"); fruitTextures[FRUIT_MELON] = spawnArgs.GetString("mtr_melon"); fruitTextures[FRUIT_BAR] = spawnArgs.GetString("mtr_bar"); fruitTextures[FRUIT_BARBAR] = spawnArgs.GetString("mtr_barbar"); fruitTextures[FRUIT_BARBARBAR] = spawnArgs.GetString("mtr_barbarbar"); for (ix=0; ix<SLOTS_IN_REEL; ix++) { reel1[ix] = (fruit_t)(ix % NUM_FRUITS); reel2[ix] = (fruit_t)(ix % NUM_FRUITS); reel3[ix] = (fruit_t)(ix % NUM_FRUITS); } // Shuffle reels int f1; for (ix=0; ix<5; ix++) { for (f1=0; f1<SLOTS_IN_REEL; f1++) { idSwap(reel1[f1], reel1[gameLocal.random.RandomInt(SLOTS_IN_REEL)]); idSwap(reel2[f1], reel2[gameLocal.random.RandomInt(SLOTS_IN_REEL)]); idSwap(reel3[f1], reel3[gameLocal.random.RandomInt(SLOTS_IN_REEL)]); } } Reset(); }
/* ============ idLCP_Symmetric::Swap ============ */ void idLCP_Symmetric::Swap(int i, int j) { if (i == j) { return; } idSwap(rowPtrs[i], rowPtrs[j]); m.SwapColumns(i, j); b.SwapElements(i, j); lo.SwapElements(i, j); hi.SwapElements(i, j); a.SwapElements(i, j); f.SwapElements(i, j); if (boxIndex) { idSwap(boxIndex[i], boxIndex[j]); } idSwap(side[i], side[j]); idSwap(permuted[i], permuted[j]); }
/* ============ idWinding2D::RayIntersection ============ */ bool idWinding2D::RayIntersection( const idVec2 &start, const idVec2 &dir, float &scale1, float &scale2, int *edgeNums ) const { int i, numEdges, localEdgeNums[2]; int sides[MAX_POINTS_ON_WINDING_2D+1], counts[3]; float d1, d2, epsilon = 0.1f; idVec3 plane, edges[2]; scale1 = scale2 = 0.0f; counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0; plane = Plane2DFromVecs( start, dir ); for ( i = 0; i < numPoints; i++ ) { d1 = plane.x * p[i].x + plane.y * p[i].y + plane.z; if ( d1 > epsilon ) { sides[i] = SIDE_FRONT; } else if ( d1 < -epsilon ) { sides[i] = SIDE_BACK; } else { sides[i] = SIDE_ON; } counts[sides[i]]++; } sides[i] = sides[0]; if ( !counts[SIDE_FRONT] ) { return false; } if ( !counts[SIDE_BACK] ) { return false; } numEdges = 0; for ( i = 0; i < numPoints; i++ ) { if ( sides[i] != sides[i+1] && sides[i+1] != SIDE_ON ) { localEdgeNums[numEdges] = i; edges[numEdges++] = Plane2DFromPoints( p[i], p[(i+1)%numPoints] ); if ( numEdges >= 2 ) { break; } } } if ( numEdges < 2 ) { return false; } d1 = edges[0].x * start.x + edges[0].y * start.y + edges[0].z; d2 = - ( edges[0].x * dir.x + edges[0].y * dir.y ); if ( d2 == 0.0f ) { return false; } scale1 = d1 / d2; d1 = edges[1].x * start.x + edges[1].y * start.y + edges[1].z; d2 = - ( edges[1].x * dir.x + edges[1].y * dir.y ); if ( d2 == 0.0f ) { return false; } scale2 = d1 / d2; if ( idMath::Fabs( scale1 ) > idMath::Fabs( scale2 ) ) { idSwap( scale1, scale2 ); idSwap( localEdgeNums[0], localEdgeNums[1] ); } if ( edgeNums ) { edgeNums[0] = localEdgeNums[0]; edgeNums[1] = localEdgeNums[1]; } return true; }
/* ==================== idRenderModelLiquid::Update ==================== */ void idRenderModelLiquid::Update( void ) { int x, y; float *p2; float *p1; float value; time += update_tics; idSwap( page1, page2 ); if ( time > nextDropTime ) { WaterDrop( -1, -1, page2 ); nextDropTime = time + drop_delay; } else if ( time < nextDropTime - drop_delay ) { nextDropTime = time + drop_delay; } p1 = page1; p2 = page2; switch( liquid_type ) { case 0 : for ( y = 1; y < verts_y - 1; y++ ) { p2 += verts_x; p1 += verts_x; for ( x = 1; x < verts_x - 1; x++ ) { value = ( p2[ x + verts_x ] + p2[ x - verts_x ] + p2[ x + 1 ] + p2[ x - 1 ] + p2[ x - verts_x - 1 ] + p2[ x - verts_x + 1 ] + p2[ x + verts_x - 1 ] + p2[ x + verts_x + 1 ] + p2[ x ] ) * ( 2.0f / 9.0f ) - p1[ x ]; p1[ x ] = value * density; } } break; case 1 : for ( y = 1; y < verts_y - 1; y++ ) { p2 += verts_x; p1 += verts_x; for ( x = 1; x < verts_x - 1; x++ ) { value = ( p2[ x + verts_x ] + p2[ x - verts_x ] + p2[ x + 1 ] + p2[ x - 1 ] + p2[ x - verts_x - 1 ] + p2[ x - verts_x + 1 ] + p2[ x + verts_x - 1 ] + p2[ x + verts_x + 1 ] ) * 0.25f - p1[ x ]; p1[ x ] = value * density; } } break; case 2 : for ( y = 1; y < verts_y - 1; y++ ) { p2 += verts_x; p1 += verts_x; for ( x = 1; x < verts_x - 1; x++ ) { value = ( p2[ x + verts_x ] + p2[ x - verts_x ] + p2[ x + 1 ] + p2[ x - 1 ] + p2[ x - verts_x - 1 ] + p2[ x - verts_x + 1 ] + p2[ x + verts_x - 1 ] + p2[ x + verts_x + 1 ] + p2[ x ] ) * ( 1.0f / 9.0f ); p1[ x ] = value * density; } } break; } }
/* ==================== idSurface_Polytope::SplitPolytope ==================== */ int idSurface_Polytope::SplitPolytope( const idPlane &plane, const float epsilon, idSurface_Polytope **front, idSurface_Polytope **back ) const { int side, i, j, s, v0, v1, v2, edgeNum; idSurface *surface[2]; idSurface_Polytope *polytopeSurfaces[2], *surf; int *onPlaneEdges[2]; onPlaneEdges[0] = (int *) _alloca( indexes.Num() / 3 * sizeof( int ) ); onPlaneEdges[1] = (int *) _alloca( indexes.Num() / 3 * sizeof( int ) ); side = Split( plane, epsilon, &surface[0], &surface[1], onPlaneEdges[0], onPlaneEdges[1] ); *front = polytopeSurfaces[0] = new idSurface_Polytope; *back = polytopeSurfaces[1] = new idSurface_Polytope; for ( s = 0; s < 2; s++ ) { if ( surface[s] ) { polytopeSurfaces[s] = new idSurface_Polytope; polytopeSurfaces[s]->SwapTriangles( *surface[s] ); delete surface[s]; surface[s] = NULL; } } *front = polytopeSurfaces[0]; *back = polytopeSurfaces[1]; if ( side != SIDE_CROSS ) { return side; } // add triangles to close off the front and back polytope for ( s = 0; s < 2; s++ ) { surf = polytopeSurfaces[s]; edgeNum = surf->edgeIndexes[onPlaneEdges[s][0]]; v0 = surf->edges[abs(edgeNum)].verts[INTSIGNBITSET(edgeNum)]; v1 = surf->edges[abs(edgeNum)].verts[INTSIGNBITNOTSET(edgeNum)]; for ( i = 1; onPlaneEdges[s][i] >= 0; i++ ) { for ( j = i+1; onPlaneEdges[s][j] >= 0; j++ ) { edgeNum = surf->edgeIndexes[onPlaneEdges[s][j]]; if ( v1 == surf->edges[abs(edgeNum)].verts[INTSIGNBITSET(edgeNum)] ) { v1 = surf->edges[abs(edgeNum)].verts[INTSIGNBITNOTSET(edgeNum)]; idSwap( onPlaneEdges[s][i], onPlaneEdges[s][j] ); break; } } } for ( i = 2; onPlaneEdges[s][i] >= 0; i++ ) { edgeNum = surf->edgeIndexes[onPlaneEdges[s][i]]; v1 = surf->edges[abs(edgeNum)].verts[INTSIGNBITNOTSET(edgeNum)]; v2 = surf->edges[abs(edgeNum)].verts[INTSIGNBITSET(edgeNum)]; surf->indexes.Append( v0 ); surf->indexes.Append( v1 ); surf->indexes.Append( v2 ); } surf->GenerateEdgeIndexes(); } return side; }
/* ============ idLCP_Square::Solve ============ */ bool idLCP_Square::Solve(const idMatX &o_m, idVecX &o_x, const idVecX &o_b, const idVecX &o_lo, const idVecX &o_hi, const int *o_boxIndex) { int i, j, n, limit, limitSide, boxStartIndex; float dir, maxStep, dot, s; char *failed; // true when the matrix rows are 16 byte padded padded = ((o_m.GetNumRows()+3)&~3) == o_m.GetNumColumns(); assert(padded || o_m.GetNumRows() == o_m.GetNumColumns()); assert(o_x.GetSize() == o_m.GetNumRows()); assert(o_b.GetSize() == o_m.GetNumRows()); assert(o_lo.GetSize() == o_m.GetNumRows()); assert(o_hi.GetSize() == o_m.GetNumRows()); // allocate memory for permuted input f.SetData(o_m.GetNumRows(), VECX_ALLOCA(o_m.GetNumRows())); a.SetData(o_b.GetSize(), VECX_ALLOCA(o_b.GetSize())); b.SetData(o_b.GetSize(), VECX_ALLOCA(o_b.GetSize())); lo.SetData(o_lo.GetSize(), VECX_ALLOCA(o_lo.GetSize())); hi.SetData(o_hi.GetSize(), VECX_ALLOCA(o_hi.GetSize())); if (o_boxIndex) { boxIndex = (int *)_alloca16(o_x.GetSize() * sizeof(int)); memcpy(boxIndex, o_boxIndex, o_x.GetSize() * sizeof(int)); } else { boxIndex = NULL; } // we override the const on o_m here but on exit the matrix is unchanged m.SetData(o_m.GetNumRows(), o_m.GetNumColumns(), const_cast<float *>(o_m[0])); f.Zero(); a.Zero(); b = o_b; lo = o_lo; hi = o_hi; // pointers to the rows of m rowPtrs = (float **) _alloca16(m.GetNumRows() * sizeof(float *)); for (i = 0; i < m.GetNumRows(); i++) { rowPtrs[i] = m[i]; } // tells if a variable is at the low boundary, high boundary or inbetween side = (int *) _alloca16(m.GetNumRows() * sizeof(int)); // index to keep track of the permutation permuted = (int *) _alloca16(m.GetNumRows() * sizeof(int)); for (i = 0; i < m.GetNumRows(); i++) { permuted[i] = i; } // permute input so all unbounded variables come first numUnbounded = 0; for (i = 0; i < m.GetNumRows(); i++) { if (lo[i] == -idMath::INFINITY && hi[i] == idMath::INFINITY) { if (numUnbounded != i) { Swap(numUnbounded, i); } numUnbounded++; } } // permute input so all variables using the boxIndex come last boxStartIndex = m.GetNumRows(); if (boxIndex) { for (i = m.GetNumRows() - 1; i >= numUnbounded; i--) { if (boxIndex[i] >= 0 && (lo[i] != -idMath::INFINITY || hi[i] != idMath::INFINITY)) { boxStartIndex--; if (boxStartIndex != i) { Swap(boxStartIndex, i); } } } } // sub matrix for factorization clamped.SetData(m.GetNumRows(), m.GetNumColumns(), MATX_ALLOCA(m.GetNumRows() * m.GetNumColumns())); diagonal.SetData(m.GetNumRows(), VECX_ALLOCA(m.GetNumRows())); // all unbounded variables are clamped numClamped = numUnbounded; // if there are unbounded variables if (numUnbounded) { // factor and solve for unbounded variables if (!FactorClamped()) { idLib::common->Printf("idLCP_Square::Solve: unbounded factorization failed\n"); return false; } SolveClamped(f, b.ToFloatPtr()); // if there are no bounded variables we are done if (numUnbounded == m.GetNumRows()) { o_x = f; // the vector is not permuted return true; } } #ifdef IGNORE_UNSATISFIABLE_VARIABLES int numIgnored = 0; #endif // allocate for delta force and delta acceleration delta_f.SetData(m.GetNumRows(), VECX_ALLOCA(m.GetNumRows())); delta_a.SetData(m.GetNumRows(), VECX_ALLOCA(m.GetNumRows())); // solve for bounded variables failed = NULL; for (i = numUnbounded; i < m.GetNumRows(); i++) { // once we hit the box start index we can initialize the low and high boundaries of the variables using the box index if (i == boxStartIndex) { for (j = 0; j < boxStartIndex; j++) { o_x[permuted[j]] = f[j]; } for (j = boxStartIndex; j < m.GetNumRows(); j++) { s = o_x[boxIndex[j]]; if (lo[j] != -idMath::INFINITY) { lo[j] = - idMath::Fabs(lo[j] * s); } if (hi[j] != idMath::INFINITY) { hi[j] = idMath::Fabs(hi[j] * s); } } } // calculate acceleration for current variable SIMDProcessor->Dot(dot, rowPtrs[i], f.ToFloatPtr(), i); a[i] = dot - b[i]; // if already at the low boundary if (lo[i] >= -LCP_BOUND_EPSILON && a[i] >= -LCP_ACCEL_EPSILON) { side[i] = -1; continue; } // if already at the high boundary if (hi[i] <= LCP_BOUND_EPSILON && a[i] <= LCP_ACCEL_EPSILON) { side[i] = 1; continue; } // if inside the clamped region if (idMath::Fabs(a[i]) <= LCP_ACCEL_EPSILON) { side[i] = 0; AddClamped(i); continue; } // drive the current variable into a valid region for (n = 0; n < maxIterations; n++) { // direction to move if (a[i] <= 0.0f) { dir = 1.0f; } else { dir = -1.0f; } // calculate force delta CalcForceDelta(i, dir); // calculate acceleration delta: delta_a = m * delta_f; CalcAccelDelta(i); // maximum step we can take GetMaxStep(i, dir, maxStep, limit, limitSide); if (maxStep <= 0.0f) { #ifdef IGNORE_UNSATISFIABLE_VARIABLES // ignore the current variable completely lo[i] = hi[i] = 0.0f; f[i] = 0.0f; side[i] = -1; numIgnored++; #else failed = va("invalid step size %.4f", maxStep); #endif break; } // change force ChangeForce(i, maxStep); // change acceleration ChangeAccel(i, maxStep); // clamp/unclamp the variable that limited this step side[limit] = limitSide; switch (limitSide) { case 0: { a[limit] = 0.0f; AddClamped(limit); break; } case -1: { f[limit] = lo[limit]; if (limit != i) { RemoveClamped(limit); } break; } case 1: { f[limit] = hi[limit]; if (limit != i) { RemoveClamped(limit); } break; } } // if the current variable limited the step we can continue with the next variable if (limit == i) { break; } } if (n >= maxIterations) { failed = va("max iterations %d", maxIterations); break; } if (failed) { break; } } #ifdef IGNORE_UNSATISFIABLE_VARIABLES if (numIgnored) { if (lcp_showFailures.GetBool()) { idLib::common->Printf("idLCP_Symmetric::Solve: %d of %d bounded variables ignored\n", numIgnored, m.GetNumRows() - numUnbounded); } } #endif // if failed clear remaining forces if (failed) { if (lcp_showFailures.GetBool()) { idLib::common->Printf("idLCP_Square::Solve: %s (%d of %d bounded variables ignored)\n", failed, m.GetNumRows() - i, m.GetNumRows() - numUnbounded); } for (j = i; j < m.GetNumRows(); j++) { f[j] = 0.0f; } } #if defined(_DEBUG) && 0 if (!failed) { // test whether or not the solution satisfies the complementarity conditions for (i = 0; i < m.GetNumRows(); i++) { a[i] = -b[i]; for (j = 0; j < m.GetNumRows(); j++) { a[i] += rowPtrs[i][j] * f[j]; } if (f[i] == lo[i]) { if (lo[i] != hi[i] && a[i] < -LCP_ACCEL_EPSILON) { int bah1 = 1; } } else if (f[i] == hi[i]) { if (lo[i] != hi[i] && a[i] > LCP_ACCEL_EPSILON) { int bah2 = 1; } } else if (f[i] < lo[i] || f[i] > hi[i] || idMath::Fabs(a[i]) > 1.0f) { int bah3 = 1; } } } #endif // unpermute result for (i = 0; i < f.GetSize(); i++) { o_x[permuted[i]] = f[i]; } // unpermute original matrix for (i = 0; i < m.GetNumRows(); i++) { for (j = 0; j < m.GetNumRows(); j++) { if (permuted[j] == i) { break; } } if (i != j) { m.SwapColumns(i, j); idSwap(permuted[i], permuted[j]); } } return true; }
/* ============ idAASLocal::ShowWallEdges ============ */ void idAASLocal::ShowWallEdges( const idVec3 &origin, int mode, bool showNumbers ) const { const int MAX_WALL_EDGES = 1024; int edges[MAX_WALL_EDGES]; float textSize; idPlayer *player = gameLocal.GetLocalPlayer(); if ( player == NULL ) { return; } idMat3 viewAxis = player->GetViewAxis(); idVec3 viewOrigin = player->GetViewPos(); idMat3 playerAxis = idAngles( 0.0f, -player->GetViewAngles().yaw, 0.0f ).ToMat3(); if ( mode == 3 ) { textSize = 0.2f; } else { textSize = 0.1f; } float radius = file->GetSettings().obstaclePVSRadius; int areaNum = PointReachableAreaNum( origin, DefaultSearchBounds(), AAS_AREA_REACHABLE_WALK, TravelFlagInvalidForTeam() ); //int numEdges = GetWallEdges( areaNum, idBounds( origin ).Expand( radius ), TFL_WALK, 64.0f, edges, MAX_WALL_EDGES ); int numEdges = GetObstaclePVSWallEdges( areaNum, edges, MAX_WALL_EDGES ); // move the wall edges to the start of the list int numWallEdges = 0; for ( int i = 0; i < numEdges; i++ ) { if ( ( file->GetEdge( abs( edges[i] ) ).flags & AAS_EDGE_WALL ) != 0 ) { idSwap( edges[numWallEdges++], edges[i] ); } } for ( int i = 0; i < numEdges; i++ ) { idVec3 start, end; GetEdge( edges[i], start, end ); if ( mode == 2 ) { start.z = end.z = origin.z; } else if ( mode == 3 ) { ProjectTopDown( start, viewOrigin, viewAxis, playerAxis, radius * 2.0f ); ProjectTopDown( end, viewOrigin, viewAxis, playerAxis, radius * 2.0f ); } if ( ( file->GetEdge( abs( edges[i] ) ).flags & AAS_EDGE_WALL ) != 0 ) { gameRenderWorld->DebugLine( colorRed, start, end, 0 ); } else { gameRenderWorld->DebugLine( colorGreen, start, end, 0 ); } if ( showNumbers ) { gameRenderWorld->DrawText( va( "%d", edges[i] ), ( start + end ) * 0.5f, textSize, colorWhite, viewAxis, 1, 0 ); } } if ( mode == 3 ) { idVec3 box[7] = { origin, origin, origin, origin, origin, origin, origin }; box[0][0] += radius; box[0][1] += radius; box[1][0] += radius; box[1][1] -= radius; box[2][0] -= radius; box[2][1] -= radius; box[3][0] -= radius; box[3][1] += radius; box[4][1] += radius; box[5][0] += radius * 0.1f; box[5][1] += radius - radius * 0.1f; box[6][0] -= radius * 0.1f; box[6][1] += radius - radius * 0.1f; for ( int i = 0; i < 7; i++ ) { ProjectTopDown( box[i], viewOrigin, viewAxis, playerAxis, radius * 2.0f ); } for ( int i = 0; i < 4; i++ ) { gameRenderWorld->DebugLine( colorCyan, box[i], box[(i+1)&3], 0 ); } gameRenderWorld->DebugLine( colorCyan, box[4], box[5], 0 ); gameRenderWorld->DebugLine( colorCyan, box[4], box[6], 0 ); } }