void fluid_dampen(fluid *in_f, int y, pvt_fluidMode *mode) { struct dampen * d = &mode->dampen; field *f = d->f; float scale = d->e; int w = fieldWidth(f); int nc = fieldComponents(f); int sx = fieldStrideX(f); int sy = fieldStrideY(f)*y; float *ptr = fieldData(f); int i; for (i=0; i<w; i++) { int c; for (c=0; c<nc; c++) { fluidFloatPointer(ptr, sy)[c] *= scale; } sy+=sx; } }
/*! * \fn QDataSchemaDriver:: * \en * \brief * * \_en \ru * \brief * * \_ru */ QString QDataSchemaDriver::fieldSQLToDS( QSqlFieldInfo *ftypedef ) { QString t; int w, d; w = fieldWidth( ftypedef ); d = fieldDecimals( ftypedef ); switch ( ftypedef->type() ) { case QVariant::DateTime: t.sprintf("D 0 0"); break; case QVariant::Int: t.sprintf("I 0 0"); break; case QVariant::LongLong: t.sprintf("L 0 0"); break; case QVariant::String: #if QT_VERSION<0x040000 case QVariant::CString: #endif t.sprintf("S %d 0", w); break; case QVariant::Double: /* if ( drv == "QPSQL7" ) { d = w & 0xFF; w = ( w & 0xFF0000 ) >> 16; } if ( drv == "QMYSQL3" ) { w = w - d; if ( d==0 ) w--; } */ t.sprintf("N %d %d", w, d); break; default: t = ""; } #if QT_VERSION<0x040000 if ( ftypedef->isRequired() ) #else if ( ftypedef->requiredStatus() ) #endif t = t.section(" ",0,0)+"N "+t.section(" ",1); t = ftypedef->name()+" "+t; return t; }
void fluid_genPressure_black(fluid *in_f, int y, pvt_fluidMode *mode) { struct pressure *p = &mode->pressure; int w = fieldWidth(p->velX); int h = fieldHeight(p->velX); #ifdef __APPLE_ALTIVEC__ #elif defined __SSE3__ #else int sx = fieldStrideX(p->velX); #endif int sy = fieldStrideY(p->velY); float *velX = fieldData(p->velX); float *velY = fieldData(p->velY); float *pressure = fieldData(p->pressure); if (y == 0) { #ifdef X_SIMD x128f *vPressure = (x128f*)fluidFloatPointer(pressure, 0*sy); x128f *vPressureP = (x128f*)fluidFloatPointer(pressure, 1*sy); int x; w/=4; for (x=0; x<w; x++) { vPressure[x] = vPressureP[x]; } #else int x; for (x=0; x<w; x++) { fluidFloatPointer(pressure,x*sx)[0] = fluidFloatPointer(pressure,x*sx + sy)[0]; } #endif } else if (y == h-1) { #ifdef X_SIMD x128f *vPressure = (x128f*)fluidFloatPointer(pressure, y*sy); x128f *vPressureP = (x128f*)fluidFloatPointer(pressure, (y-1)*sy); int x; w/=4; for (x=0; x<w; x++) { vPressure[x] = vPressureP[x]; } #else int x; for (x=0; x<w; x++) { fluidFloatPointer(pressure,x*sx + y*sy)[0] = fluidFloatPointer(pressure,x*sx + (y-1)*sy)[0]; } #endif } else { #ifdef X_SIMD float *vPressureRow = fluidFloatPointer(pressure, y*sy); x128f *vPressure = (x128f*)vPressureRow; x128f *vVelX = (x128f*)fluidFloatPointer(velX, y*sy); x128f *vPressureN = (x128f*)fluidFloatPointer(pressure, (y+1)*sy); x128f *vVelYN = (x128f*)fluidFloatPointer(velY, (y+1)*sy); x128f *vPressureP = (x128f*)fluidFloatPointer(pressure, (y-1)*sy); x128f *vVelYP = (x128f*)fluidFloatPointer(velY, (y-1)*sy); x128f div4 = {0.0f, 1.0f/4.0f, 0.0f, 1.0f/4.0f}; x128f mask = {1.0f, 0.0f, 1.0f, 0.0f}; #endif #ifdef __APPLE_ALTIVEC__ //int myTempVariable = __mfspr( 1023 ); vector float vZero = {0,0,0,0}; vec_dstst(vPressure, 0x01000001, 0); vec_dst(vVelX, 0x01000001, 1); vec_dst(vVelYN, 0x01000001, 2); vec_dst(vVelYP, 0x01000001, 3); int x; { vector float tmp; //Compute shifts vector float sl_p = vec_sld(vPressure[0], vPressure[1],4); vector float sr_p = vec_sld(vZero, vPressure[0], 12); vector float sl_vx = vec_sld(vVelX[0], vVelX[1],4); vector float sr_vx = vec_sld(vZero, vVelX[0], 12); //Sum everything!!! tmp = vec_add(sl_p, sr_p); tmp = vec_add(tmp, vPressureN[0]); tmp = vec_add(tmp, vPressureP[0]); tmp = vec_sub(tmp, sl_vx); tmp = vec_add(tmp, sr_vx); tmp = vec_sub(tmp, vVelYN[0]); tmp = vec_add(tmp, vVelYP[0]); vPressure[0] = vec_madd(tmp, div4, vZero); vPressureRow[0] = vPressureRow[1]; } x=1; while (x<w/4-5) { PRESSURE_VEC_PRE(0) PRESSURE_VEC_PRE(1) PRESSURE_VEC_PRE(2) PRESSURE_VEC_PRE(3) PRESSURE_VEC_SHIFT(0) PRESSURE_VEC_SHIFT(1) PRESSURE_VEC_SHIFT(2) PRESSURE_VEC_SHIFT(3) PRESSURE_VEC_END(0) PRESSURE_VEC_END(1) PRESSURE_VEC_END(2) PRESSURE_VEC_END(3) x+=4; } while (x<w/4-1) { PRESSURE_VEC_PRE(0) PRESSURE_VEC_SHIFT(0) PRESSURE_VEC_END(0) x++; } { vector float tmp; //Compute shifts vector float sl_p = vec_sld(vPressure[x], vZero,4); vector float sr_p = vec_sld(vPressure[x-1], vPressure[x], 12); vector float sl_vx = vec_sld(vVelX[x], vZero,4); vector float sr_vx = vec_sld(vVelX[x-1], vVelX[x], 12); //Sum everything!!! tmp = vec_add(sl_p, sr_p); tmp = vec_add(tmp, vPressureN[x]); tmp = vec_add(tmp, vPressureP[x]); tmp = vec_sub(tmp, sl_vx); tmp = vec_add(tmp, sr_vx); tmp = vec_sub(tmp, vVelYN[x]); tmp = vec_add(tmp, vVelYP[x]); vPressure[x] = vec_madd(tmp, div4, vZero); vPressureRow[w-1] = vPressureRow[w-2]; } #elif defined __SSE3__ int x; { __m128 tmp; //Compute shifts __m128 sl_p = _mm_srli_sf128(vPressure[0],4); sl_p = _mm_add_ps(sl_p,_mm_slli_sf128(vPressure[1],12)); __m128 sr_p = _mm_slli_sf128(vPressure[0],4); __m128 sl_vx = _mm_srli_sf128(vVelX[0],4); sl_vx = _mm_add_ps(sl_vx,_mm_slli_sf128(vVelX[1],12)); __m128 sr_vx = _mm_slli_sf128(vVelX[0],4); //Sum everything!!! tmp = _mm_add_ps(sl_p, sr_p); tmp = _mm_add_ps(tmp, vPressureN[0]); tmp = _mm_add_ps(tmp, vPressureP[0]); tmp = _mm_sub_ps(tmp, sl_vx); tmp = _mm_add_ps(tmp, sr_vx); tmp = _mm_sub_ps(tmp, vVelYN[0]); tmp = _mm_add_ps(tmp, vVelYP[0]); vPressure[0] = _mm_mul_ps(tmp, div4); vPressureRow[0] = vPressureRow[1]; } x=1; while (x<w/4-9) { //Compute shifts (1) PRESSURE_SSE_PRE(0); PRESSURE_SSE_PRE(1); PRESSURE_SSE_PRE(2); //Sum everything!!! (1) PRESSURE_SSE_POST(0); PRESSURE_SSE_POST(1); PRESSURE_SSE_POST(2); x+=3; } while (x<w/4-1) { //Compute shifts PRESSURE_SSE_PRE(0); //Sum everything!!! PRESSURE_SSE_POST(0); x++; } { __m128 tmp; //Compute shifts __m128 sl_p = _mm_srli_sf128(vPressure[x],4); __m128 sr_p = _mm_slli_sf128(vPressure[x],4); sr_p = _mm_add_ps(sr_p,_mm_srli_sf128(vPressure[x-1],12)); __m128 sl_vx = _mm_srli_sf128(vVelX[x],4); __m128 sr_vx = _mm_slli_sf128(vVelX[x],4); sr_vx = _mm_add_ps(sr_vx,_mm_srli_sf128(vVelX[x-1],12)); //Sum everything!!! tmp = _mm_add_ps(sl_p, sr_p); tmp = _mm_add_ps(tmp, vPressureN[x]); tmp = _mm_add_ps(tmp, vPressureP[x]); tmp = _mm_sub_ps(tmp, sl_vx); tmp = _mm_add_ps(tmp, sr_vx); tmp = _mm_sub_ps(tmp, vVelYN[x]); tmp = _mm_add_ps(tmp, vVelYP[x]); vPressure[x] = _mm_mul_ps(tmp, div4); vPressureRow[w-1] = vPressureRow[w-2]; } #else float lastPressureX = fluidFloatPointer(pressure,sx + y*sy)[0]; float lastVelX = fluidFloatPointer(velX, y*sy)[0]; float curPressureX = lastPressureX; float curVelX = fluidFloatPointer(velX, sx + y*sy)[0]; fluidFloatPointer(pressure,y*sy)[0] = lastPressureX; int x; int curxy = sx + y*sy; for (x=1; x<w-1; x++) { float nextPressureX = fluidFloatPointer(pressure,curxy + sx)[0]; float nextVelX = fluidFloatPointer(velX,curxy + sx)[0]; fluidFloatPointer(pressure,curxy)[0] = ( lastPressureX + nextPressureX + fluidFloatPointer(pressure,curxy - sy)[0] + fluidFloatPointer(pressure,curxy + sy)[0] - ( nextVelX - lastVelX + fluidFloatPointer(velY,curxy + sy)[0] - fluidFloatPointer(velY,curxy - sy)[0])) / 4.0f; lastPressureX = curPressureX; curPressureX = nextPressureX; lastVelX = curVelX; curVelX = nextVelX; curxy += sx; } fluidFloatPointer(pressure,(w-1)*sx + y*sy)[0] = fluidFloatPointer(pressure,(w-2)*sx + y*sy)[0]; #endif } }
//Basic advection of only the velocity... void fluid_advection_stam_velocity(fluid *in_f, int y, pvt_fluidMode *mode) { int x; int w = fieldWidth(mode->advection_stam_velocity.srcVelX); int h = fieldHeight(mode->advection_stam_velocity.srcVelY); float *velX = fieldData(mode->advection_stam_velocity.srcVelX); float *velY = fieldData(mode->advection_stam_velocity.srcVelY); float *velDestX = fieldData(mode->advection_stam_velocity.dstVelX); float *velDestY = fieldData(mode->advection_stam_velocity.dstVelY); int sX = fieldStrideX(mode->advection_stam_velocity.srcVelX); int sY = fieldStrideY(mode->advection_stam_velocity.srcVelY); float timestep = mode->advection_stam_velocity.timestep; //Loop over the data and do the desired computation float fx; float fy = (float)y; #define ADVECT_PRE(n) \ float fDataX ## n = fluidFloatPointer(velX, x*sX + y*sY)[n]; \ float fDataY ## n = fluidFloatPointer(velY, x*sX + y*sY)[n]; \ \ /*Find the cell back in time (keep a -10,10 radius)*/ \ float backX ## n = -timestep * fDataX ## n + fx+n; \ float backY ## n = -timestep * fDataY ## n + fy; \ \ int nBackX ## n = (int)backX ## n; \ int nBackY ## n = (int)backY ## n; \ \ float scaleX ## n = backX ## n - (float)(nBackX ## n); \ float scaleY ## n = backY ## n - (float)(nBackY ## n); \ \ /*Clamp as it's easier to parallelize given the scheduler*/ \ nBackX ## n = fluidClamp(nBackX ## n, 0,w-2); \ nBackY ## n = fluidClamp(nBackY ## n, 0,h-2); \ \ /*That was easy... now advect the velocity...*/ \ float *fVelDestX ## n = fluidFloatPointer(velDestX, x*sX + y*sY); \ float *fVelDestY ## n = fluidFloatPointer(velDestY, x*sX + y*sY); \ \ int offBackX ## n = nBackX ## n * sX; \ int offBackY ## n = nBackY ## n * sY; \ int offX2 ## n = offBackX ## n + sX; \ int offY2 ## n = offBackY ## n + sY; \ \ float bZZ_x ## n = fluidFloatPointer(velX, offBackX ## n + offBackY ## n)[0]; \ float bOZ_x ## n = fluidFloatPointer(velX, offX2 ## n + offBackY ## n)[0]; \ float bZO_x ## n = fluidFloatPointer(velX, offBackX ## n + offY2 ## n)[0]; \ float bOO_x ## n = fluidFloatPointer(velX, offX2 ## n + offY2 ## n)[0]; \ \ float bZZ_y ## n = fluidFloatPointer(velY, offBackX ## n + offBackY ## n)[0]; \ float bOZ_y ## n = fluidFloatPointer(velY, offX2 ## n + offBackY ## n)[0]; \ float bZO_y ## n = fluidFloatPointer(velY, offBackX ## n + offY2 ## n)[0]; \ float bOO_y ## n = fluidFloatPointer(velY, offX2 ## n + offY2 ## n)[0]; #define ADVECT_X(n) \ fVelDestX ## n[n] = fluidLinearInterpolation(scaleX ## n, scaleY ## n, \ bZZ_x ## n, bOZ_x ## n, bZO_x ## n, bOO_x ## n); #define ADVECT_Y(n) \ fVelDestY ## n[n] = fluidLinearInterpolation(scaleX ## n, scaleY ## n, \ bZZ_y ## n, bOZ_y ## n, bZO_y ## n, bOO_y ## n); x=0; fx=0; while(x<w-3) { ADVECT_PRE(0) ADVECT_PRE(1) ADVECT_PRE(2) ADVECT_X(0) ADVECT_X(1) ADVECT_X(2) ADVECT_Y(0) ADVECT_Y(1) ADVECT_Y(2) x+=3; fx+=3; } while(x<w) { ADVECT_PRE(0) ADVECT_X(0) ADVECT_Y(0) x++; fx++; } }
int fieldServerOnConnect(void *i, netServer *s, netClient *c) { fieldServer *r = (fieldServer*)i; struct fieldServerJitHeader header; double prevTime; //Store times (no manipulation == easier!) int hasLatency = 0; //Set to 1 after first matrix arrives. nextPacket: netClientGetBinary(c, &header, sizeof(header), 10); header.id = ntohl(header.id); if (header.id == 'JMTX') { struct fieldServerJitLatency latency; latency.id = htonl('JMLP'); //printf("FieldServer: Jitter Matrix!\n"); struct fieldServerJitMatrix matrixInfo; // int invByteOrder = 0; // if (sizeof(matrixInfo) != header.size) // { // header.size = ntohl(header.size); // if (header.size != sizeof(matrixInfo)) // { // printf("FieldServer: ERROR: More data sent than expected! (sent %i expected %u)\n", // header.size, (unsigned int)sizeof(matrixInfo)); // return 0; // } // else // invByteOrder = 1; // } netClientGetBinary(c, &matrixInfo, sizeof(matrixInfo), 10); matrixInfo.planeCount = ntohl(matrixInfo.planeCount); matrixInfo.type = ntohl(matrixInfo.type); matrixInfo.dimCount = ntohl(matrixInfo.dimCount); if (matrixInfo.dimCount < 2 || matrixInfo.dimCount > 32) { printf("FieldServer: ERROR: Insane dim count! (sent %i)\n", matrixInfo.dimCount); return 0; } int x; for (x=0; x<matrixInfo.dimCount; x++) matrixInfo.dim[x] = ntohl(matrixInfo.dim[x]); for (x=0; x<matrixInfo.dimCount; x++) matrixInfo.dimStride[x] = ntohl(matrixInfo.dimStride[x]); matrixInfo.dataSize = ntohl(matrixInfo.dataSize); //printf(" - planeCount: %u\n", matrixInfo.planeCount); //printf(" - dimCount: %u\n", matrixInfo.dimCount); //printf(" - time: %f\n", matrixInfo.time); int sizeOfData; if (r->dataType == FIELD_JIT_FLOAT32) sizeOfData = 4; else sizeOfData = 1; pthread_mutex_lock(&r->mtx); while (r->needSwap == 1) { x_pthread_cond_wait(&r->cnd, &r->mtx); if (r->server == NULL) { pthread_mutex_unlock(&r->mtx); return 0; } } pthread_mutex_unlock(&r->mtx); //Attempt to resize the field fieldResize_sy(r->fld_net, matrixInfo.dim[0], matrixInfo.dim[1], matrixInfo.dimStride[1]); //Loop over and receive!!! if (matrixInfo.dimCount == 2 && matrixInfo.type == r->dataType && matrixInfo.planeCount == fieldComponents(r->fld_net) && matrixInfo.dim[0] == fieldWidth(r->fld_net) && matrixInfo.dim[1] == fieldHeight(r->fld_net) && matrixInfo.dimStride[0] == fieldStrideX(r->fld_net) && matrixInfo.dimStride[1] == fieldStrideY(r->fld_net) && matrixInfo.dataSize == fieldStrideY(r->fld_net) * fieldHeight(r->fld_net)) { //printf(" - OPTIMAL!\n"); float *d = fieldData(r->fld_net); netClientGetBinary(c, d, matrixInfo.dataSize, 10); pthread_mutex_lock(&r->mtx); r->needSwap = 1; if (r->server == NULL) { pthread_mutex_unlock(&r->mtx); return 0; } //printf("AWAKE!!\n"); pthread_mutex_unlock(&r->mtx); if (hasLatency == 0) { hasLatency = 1; prevTime = matrixInfo.time; } else { latency.client_time = prevTime; latency.parsed_header = matrixInfo.time; latency.parsed_done = matrixInfo.time; /*double diff = latency.parsed_header - matrixInfo.time; latency.parsed_header -= diff; latency.parsed_done -= diff; diff = (latency.parsed_done-latency.parsed_header)/2; latency.parsed_header += diff; latency.parsed_done += diff;*/ //printf("LATENCY (%f,%f,%f)\n",latency.client_time, // latency.parsed_done, // latency.parsed_header); netClientSendBinary(c, &latency, sizeof(latency)); prevTime = matrixInfo.time; } goto nextPacket; } else { printf(" - Backup data fetcher = discard...\n"); printf(" --> Type: %u (%u)\n", matrixInfo.type, r->dataType); printf(" --> Dims: %u (%u)\n", matrixInfo.dimCount, 2); printf(" --> Planes: %u (%u)\n", matrixInfo.planeCount, fieldComponents(r->fld_net)); printf(" --> Width: %u (%u)\n", matrixInfo.dim[0], fieldWidth(r->fld_net)); printf(" --> Height: %u (%u)\n", matrixInfo.dim[1], fieldHeight(r->fld_net)); printf(" --> StrideX: %u (%u)\n", matrixInfo.dimStride[0], fieldStrideX(r->fld_net)); printf(" --> StrideY: %u (%u)\n", matrixInfo.dimStride[1], fieldStrideY(r->fld_net)); printf(" --> dataSize: %u (%u)\n", matrixInfo.dataSize, fieldStrideY(r->fld_net) * fieldHeight(r->fld_net)); } } else if (header.id == 'JMLP') { printf("FieldServer: Jitter Latency!\n"); } else if (header.id == 'JMMP') { int rdMsg = 0; pthread_mutex_lock(&r->mtx); while ((r->curWriteMsg + 2) % 8 == r->curReadMsg) { printf("FieldServer: MSG Stall\n"); x_pthread_cond_wait(&r->cndMsg, &r->mtx); if (r->server == NULL) { pthread_mutex_unlock(&r->mtx); return 0; } } //printf("FieldServer: MSG Pass\n"); rdMsg = r->curWriteMsg; pthread_mutex_unlock(&r->mtx); fieldMsgReceive(r->msg_loop[rdMsg], c); pthread_mutex_lock(&r->mtx); r->curWriteMsg = (r->curWriteMsg+1)%8; pthread_mutex_unlock(&r->mtx); goto nextPacket; } else { char *cda = (char*)&header.id; printf("FieldServer: ERROR: Unknown Packet '%c%c%c%c'!\n",cda[0],cda[1], cda[2], cda[3]); return 0; } printf("FieldServer: Completed Processing!\n"); return 0; }
bool QgsNewGeoPackageLayerDialog::apply() { QString fileName( mDatabase->filePath() ); if ( !fileName.endsWith( QLatin1String( ".gpkg" ), Qt::CaseInsensitive ) ) fileName += QLatin1String( ".gpkg" ); bool createNewDb = false; if ( QFile( fileName ).exists( fileName ) ) { bool overwrite = false; switch ( mBehavior ) { case Prompt: { QMessageBox msgBox; msgBox.setIcon( QMessageBox::Question ); msgBox.setWindowTitle( tr( "The File Already Exists." ) ); msgBox.setText( tr( "Do you want to overwrite the existing file with a new database or add a new layer to it?" ) ); QPushButton *overwriteButton = msgBox.addButton( tr( "Overwrite" ), QMessageBox::ActionRole ); QPushButton *addNewLayerButton = msgBox.addButton( tr( "Add new layer" ), QMessageBox::ActionRole ); msgBox.setStandardButtons( QMessageBox::Cancel ); msgBox.setDefaultButton( addNewLayerButton ); bool cancel = false; if ( property( "hideDialogs" ).toBool() ) { overwrite = property( "question_existing_db_answer_overwrite" ).toBool(); if ( !overwrite ) cancel = !property( "question_existing_db_answer_add_new_layer" ).toBool(); } else { int ret = msgBox.exec(); if ( ret == QMessageBox::Cancel ) cancel = true; if ( msgBox.clickedButton() == overwriteButton ) overwrite = true; } if ( cancel ) { return false; } break; } case Overwrite: overwrite = true; break; case AddNewLayer: overwrite = false; break; } if ( overwrite ) { QFile( fileName ).remove(); createNewDb = true; } } else { createNewDb = true; } OGRSFDriverH hGpkgDriver = OGRGetDriverByName( "GPKG" ); if ( !hGpkgDriver ) { if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), tr( "GeoPackage driver not found" ) ); return false; } gdal::ogr_datasource_unique_ptr hDS; if ( createNewDb ) { hDS.reset( OGR_Dr_CreateDataSource( hGpkgDriver, fileName.toUtf8().constData(), nullptr ) ); if ( !hDS ) { QString msg( tr( "Creation of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } } else { OGRSFDriverH hDriver = nullptr; hDS.reset( OGROpen( fileName.toUtf8().constData(), true, &hDriver ) ); if ( !hDS ) { QString msg( tr( "Opening of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } if ( hDriver != hGpkgDriver ) { QString msg( tr( "Opening of file succeeded, but this is not a GeoPackage database" ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } } QString tableName( mTableNameEdit->text() ); bool overwriteTable = false; if ( OGR_DS_GetLayerByName( hDS.get(), tableName.toUtf8().constData() ) ) { if ( property( "hideDialogs" ).toBool() ) { overwriteTable = property( "question_existing_layer_answer_overwrite" ).toBool(); } else if ( QMessageBox::question( this, tr( "Existing layer" ), tr( "A table with the same name already exists. Do you want to overwrite it?" ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::Yes ) { overwriteTable = true; } if ( !overwriteTable ) { return false; } } QString layerIdentifier( mLayerIdentifierEdit->text() ); QString layerDescription( mLayerDescriptionEdit->text() ); OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType> ( mGeometryTypeBox->currentData( Qt::UserRole ).toInt() ); // z-coordinate & m-value. if ( mGeometryWithZCheckBox->isChecked() ) wkbType = OGR_GT_SetZ( wkbType ); if ( mGeometryWithMCheckBox->isChecked() ) wkbType = OGR_GT_SetM( wkbType ); OGRSpatialReferenceH hSRS = nullptr; // consider spatial reference system of the layer QgsCoordinateReferenceSystem srs = mCrsSelector->crs(); if ( wkbType != wkbNone && srs.isValid() ) { QString srsWkt = srs.toWkt(); hSRS = OSRNewSpatialReference( srsWkt.toLocal8Bit().data() ); } // Set options char **options = nullptr; if ( overwriteTable ) options = CSLSetNameValue( options, "OVERWRITE", "YES" ); if ( !layerIdentifier.isEmpty() ) options = CSLSetNameValue( options, "IDENTIFIER", layerIdentifier.toUtf8().constData() ); if ( !layerDescription.isEmpty() ) options = CSLSetNameValue( options, "DESCRIPTION", layerDescription.toUtf8().constData() ); QString featureId( mFeatureIdColumnEdit->text() ); if ( !featureId.isEmpty() ) options = CSLSetNameValue( options, "FID", featureId.toUtf8().constData() ); QString geometryColumn( mGeometryColumnEdit->text() ); if ( wkbType != wkbNone && !geometryColumn.isEmpty() ) options = CSLSetNameValue( options, "GEOMETRY_COLUMN", geometryColumn.toUtf8().constData() ); if ( wkbType != wkbNone ) options = CSLSetNameValue( options, "SPATIAL_INDEX", mCheckBoxCreateSpatialIndex->isChecked() ? "YES" : "NO" ); OGRLayerH hLayer = OGR_DS_CreateLayer( hDS.get(), tableName.toUtf8().constData(), hSRS, wkbType, options ); CSLDestroy( options ); if ( hSRS ) OSRRelease( hSRS ); if ( !hLayer ) { QString msg( tr( "Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } QTreeWidgetItemIterator it( mAttributeView ); while ( *it ) { QString fieldName( ( *it )->text( 0 ) ); QString fieldType( ( *it )->text( 1 ) ); QString fieldWidth( ( *it )->text( 2 ) ); OGRFieldType ogrType( OFTString ); if ( fieldType == QLatin1String( "text" ) ) ogrType = OFTString; else if ( fieldType == QLatin1String( "integer" ) ) ogrType = OFTInteger; else if ( fieldType == QLatin1String( "integer64" ) ) ogrType = OFTInteger64; else if ( fieldType == QLatin1String( "real" ) ) ogrType = OFTReal; else if ( fieldType == QLatin1String( "date" ) ) ogrType = OFTDate; else if ( fieldType == QLatin1String( "datetime" ) ) ogrType = OFTDateTime; int ogrWidth = fieldWidth.toInt(); gdal::ogr_field_def_unique_ptr fld( OGR_Fld_Create( fieldName.toUtf8().constData(), ogrType ) ); OGR_Fld_SetWidth( fld.get(), ogrWidth ); if ( OGR_L_CreateField( hLayer, fld.get(), true ) != OGRERR_NONE ) { if ( !property( "hideDialogs" ).toBool() ) { QMessageBox::critical( this, tr( "Layer creation failed" ), tr( "Creation of field %1 failed (OGR error: %2)" ) .arg( fieldName, QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); } return false; } ++it; } // In GDAL >= 2.0, the driver implements a deferred creation strategy, so // issue a command that will force table creation CPLErrorReset(); OGR_L_ResetReading( hLayer ); if ( CPLGetLastErrorType() != CE_None ) { QString msg( tr( "Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) ); if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Layer creation failed" ), msg ); return false; } hDS.reset(); QString uri( QStringLiteral( "%1|layername=%2" ).arg( fileName, tableName ) ); QString userVisiblelayerName( layerIdentifier.isEmpty() ? tableName : layerIdentifier ); QgsVectorLayer *layer = new QgsVectorLayer( uri, userVisiblelayerName, QStringLiteral( "ogr" ) ); if ( layer->isValid() ) { // register this layer with the central layers registry QList<QgsMapLayer *> myList; myList << layer; //addMapLayers returns a list of all successfully added layers //so we compare that to our original list. if ( myList == QgsProject::instance()->addMapLayers( myList ) ) return true; } else { if ( !property( "hideDialogs" ).toBool() ) QMessageBox::critical( this, tr( "Invalid Layer" ), tr( "%1 is an invalid layer and cannot be loaded." ).arg( tableName ) ); delete layer; } return false; }
//Basic advection of only the velocity... void fluid_advection_stam_velocity_npt(fluid *in_f, int y, pvt_fluidMode *mode) { int x; int w = fieldWidth(mode->advection_stam_velocity.srcVelX); int h = fieldHeight(mode->advection_stam_velocity.srcVelY); float *velX = fieldData(mode->advection_stam_velocity.srcVelX); float *velY = fieldData(mode->advection_stam_velocity.srcVelY); float *velDestX = fieldData(mode->advection_stam_velocity.dstVelX); float *velDestY = fieldData(mode->advection_stam_velocity.dstVelY); float *repDestX = fieldData(mode->advection_stam_velocity.dstReposX); float *repDestY = fieldData(mode->advection_stam_velocity.dstReposY); int sX = fieldStrideX(mode->advection_stam_velocity.srcVelX); int sY = fieldStrideY(mode->advection_stam_velocity.srcVelY); float timestep = -mode->advection_stam_velocity.timestep * 0.1f; //Loop over the data and do the desired computation float fx; float fy = (float)y; x=0; fx=0; while(x<w) { float fDataX = fluidFloatPointer(velX, x*sX + y*sY)[0]; float fDataY = fluidFloatPointer(velY, x*sX + y*sY)[0]; /*Find the cell back in time (keep a -10,10 radius)*/ float backX = timestep * fDataX + fx; float backY = timestep * fDataY + fy; int nBackX = (int)backX ; int nBackY = (int)backY ; float scaleX = backX - (float)(nBackX ); float scaleY = backY - (float)(nBackY ); /*Clamp as it's easier to parallelize given the scheduler*/ nBackX = fluidClamp(nBackX , 0,w-2); nBackY = fluidClamp(nBackY , 0,h-2); /*That was easy... now advect the velocity...*/ float *fVelDestX = fluidFloatPointer(velDestX, x*sX + y*sY); float *fVelDestY = fluidFloatPointer(velDestY, x*sX + y*sY); int offBackX = nBackX * sX; int offBackY = nBackY * sY; int offX2 = offBackX + sX; int offY2 = offBackY + sY; float bZZ_x = fluidFloatPointer(velX, offBackX + offBackY )[0]; float bOZ_x = fluidFloatPointer(velX, offX2 + offBackY )[0]; float bZO_x = fluidFloatPointer(velX, offBackX + offY2 )[0]; float bOO_x = fluidFloatPointer(velX, offX2 + offY2 )[0]; float bZZ_y = fluidFloatPointer(velY, offBackX + offBackY )[0]; float bOZ_y = fluidFloatPointer(velY, offX2 + offBackY )[0]; float bZO_y = fluidFloatPointer(velY, offBackX + offY2 )[0]; float bOO_y = fluidFloatPointer(velY, offX2 + offY2 )[0]; //Second velocities are here!!!! int i; for (i=0; i<9;i++) { fDataX = fluidLinearInterpolation(scaleX , scaleY , bZZ_x , bOZ_x , bZO_x , bOO_x ); fDataY = fluidLinearInterpolation(scaleX , scaleY , bZZ_y , bOZ_y , bZO_y , bOO_y ); //Compute using the next characteristic that we find (follow the curve!) backX += timestep * fDataX; backY += timestep * fDataY; nBackX = (int)backX; nBackY = (int)backY; scaleX = backX - (float)nBackX; scaleY = backY - (float)nBackY; nBackX = fluidClamp(nBackX, 0, w-2); nBackY = fluidClamp(nBackY, 0, h-2); offBackX = nBackX * sX; offBackY = nBackY * sY; offX2 = offBackX + sX; offY2 = offBackY + sY; bZZ_x = fluidFloatPointer(velX, offBackX + offBackY )[0]; bOZ_x = fluidFloatPointer(velX, offX2 + offBackY )[0]; bZO_x = fluidFloatPointer(velX, offBackX + offY2 )[0]; bOO_x = fluidFloatPointer(velX, offX2 + offY2 )[0]; bZZ_y = fluidFloatPointer(velY, offBackX + offBackY )[0]; bOZ_y = fluidFloatPointer(velY, offX2 + offBackY )[0]; bZO_y = fluidFloatPointer(velY, offBackX + offY2 )[0]; bOO_y = fluidFloatPointer(velY, offX2 + offY2 )[0]; //Second velocities are here!!!! fDataX = fluidLinearInterpolation(scaleX , scaleY , bZZ_x , bOZ_x , bZO_x , bOO_x ); fDataY = fluidLinearInterpolation(scaleX , scaleY , bZZ_y , bOZ_y , bZO_y , bOO_y ); } backX = fluidClamp(backX, 0, w-2); backY = fluidClamp(backY, 0, h-2); fluidFloatPointer(repDestX, x*sX + y*sY)[0] = backX; fluidFloatPointer(repDestY, x*sX + y*sY)[0] = backY; fVelDestX[0] = fDataX; fVelDestY[0] = fDataY; x++; fx++; } }
//Basic corrector part of predictor-corrector. void fluid_advection_mccormack_repos(fluid *in_f, const int y, pvt_fluidMode *mode) { struct mccormack_vel_repos *data = &mode->mccormack_vel_repos; int x; //Simple looping var int w = fieldWidth(data->srcVelX); //Width of the data int h = fieldHeight(data->srcVelX); int sY = fieldStrideY(data->srcVelY); x128f timestep = {data->timestep,data->timestep,data->timestep,data->timestep}; int sX = fieldStrideX(data->srcVelX); x128i vsX = {sX, sX, sX, sX}; x128i vsY = {sY, sY, sY, sY}; const float *srcVelX = fieldData(data->srcVelX); const float *srcVelY = fieldData(data->srcVelY); float *dstReposX = fieldData(data->dstReposX); float *dstReposY = fieldData(data->dstReposY); const int curxy = y*sY; const int w2 = w/4; //printf("%i %i\n", w2, w); x128f vMin = {-ADVECT_DIST, -ADVECT_DIST, -ADVECT_DIST, -ADVECT_DIST}; x128f vMax = {ADVECT_DIST, ADVECT_DIST, ADVECT_DIST, ADVECT_DIST}; const x128f *vSrcVelX = (x128f*)fluidFloatPointer(srcVelX, curxy); const x128f *vSrcVelY = (x128f*)fluidFloatPointer(srcVelY, curxy); // const x128f *vSrcVelXM = (x128f*)fluidFloatPointer(srcVelX, curxy-sY); // const x128f *vSrcVelYM = (x128f*)fluidFloatPointer(srcVelY, curxy-sY); // // const x128f *vSrcVelXP = (x128f*)fluidFloatPointer(srcVelX, curxy+sY); // const x128f *vSrcVelYP = (x128f*)fluidFloatPointer(srcVelY, curxy+sY); x128f *vDstReposX = (x128f*)fluidFloatPointer(dstReposX, curxy); x128f *vDstReposY = (x128f*)fluidFloatPointer(dstReposY, curxy); x128f vX = {0.0f, 1.0f, 2.0f, 3.0f}; const x128f vY = {y, y, y, y}; // const x128f vYM = {y-1, y-1, y-1, y-1}; // const x128f vYP = {y+1, y+1, y+1, y+1}; const x128f vHalf = {0.5f,0.5f,0.5f,0.5f}; const x128f v4 = {4.0f, 4.0f, 4.0f, 4.0f}; const x128f vN1 = {-1.0f, -1.0f, -1.0f, -1.0f}; const x128f vW = {w-1.01f,w-1.01f,w-1.01f,w-1.01f}; const x128f vH = {h-1.01f,h-1.01f,h-1.01f,h-1.01f}; u128i offBackX, offBackY, offBackX2, offBackY2, d1, d2, d3, d4; u128f scaleX, scaleY, fwdVelX, fwdVelY; float bZZ, bOZ, bZO, bOO; for (x=0; x<w2; x++) { //Basic... u128f fVelX, fVelY; fVelX.v = x_mul(timestep, vSrcVelX[x]); fVelY.v = x_mul(timestep, vSrcVelY[x]); // //Assume we can do this ina 9x9 window... // x128f x1 = x_sub(x_sub(vX, x_simd_one), fVelX.v); // x128f x2 = x_sub(vX, fVelX.v); // x128f x3 = x_sub(x_add(vX, x_simd_one), fVelX.v); // // x128f y1 = x_sub(vYM, fVelY.v); // x128f y2 = x_sub(vY, fVelY.v); // x128f y3 = x_sub(vYP, fVelY.v); // // x128f sum1 = x_add(x_add(x_add(x1,x2),x3),x_add(x_add(y1,y2),y3)); // // x1 = x_abs(x1); // x2 = x_abs(x2); // x3 = x_abs(x3); // // y1 = x_abs(y1); // y2 = x_abs(y2); // y3 = x_abs(y3); // // // x128f sum2 = x_add(x_add(x_add(x1,x2),x3),x_add(x_add(y1,y2),y3)); //Clamp the values... // x1 = x_sub(x_simd_one, x1); // x2 = x_sub(x_simd_one, x2); // x3 = x_sub(x_simd_one, x3); // // y1 = x_sub(x_simd_one, y1); // y2 = x_sub(x_simd_one, y2); // y3 = x_sub(x_simd_one, y3); //Advect forward in time... x128f fSrcVelX = x_clamp(fVelX.v, vMin, vMax); x128f fSrcVelY = x_clamp(fVelY.v, vMin, vMax); //Go forward x128f fwdX = x_clamp(x_add(vX, fSrcVelX), x_simd_zero, vW); x128f fwdY = x_clamp(x_add(vY, fSrcVelY), x_simd_zero, vH); // x128f fwdX = x_clamp(x_add(fSrcVelX, vX), x_simd_zero, vW); // x128f fwdY = x_clamp(x_add(fSrcVelY, vY), x_simd_zero, vH); //Back as integer x128i nBackX = x_ftoi(fwdX); x128i nBackY = x_ftoi(fwdY); // if (!x_all_lt(sum1, sum2)) // { // x1 = x_max(x_simd_zero, x1); // x2 = x_max(x_simd_zero, x2); // x3 = x_max(x_simd_zero, x3); // // y1 = x_max(x_simd_zero, y1); // y2 = x_max(x_simd_zero, y2); // y3 = x_max(x_simd_zero, y3); // // x128f slX, slY, srX, srY; // // x128f yMX, yMY, yPX, yPY; // // x128f X11, X31, X33, X13; // x128f Y11, Y31, Y33, Y13; // // if (y == 0) // { // yMX = x_simd_zero; // yMY = x_simd_zero; // // X31 = x_simd_zero; // X11 = x_simd_zero; // // Y31 = x_simd_zero; // Y11 = x_simd_zero; // } // else // { // yMX = vSrcVelXM[x]; // yMY = vSrcVelYM[x]; // // if (x == 0) // { // X11 = x_sld(x_simd_zero, vSrcVelXM[x], 4); // Y11 = x_sld(x_simd_zero, vSrcVelYM[x], 4); // } // else // { // X11 = x_sld(vSrcVelXM[x-1], vSrcVelXM[x], 4); // Y11 = x_sld(vSrcVelXM[x-1], vSrcVelYM[x], 4); // } // // if (x == w2-1) // { // X31 = x_sld(vSrcVelXM[x], x_simd_zero, 12); // Y31 = x_sld(vSrcVelYM[x], x_simd_zero, 12); // } // else // { // X31 = x_sld(vSrcVelXM[x], vSrcVelXM[x+1], 12); // Y31 = x_sld(vSrcVelXM[x], vSrcVelYM[x+1], 12); // } // } // // if (y == h-1) // { // yPX = x_simd_zero; // yPY = x_simd_zero; // // X33 = x_simd_zero; // X13 = x_simd_zero; // // Y33 = x_simd_zero; // Y13 = x_simd_zero; // } // else // { // yPX = vSrcVelXP[x]; // yPY = vSrcVelYP[x]; // // if (x == 0) // { // X13 = x_sld(x_simd_zero, vSrcVelXP[x], 4); // Y13 = x_sld(x_simd_zero, vSrcVelYP[x], 4); // } // else // { // X13 = x_sld(vSrcVelXP[x-1], vSrcVelXP[x], 4); // Y13 = x_sld(vSrcVelXP[x-1], vSrcVelYP[x], 4); // } // // if (x == w2-1) // { // X33 = x_sld(vSrcVelXP[x], x_simd_zero, 12); // Y33 = x_sld(vSrcVelYP[x], x_simd_zero, 12); // } // else // { // X33 = x_sld(vSrcVelXP[x], vSrcVelXP[x+1], 12); // Y33 = x_sld(vSrcVelXP[x], vSrcVelYP[x+1], 12); // } // } // // if (x == 0) // { // srX = x_sld(x_simd_zero, vSrcVelX[x], 4); // srY = x_sld(x_simd_zero, vSrcVelY[x], 4); // } // else // { // srX = x_sld(vSrcVelX[x-1], vSrcVelX[x], 4); // srY = x_sld(vSrcVelY[x-1], vSrcVelY[x], 4); // } // // if (x == w2 - 1) // { // slX = x_sld(vSrcVelX[x], x_simd_zero, 12); // slY = x_sld(vSrcVelX[x], x_simd_zero, 12); // } // else // { // slX = x_sld(vSrcVelX[x], vSrcVelX[x+1], 12); // slY = x_sld(vSrcVelX[x], vSrcVelX[x+1], 12); // } // // fwdVelX.v = x_mul(x_mul(x2,y2), vSrcVelX[x]); // fwdVelY.v = x_mul(x_mul(x2,y2), vSrcVelY[x]); // // // // fwdVelX.v = x_madd(x_mul(x1,y2), srX, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x1,y2), srY, fwdVelY.v); // // fwdVelX.v = x_madd(x_mul(x3,y2), srX, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x3,y2), srY, fwdVelY.v); // // // fwdVelX.v = x_madd(x_mul(x2,y1), yMX, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x2,y1), yMY, fwdVelY.v); // // fwdVelX.v = x_madd(x_mul(x2,y3), yPX, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x2,y3), yPY, fwdVelY.v); // // // // fwdVelX.v = x_madd(x_mul(x1,y1), X11, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x1,y1), Y11, fwdVelY.v); // // fwdVelX.v = x_madd(x_mul(x1,y3), X13, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x1,y3), Y13, fwdVelY.v); // // // fwdVelX.v = x_madd(x_mul(x3,y1), X31, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x3,y1), Y31, fwdVelY.v); // // fwdVelX.v = x_madd(x_mul(x3,y3), X33, fwdVelX.v); // fwdVelY.v = x_madd(x_mul(x3,y3), Y33, fwdVelY.v); // } // else // { //Compute scaling factor scaleX.v = x_sub(fwdX, x_itof(nBackX)); scaleY.v = x_sub(fwdY, x_itof(nBackY)); //Compute the addresses of the destinations... offBackX.v = x_imul(nBackX, vsX); offBackY.v = x_imul(nBackY, vsY); offBackX2.v = x_iadd(offBackX.v, vsX); offBackY2.v = x_iadd(offBackY.v, vsY); d1.v = x_iadd(offBackX.v, offBackY.v); d2.v = x_iadd(offBackX2.v, offBackY.v); d3.v = x_iadd(offBackX.v, offBackY2.v); d4.v = x_iadd(offBackX2.v, offBackY2.v); int i; for (i=0; i<4; i++) { bZZ = fluidFloatPointer(srcVelX, d1.i[i])[0]; bOZ = fluidFloatPointer(srcVelX, d2.i[i])[0]; bZO = fluidFloatPointer(srcVelX, d3.i[i])[0]; bOO = fluidFloatPointer(srcVelX, d4.i[i])[0]; fwdVelX.f[i] = fluidLinearInterpolation(scaleX.f[i], scaleY.f[i],bZZ, bOZ, bZO, bOO); bZZ = fluidFloatPointer(srcVelY, d1.i[i])[0]; bOZ = fluidFloatPointer(srcVelY, d2.i[i])[0]; bZO = fluidFloatPointer(srcVelY, d3.i[i])[0]; bOO = fluidFloatPointer(srcVelY, d4.i[i])[0]; fwdVelY.f[i] = fluidLinearInterpolation(scaleX.f[i], scaleY.f[i],bZZ, bOZ, bZO, bOO); } // } // // __builtin_prefetch(vSrcVelX+x+4); // __builtin_prefetch(vSrcVelXM+x+4); // __builtin_prefetch(vSrcVelXP+x+4); // // __builtin_prefetch(vSrcVelY+x+4); // __builtin_prefetch(vSrcVelYM+x+4); // __builtin_prefetch(vSrcVelYP+x+4); //Compute the velocity at that point... //This velocity (computed the other way) will give spatial error u128f errX, errY; //errX.v = x_sub(x_add(x_clamp(x_mul(x_mul(vN1, timestep), fwdVelX.v), vMin, vMax), fwdX), vX); //errY.v = x_sub(x_add(x_clamp(x_mul(x_mul(vN1, timestep), fwdVelY.v), vMin, vMax), fwdY), vY); errX.v = x_clamp(x_mul(timestep, fwdVelX.v), vMin, vMax); errY.v = x_clamp(x_mul(timestep, fwdVelY.v), vMin, vMax); //Most of the error is from velocity advection (so we assume) // This is a cheap way of computing error! x128f backX = x_add(x_clamp(x_madd(vHalf,errX.v,x_mul(fVelX.v,vN1)),vMin,vMax), vX); vDstReposX[x] = x_clamp(backX,x_simd_zero, vW); x128f backY = x_add(x_clamp(x_madd(vHalf,errY.v,x_mul(fVelY.v,vN1)),vMin,vMax), vY); vDstReposY[x] = x_clamp(backY,x_simd_zero, vH); vX = x_add(vX, v4); } }
//Simply generate positions for advection... void fluid_advection_stam_repos(fluid *in_f, const int y, pvt_fluidMode *mode) { struct mccormack_vel_repos *data = &mode->mccormack_vel_repos; int x; //Simple looping var int w = fieldWidth(data->srcVelX); //Width of the data int h = fieldHeight(data->srcVelX); int sY = fieldStrideY(data->srcVelY); x128f timestep = {-data->timestep,-data->timestep,-data->timestep,-data->timestep}; const float *srcVelX = fieldData(data->srcVelX); const float *srcVelY = fieldData(data->srcVelY); float *dstReposX = fieldData(data->dstReposX); float *dstReposY = fieldData(data->dstReposY); const int curxy = y*sY; const int w2 = w/4; //printf("%i %i\n", w2, w); x128f vMin = {-ADVECT_DIST, -ADVECT_DIST, -ADVECT_DIST, -ADVECT_DIST}; x128f vMax = {ADVECT_DIST, ADVECT_DIST, ADVECT_DIST, ADVECT_DIST}; const x128f *vSrcVelX = (x128f*)fluidFloatPointer(srcVelX, curxy); const x128f *vSrcVelY = (x128f*)fluidFloatPointer(srcVelY, curxy); x128f *vDstReposX = (x128f*)fluidFloatPointer(dstReposX, curxy); x128f *vDstReposY = (x128f*)fluidFloatPointer(dstReposY, curxy); x128f vX = {0.0f, 1.0f, 2.0f, 3.0f}; const x128f vY = {y, y, y, y}; const x128f v4 = {4.0f, 4.0f, 4.0f, 4.0f}; const x128f vW = {w-1.01f,w-1.01f,w-1.01f,w-1.01f}; const x128f vH = {h-1.01f,h-1.01f,h-1.01f,h-1.01f}; for (x=0; x<w2; x++) { //Basic... u128f fVelX, fVelY; fVelX.v = x_mul(timestep, vSrcVelX[x]); fVelY.v = x_mul(timestep, vSrcVelY[x]); //Advect forward in time... x128f fSrcVelX = x_clamp(fVelX.v, vMin, vMax); x128f fSrcVelY = x_clamp(fVelY.v, vMin, vMax); //Go forward x128f fwdX = x_clamp(x_add(fSrcVelX, vX), x_simd_zero, vW); x128f fwdY = x_clamp(x_add(fSrcVelY, vY), x_simd_zero, vH); vDstReposX[x] = fwdX; vDstReposY[x] = fwdY; vX = x_add(vX, v4); } }