void rotateRow( int x, int y, int z, int v, int s) { // rotate all objects matching x, y, z mask with value v // s verse of rotation int j, i, ix, iy, iz; // animation loop 0-90 deg for(j = 0; j <= 90; j+= STEP) { // clear painting scren gClearScreen(); // clear the hidden screen // search all objects for matching pattern for( iz=0; iz<3; iz++) for( iy=0; iy<3; iy++) for(ix=0; ix<3; ix++) { if ( ix*iy*iz == 1) continue; // ignore c[1][1][1] i = c[ix][iy][iz]; // check if requires rotation if (( (ix+1)*x == v+1) || ((iy+1)*y == v+1) || ((iz+1)*z == v+1)) { // rotate the corresponding axis // transform and draw the object initMatrix( mo, x*s*j, y*s*j, z*s*j, 0, 0, 0); drawObject( mo, i); // if final rotation if ( j == 90) rotateObject( mo, i); } else { // transform and draw the object initMatrix( mo, 0, 0, 0, 0, 0, 0); drawObject( mo, i); } } // update visible screen copyV(); } // for j steps // update pointer matrix c[][][] rotateC( x, y, z, v, s); } // animate rotation of one row/face
void rotateCube( int alpha, int beta, int gamma) { int j, i, ar, br, gr; for(j = 0; j <= 90; j+= STEP) { // clear painting screen gClearScreen(); // clear the hidden screen // rotate the corresponding axis ar = alpha * j; br = beta * j; gr = gamma * j ; for( i=objc; i<MAXOBJ; i++) { // transform and draw the object initMatrix( mo, ar, br, gr, 0, 0, 0); drawObject( mo, i); // if final rotation if ( j == 90) rotateObject( mo, i); } // update visible screen copyV(); } // for j steps // update pointer matrix c[][][] for ( i=0; i<3; i++) { if (( alpha<0)||( beta<0)||( gamma<0)) rotateC( ( alpha!=0), ( beta!=0), ( gamma!=0), i, -1); else rotateC( ( alpha!=0), ( beta!=0), ( gamma!=0), i, +1); } } // animate rotation of entire cube
void initVideo( void) { gClearScreen(); InitGraph(); // define HRES x VRES window SetReg(0x04,(HRES-1)>>8); SetReg(0x05,(HRES-1)); SetReg(0x08,0x00); SetReg(0x09,(VRES-1)); copyV(); BacklightOn(); // 4. Timer3 on, prescaler 1:8, internal clock, period //OpenTimer3( T3_ON | T3_PS_1_256 | T3_SOURCE_INT, FRAME_T-1); // 9. Enable Timer3 Interrupts // set the priority level 6 //mT3SetIntPriority( 6); //mT3IntEnable( 1); } // initVideo
// ************************************************************ int main( void) { // double t; short v, i, j; char start; char roll; char s[32], kj; // init offsets x0 = 125; y0 = 100; z0 = 200; // hardware and video initialization MMBInit(); initVideo(); initMatrix( mw, AOFFS, BOFFS, GOFFS, x0, y0, z0); // 3. main loop while( 1) { roll = 1; start = 0; gClearScreen(); // splash screen setColor( 2); // red AT(8, 1); putsV( "Rubik's Cube Demo"); AT(8, 3); putsV( " LDJ v1.0"); AT(8, 5); putsV( " for PIC32MX4 MMB"); copyV(); // update visible screen while( !MMBReadKey()); srand( ReadCoreTimer()); // clear all objects objc = MAXOBJ; pyc = MAXPOLY; pc = MAXP; // init all objects angles for( i=0; i<MAXOBJ; i++) a[i] = b[i] = g[i] = 0; // create the rubik cube newCube(); // init cursor and define grid qx = 1; qy = 1; initGrid(); while ( roll) { // paint cube in current position (with cursor) gClearScreen(); // clear the hidden screen for( i=objc; i<MAXOBJ; i++) { initMatrix( mo, 0, 0, 0, 0, 0, 0); drawObject( mo, i); } drawCursor( qx, qy); copyV(); // read the joystick and rotate center rows kj = MMBGetKey(); if ( kj & 0x80) // long pressure { switch( kj & 0x7F){ case JOY_RIGHT: // rotate whole cube rotateCube( 0, +1, 0); break; case JOY_LEFT: // rotate whole cube rotateCube( 0, -1, 0); break; case JOY_UP: // rotate whole cube rotateCube( -1, 0, 0); break; case JOY_DOWN: // rotate whole cube rotateCube( +1, 0, 0); break; case JOY_SELECT: // rotate face counter clockwise rotateRow( 0, 0, 1, 2, +1); break; } } else // short pressure { switch( kj){ case JOY_RIGHT: // rotate only the current row if (qx == 2) rotateRow( 0, 1, 0, qy, +1); else qx++; break; case JOY_LEFT: // rotate only the current row if (qx == 0) rotateRow( 0, 1, 0, qy, -1); else qx--; break; case JOY_UP: // rotate only the current row if (qy == 2) rotateRow( 1, 0, 0, qx, -1); else qy++; break; case JOY_DOWN: // rotate only the current row if (qy == 0) rotateRow( 1, 0, 0, qx, +1); else qy--; break; case JOY_SELECT: // rotate face clockwise rotateRow( 0, 0, 1, 2, -1); break; } // switch } // short pressure } //roll } // main loop } // main
void FluidSimulator::project(){ /*for (int j = simulationGrid->height - 3; j >=1; j--){ for (int i = simulationGrid->width - 3; i >= 1; i--){ if (simulationGrid->getCellType(i, j) == FLUID){ std::cout << "i" << i << "j" << j << ": " << simulationGrid->cells[i-1][j].u << " " << simulationGrid->cells[i][j-1].v << " " << simulationGrid->cells[i][j].u << " " << simulationGrid->cells[i][j].v << " " << simulationGrid->cells[i + 1][j].u << " " << simulationGrid->cells[i][j + 1].v << "\n"; } } }*/ int fluidCellsCount = simulationGrid->getFluidCellCount(); std::cout <<"N" << fluidCellsCount << "\n"; int index = 0; for (int i = 0; i < simulationGrid->width; i++){ for (int j = 0; j < simulationGrid->height; j++){ if (simulationGrid->getCellType(i, j) == FLUID){ indices.insert(std::make_pair(std::make_pair(i, j), index++)); } } } std::cout << indices.size(); pressureCoefficients = new double*[fluidCellsCount]; double * rhs = calculateNegativeDivergence(); for (int i = 0; i < fluidCellsCount; i++){ // return if pressure is already divergent free if (rhs[i] != 0) break; if (i + 1 == fluidCellsCount){ indices.clear(); std::cout << "divFree\n"; return; } } double * Adiag = new double[fluidCellsCount](); double * Aplusi = new double[fluidCellsCount](); double * precon = new double[fluidCellsCount](); double * Aplusj = new double[fluidCellsCount](); double * Aprevi = new double[fluidCellsCount](); double * Aprevj = new double[fluidCellsCount](); double scale = dt / (DENSITY*simulationGrid->getCellSize()*simulationGrid->getCellSize()); for (int i = 0; i < simulationGrid->width; i++){ //compute A... where A*pressure(unknown) = negative divergence... pressure makes the field divergent free for (int j = 0; j < simulationGrid->height; j++){ if (simulationGrid->getCellType(i, j) != FLUID) continue; int place = indices[std::make_pair(i, j)]; if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i + 1, j) == FLUID){ Adiag[place] += scale; Aplusi[place] = -scale; } else if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i + 1, j) == FREE){ Adiag[place] += scale; } if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i, j + 1) == FLUID){ Adiag[place] += scale; Aplusj[place] = -scale; } else if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i, j + 1) == FREE) Adiag[place] += scale; if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i - 1, j) == FLUID){ Adiag[place] += scale; Aprevi[place] = -scale; } else if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i - 1, j) == FREE){ Adiag[place] += scale; } if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i, j-1) == FLUID){ Adiag[place] += scale; Aprevj[place] = -scale; } else if (simulationGrid->getCellType(i, j) == FLUID && simulationGrid->getCellType(i, j-1) == FREE){ Adiag[place] += scale; } /* if (simulationGrid->getCellType(i, j) == FREE && simulationGrid->getCellType(i, j + 1) == FLUID) Adiag[indices[std::make_pair(i, j + 1)]] += scale; if (simulationGrid->getCellType(i, j) == FREE && simulationGrid->getCellType(i + 1, j) == FLUID) Adiag[indices[std::make_pair(i + 1, j)]] += scale;*/ } } /*for (int i = 15; i < simulationGrid->width; i=i+9){ for (int j = 0; j < simulationGrid->height; j++){ if (simulationGrid->getCellType(i, j) != FLUID) continue; int place = indices[std::make_pair(i, j)]; std::cout << "***place:" << i << " " << j << " " << place << " Adiag: " << Adiag[place] / scale << "\n"; std::cout << " Aprevi: " << Aprevi[place] / scale << " " << getIndex(i-1, j) << " " << indices.count(std::make_pair(i-1, j)) << "\n"; std::cout << " Aprevj: " << Aprevj[place] / scale << " " << getIndex(i, j-1) << " " << indices.count(std::make_pair(i, j - 1)) << "\n"; std::cout << " Aplusi: " << Aplusi[place] / scale << " " << getIndex(i + 1, j) << " " << indices.count(std::make_pair(i + 1, j)) << "\n"; std::cout << " Aplusj: " << Aplusj[place] / scale << " " << getIndex(i, j+1) << " " << indices.count(std::make_pair(i, j + 1)) << "\n"; } }*/ double tau = 0.97, beta = 0.25; for (int i = 0; i < simulationGrid->width; i++){ //compute preconditioner... initial guess for solving the system for (int j = 0; j < simulationGrid->height; j++){ if (simulationGrid->getCellType(i, j) == FLUID){ int place = indices[std::make_pair(i, j)]; double e = Adiag[place]; if (indices.count(std::make_pair(i - 1, j)) > 0) e -= square(Aprevi[place] * precon[getIndex(i-1,j)]); if (indices.count(std::make_pair(i, j - 1)) > 0) e -= square(Aprevj[place] * precon[getIndex(i, j - 1)]); if (indices.count(std::make_pair(i - 1, j)) > 0) e -= tau*(Aplusi[getIndex(i - 1, j)] * Aplusj[getIndex(i - 1, j)] * square(precon[getIndex(i - 1, j)])); if (indices.count(std::make_pair(i, j - 1)) > 0) e -= tau*(Aplusj[getIndex(i, j - 1)] * Aplusi[getIndex(i, j - 1)] * square(precon[getIndex(i, j - 1)])); if (e < beta * Adiag[place]) e = Adiag[place]; precon[place] = 1 / sqrt(e+0.000001); } } } double * p = new double[fluidCellsCount](); double * r = copyV(rhs, fluidCellsCount); double * z = applyPreconditioner(Adiag, Aplusi, Aplusj, Aprevi, Aprevj, precon, r); double * s = copyV(z, fluidCellsCount); double dp = dotproduct(z, r, fluidCellsCount); bool done = false; double maxR; int iterations = 0; while (!done && iterations < MAX_ITERATIONS){ z = apply(Adiag, Aplusi, Aplusj, Aprevi, Aprevj, s, fluidCellsCount); double den = dotproduct(z, s, fluidCellsCount); if (den == 0) break; double alph = dp / den; maxR = 0; for (int i = 0; i < fluidCellsCount; i++){ p[i] = p[i] + alph*s[i]; r[i] = r[i] - alph*z[i]; if (r[i] > maxR) maxR = r[i]; } if (abs(maxR) <= TOLERANCE){ done = true; //std::cout << "MX" << maxR << "#"; break; } z = applyPreconditioner(Adiag, Aplusi, Aplusj, Aprevi, Aprevj, precon, r); double dpNew = dotproduct(z, r, fluidCellsCount); double beeta = dpNew / dp; //std::cout << "beeta" << beeta << "dp" << dp << "dpnew" << dpNew; for (int i = 0; i < fluidCellsCount; i++) s[i] = z[i] + beeta*s[i]; dp = dpNew; iterations++; //if (iterations + 1 == MAX_ITERATIONS || done) std::cout << "MX" << maxR << "#"; } for (int i = 0; i < fluidCellsCount; i++) p[i] *= dt / (DENSITY * simulationGrid->getCellSize()); double * res = apply(Adiag, Aplusi, Aplusj, Aprevi, Aprevj, p, fluidCellsCount); for (int i = 0; i < simulationGrid->width; i++){ for (int j = 0; j < simulationGrid->height; j++){ if (simulationGrid->getCellType(i, j) != FLUID) continue; int place = indices[std::make_pair(i, j)]; if (simulationGrid->getCellType(i, j) == FLUID && ( simulationGrid->getCellType(i - 1, j)!= FLUID || simulationGrid->getCellType(i + 1, j) != FLUID)){ std::cout << dt / (DENSITY * simulationGrid->getCellSize()) << "p " << p[place] << " "; std::cout << i << " " << j << "\n"; //std::cout << "^" << rhs[place] << "\n"; } } } //std::cout << "uterations: " << iterations << "\n"; /*for (int i = 0; i < fluidCellsCount; i++) std::cout << "p: " << p[i] << "\n";*/ for (int i = 0; i < simulationGrid->width; i++){ for (int j = 0; j < simulationGrid->height; j++){ double sc = 1; if (simulationGrid->getCellType(i, j) == FLUID){ int place = indices[std::make_pair(i, j)]; simulationGrid->cells[i][j].u -= sc*p[place]; simulationGrid->cells[i + 1][j].u += sc*p[place]; simulationGrid->cells[i][j].v -= sc*p[place]; simulationGrid->cells[i][j + 1].v += sc*p[place]; } } } for (int i = 0; i < simulationGrid->width; i++){ for (int j = 0; j < simulationGrid->height; j++){ if (simulationGrid->getCellType(i, j) == SOLID){ simulationGrid->cells[i][j].u = 0; if (i + 1 <simulationGrid->width) simulationGrid->cells[i + 1][j].u = 0; simulationGrid->cells[i][j].v = 0; if (j + 1 <simulationGrid->height) simulationGrid->cells[i][j + 1].v = 0; } } } /*for (int i = 0; i < simulationGrid->width; i++){ //compute preconditioner... initial guess for solving the system for (int j = 0; j < simulationGrid->height; j++){ if (simulationGrid->getCellType(i, j) != FLUID) continue; int place = indices[std::make_pair(i, j)]; if (simulationGrid->getCellType(i, j) == FLUID && (simulationGrid->getCellType(i - 1, j) != FLUID || simulationGrid->getCellType(i + 1, j) != FLUID)){ //std::cout << "u " << simulationGrid->cells[i][j].u << " v" << simulationGrid->cells[i][j].v ; std::cout << i << " " << j << "\n"; if (simulationGrid->getCellType(i - 1, j) == FLUID) std::cout << "* " << (simulationGrid->cells[i + 1][j].u + simulationGrid->cells[i][j].u) / 2 << " " << (simulationGrid->cells[i][j].v + simulationGrid->cells[i][j + 1].v) / 2 << "\n"; if (simulationGrid->getCellType(i + 1, j) == FLUID) std::cout << "* " << (simulationGrid->cells[i + 1][j].u + simulationGrid->cells[i][j].u) / 2 << " " << (simulationGrid->cells[i][j].v + simulationGrid->cells[i][j+1].v) / 2 <<"\n"; //std::cout << "^" << rhs[place] << "\n"; } } }*/ indices.clear(); delete[] rhs; delete[] Adiag; delete[] Aplusi; delete[] precon; delete[] Aplusj; delete[] Aprevi; delete[] Aprevj; std::cout << "aft" << indices.size(); }