bool Grid::canNudge(bool left) { bool ret = true; if(!current) { return false; } int direction = 1; if(left) { direction = -1; } Vec4<Vec2i> blocks = current->getBricks(); if(blocks.X().Y() < H && (blocks.X().X()+direction > 0) && (blocks.X().X() + direction < (W-1)) && GD[((blocks.X().Y())*W)+blocks.X().X()+direction]) { ret = false; } if(blocks.Y().Y() < H && (blocks.Y().X()+direction > 0) && (blocks.Y().X() + direction < (W-1)) && GD[((blocks.Y().Y())*W)+blocks.Y().X()+direction]) { ret = false; } if(blocks.Z().Y() < H && (blocks.Z().X()+direction > 0) && (blocks.Z().X() + direction < (W-1)) && GD[((blocks.Z().Y())*W)+blocks.Z().X()+direction]) { ret = false; } if(blocks.W().Y() < H && (blocks.W().X()+direction > 0) && (blocks.W().X() + direction < (W-1)) && GD[((blocks.W().Y())*W)+blocks.W().X()+direction]) { ret = false; } return ret; }
bool Grid::collision() { bool ret = false; if(!current) { return false; } Vec4<Vec2i> blocks = current->getBricks(); if(blocks.X().Y() < H && (blocks.X().Y() == 0 || GD[((blocks.X().Y()-1)*W)+blocks.X().X()])) { ret = true; } if(blocks.Y().Y() < H && (blocks.Y().Y() == 0 || GD[((blocks.Y().Y()-1)*W)+blocks.Y().X()])) { ret = true; } if(blocks.Z().Y() < H && (blocks.Z().Y() == 0 || GD[((blocks.Z().Y()-1)*W)+blocks.Z().X()])) { ret = true; } if(blocks.W().Y() < H && (blocks.W().Y() == 0 || GD[((blocks.W().Y()-1)*W)+blocks.W().X()])) { ret = true; } return ret; }
Vec4 Vec4::cross3(Vec4 a, Vec4 b) { Vec4 result = Vec4( a.Y()*b.Z() - a.Z()*b.Y(), a.Z()*b.X() - a.X()*b.Z(), a.X()*b.Y() - a.Y()*b.X()); if (!a.isValid() || !b.isValid()) result.valid = VTERR; return result; }
bool Sphere::Intersect( Ray const &ray, float *tHit, float *epsilon, DifferentialGeometry *geom ) const { Transform tf = Tform(); Ray r = ray * Inverse( tf ); float t; if( !Intersect( ray, &t ) ) return false; // compute differential geometry Vec4 p = ray.Point( t ); float x = p.X(); float y = p.Y(); float z = p.Z(); if( x == 0.0f && z == 0.0f ) { // can't have both atan2 arguments be zero z = kEpsilon * m_radius; } float theta = atan2( p.X(), p.Z() ); if( theta < 0.0f ) { // remap theta to [0, 2pi] to match sphere's definition theta += k2Pi; } float phi = Acos( Clamp( z / m_radius, -1.0f, 1.0f ) ); // parameterize sphere hit float u = theta * kInv2Pi; float v = phi * kInvPi; float sTheta, cTheta; float sPhi, cPhi; SinCos( theta, &sTheta, &cTheta ); SinCos( phi, &sPhi, &cPhi ); Vec4 dpdu( k2Pi * z, 0.0f, -k2Pi * x, 0.0f ); Vec4 dpdv( kPi * y * sTheta, -kPi * m_radius * sPhi, kPi * y * cTheta, 0.0f ); Vec4 d2pdu2( -k2Pi * k2Pi * x, 0.0f, -k2Pi * k2Pi * z, 0.0f ); Vec4 d2pduv( k2Pi * kPi * y * cTheta, 0.0f, -k2Pi * kPi * y * sTheta, 0.0f ); Vec4 d2pdv2( -kPi * kPi * x, -kPi * kPi * y, -kPi * kPi * z, 0.0f ); // change in normal is computed using Weingarten equations Scalar E = Dot( dpdu, dpdu ); Scalar F = Dot( dpdu, dpdv ); Scalar G = Dot( dpdv, dpdv ); Vec4 N = Normalize( Cross( dpdu, dpdv ) ); Scalar e = Dot( N, d2pdu2 ); Scalar f = Dot( N, d2pduv ); Scalar g = Dot( N, d2pdv2 ); Scalar h = 1.0f / ( E * G - F * F ); Vec4 dndu = ( f * F - e * G ) * h * dpdu + ( e * F - f * E ) * h * dpdv; Vec4 dndv = ( g * F - f * G ) * h * dpdu + ( f * F - g * E ) * h * dpdv; *tHit = t; *epsilon = 5e-4f * t; // return world space differential geometry *geom = DifferentialGeometry( Handle(), p * tf, dpdu * tf, dpdv * tf, Normal( dndu ) * tf, Normal( dndv ) * tf, u, v ); return true; }
void Grid::Update() { if(GameOver()) { return; } if(current) { current->Update(); //check for boundaries Vec4<Vec2i> blocks = current->getBricks(); int minX = blocks.X().X(); int maxX = blocks.X().X(); if (blocks.Y().X() < minX) { minX = blocks.Y().X(); } if (blocks.Y().X() > maxX) { maxX = blocks.Y().X(); } if (blocks.Z().X() < minX) { minX = blocks.Z().X(); } if (blocks.Z().X() > maxX) { maxX = blocks.Z().X(); } if (blocks.W().X() < minX) { minX = blocks.W().X(); } if (blocks.W().X() > maxX) { maxX = blocks.W().X(); } if (minX < 0) { current->nudge(-minX,0); } if (maxX >= W) { current->nudge((W-maxX)-1,0); } if(collision()) { Brick* b = new Brick(Vec3f(blocks.X().X()*2,blocks.X().Y()*2,0)); Game::instance()->addObject(b); int a = blocks.X().Y()*W+blocks.X().X(); if(a < GD.size()) { GD[a] = b; } b = new Brick(Vec3f(blocks.Y().X()*2,blocks.Y().Y()*2,0)); Game::instance()->addObject(b); a = blocks.Y().Y()*W+blocks.Y().X(); if(a < GD.size()) { GD[a] = b; } b = new Brick(Vec3f(blocks.Z().X()*2,blocks.Z().Y()*2,0)); Game::instance()->addObject(b); a = blocks.Z().Y()*W+blocks.Z().X(); if(a < GD.size()) { GD[a] = b; } b = new Brick(Vec3f(blocks.W().X()*2,blocks.W().Y()*2,0)); Game::instance()->addObject(b); a = blocks.W().Y()*W+blocks.W().X(); if(a < GD.size()) { GD[a] = b; } delete current; current = 0; lines(); if(GameOver()) { SoundManager::instance()->playSound(failfx); } else { SoundManager::instance()->playSound(dropfx); } } } else { current = new Tetrad(); current->setPivot(Vec2i(5,17)); int lf = -linecount/7; current->setVel(Vec3f(0,-1+lf,0)); current->setPos(Vec3f(2*5,2*17,0)); } }
floatv Vec4::dot3(Vec4 a, Vec4 b) { floatv result = 0.0; if () result = a.X()*b.X() + a.Y()*b.Y() + a.Z()*b.Z(); return result; }
void BitoneClusterFit::ClusterFit4Constant(void* block) { // declare variables int const count = m_bitones->GetCount(); Vec4 const two = VEC4_CONST(2.0f); Vec4 const one = VEC4_CONST(1.0f); Vec4 const onethird_onethird2 (1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 9.0f); Vec4 const twothirds_twothirds2(2.0f / 3.0f, 2.0f / 3.0f, 2.0f / 3.0f, 4.0f / 9.0f); Vec4 const twonineths = VEC4_CONST(2.0f / 9.0f); assume((count > 0) && (count <= 16)); // check all possible clusters and iterate on the total order Vec4 beststart = VEC4_CONST(0.0f); Vec4 bestend = VEC4_CONST(0.0f); Scr4 besterror = m_besterror; u8 bestindices[16]; int bestiteration = 0; int besti = 0, bestj = 0, bestk = 0; // prepare an ordering using the principle axis ConstructOrdering(m_principle, 0); // loop over iterations (we avoid the case that all points in first or last cluster) for (int iterationIndex = 0;;) { // cache some values Vec4 const xsum_wsum = m_xsum_wsum; // constants if weights == 1 Vec4 alphabeta_dltas = *((Vec4 *)part2delta[0]); Vec4 *alphabeta_inits = (Vec4 *)part2inits[0]; float *alphabeta_factors = (float *)part2factors; #if 0 Vec4 lasta = Vec4(0.0f); Vec4 lastb = xsum_wsum; Vec4 lastc = Vec4(0.0f); #endif // first cluster [0,i) is at the start Vec4 part0 = VEC4_CONST(0.0f); for (int i = 0; i < count; ++i) { // second cluster [i,j) is one third along Vec4 part1 = VEC4_CONST(0.0f); for (int j = i;;) { // third cluster [j,k) is two thirds along Vec4 part2 = (j == 0) ? m_points_weights[0] : VEC4_CONST(0.0f); Vec4 alphabeta_val = *alphabeta_inits++; int kmin = (j == 0) ? 1 : j; for (int k = kmin;;) { // TODO: the inner alphabeta_sum seems always to be the same sequence Vec4 alphabeta_factor = alphabeta_val * Vec4(*alphabeta_factors++); // compute least squares terms directly Vec4 const alphax_sum = MultiplyAdd(part2, onethird_onethird2, MultiplyAdd(part1, twothirds_twothirds2, part0)); Vec4 const betax_sum = /*MultiplyAdd(part1, onethird_onethird2, MultiplyAdd(part2, twothirds_twothirds2, part3))*/ xsum_wsum - alphax_sum; Vec4 const alpha2_sum = alphabeta_val.SplatX(); Vec4 const beta2_sum = alphabeta_val.SplatY(); Vec4 const alphabeta_sum = alphabeta_val.SplatZ(); Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_factor.SplatZ(), alphax_sum * alphabeta_factor.SplatY()); Vec4 b = NegativeMultiplySubtract(alphax_sum, alphabeta_factor.SplatZ(), betax_sum * alphabeta_factor.SplatX()); #if 0 // last cluster [k,count) is at the end Vec4 part3 = xsum_wsum - part2 - part1 - part0; // compute least squares terms directly Vec4 const _alphax_sum = MultiplyAdd(part2, onethird_onethird2, MultiplyAdd(part1, twothirds_twothirds2, part0)); Vec4 const _betax_sum = MultiplyAdd(part1, onethird_onethird2, MultiplyAdd(part2, twothirds_twothirds2, part3)); // Vec4 const _betac_sum = xsum_wsum - _alphax_sum; Vec4 const _alpha2_sum = _alphax_sum.SplatW(); Vec4 const _beta2_sum = _betax_sum.SplatW(); Vec4 const _alphabeta_sum = twonineths * (part1 + part2).SplatW(); // compute the least-squares optimal points Vec4 _factor = Reciprocal(NegativeMultiplySubtract(_alphabeta_sum, _alphabeta_sum, _alpha2_sum * _beta2_sum)); Vec4 _a = NegativeMultiplySubtract( _betax_sum, _alphabeta_sum, _alphax_sum * _beta2_sum) * _factor; Vec4 _b = NegativeMultiplySubtract(_alphax_sum, _alphabeta_sum, _betax_sum * _alpha2_sum) * _factor; #undef limit #define limit 2e-5 assert(fabs(_alpha2_sum.W() - alpha2_sum.X()) < limit); assert(fabs(_beta2_sum.W() - beta2_sum.X()) < limit); assert(fabs(_alphabeta_sum.W() - alphabeta_sum.X()) < limit); if (alphabeta_factors[-1] != FLT_MAX) { assert(fabs(_factor.W() - alphabeta_factors[-1]) < limit); assert(fabs(_alpha2_sum.W() * _factor.W() - alphabeta_factor.X()) < limit); assert(fabs(_beta2_sum.W() * _factor.W() - alphabeta_factor.Y()) < limit); assert(fabs(_alphabeta_sum.W() * _factor.W() - alphabeta_factor.Z()) < limit); assert(fabs(a.X() - _a.X()) < limit); assert(fabs(a.Y() - _a.Y()) < limit); assert(fabs(a.Z() - _a.Z()) < limit); assert(fabs(b.X() - _b.X()) < limit); assert(fabs(b.Y() - _b.Y()) < limit); assert(fabs(b.Z() - _b.Z()) < limit); } #if 0 fprintf(stderr, "{%.9ff},", _factor.W()); if (k == kmin) fprintf(stderr, "{%.9f, %.9f, %.9f},\n", alpha2_sum.W(), beta2_sum.W(), alphabeta_sum.W()); fprintf(stderr, "{%.9f/*%.9f*/,%.9f/*%.9f*/,%.9f,%.9f},\n", alpha2_sum.W(), lasta.W() - alpha2_sum.W(), beta2_sum.W(), lastb.W() - beta2_sum.W(), alphabeta_sum.W(), lastc.W() - alphabeta_sum.W(), factor.W()); lasta = alpha2_sum; lastb = beta2_sum; lastc = alphabeta_sum; #endif #endif // snap floating-point-values to the integer-lattice a = Truncate(a * 255.0f) * (1.0f / 255.0f); b = Truncate(b * 255.0f) * (1.0f / 255.0f); // compute the error (we skip the constant xxsum) Vec4 e1 = MultiplyAdd(a * a, alpha2_sum, b * b * beta2_sum); Vec4 e2 = NegativeMultiplySubtract(a, alphax_sum, a * b * alphabeta_sum); Vec4 e3 = NegativeMultiplySubtract(b, betax_sum, e2); Vec4 e4 = MultiplyAdd(two, e3, e1); // apply the metric to the error term Scr4 eS = e4; // keep the solution if it wins if (besterror > eS) { besterror = eS; beststart = a; bestend = b; bestiteration = iterationIndex; besti = i; bestj = j; bestk = k; } alphabeta_val += alphabeta_dltas; // advance if (k == count) break; part2 += m_points_weights[k]; ++k; } // advance if (j == count) break; part1 += m_points_weights[j]; ++j; } // advance part0 += m_points_weights[i]; } // stop if we didn't improve in this iteration if (bestiteration != iterationIndex) break; // advance if possible ++iterationIndex; if (iterationIndex == m_iterationCount) break; // stop if a new iteration is an ordering that has already been tried Vec3 axis = (bestend - beststart).GetVec3(); if (!ConstructOrdering(axis, iterationIndex)) break; } // save the block if necessary if (besterror < m_besterror) { // save the error m_besterror = besterror; // remap the indices u8 const* order = (u8*)m_order + 16 * bestiteration; u8 unordered[16]; for (int m = 0; m < besti; ++m) unordered[order[m]] = 0; for (int m = besti; m < bestj; ++m) unordered[order[m]] = 2; for (int m = bestj; m < bestk; ++m) unordered[order[m]] = 3; for (int m = bestk; m < count; ++m) unordered[order[m]] = 1; m_bitones->RemapIndices(unordered, bestindices); // save the block WriteBitoneBlock4(beststart.GetVec3(), bestend.GetVec3(), bestindices, block); } }