//-- public methods ----- float clampf(float x, float lo, float hi) { return fminf(fmaxf(x, lo), hi); }
/// clamp each vector values Vec3 clamp(const Vec3& min_v, const Vec3& max_v) const { return Vec3( fminf( fmaxf(x, min_v.x), max_v.x), fminf( fmaxf(y, min_v.y), max_v.y), fminf( fmaxf(z, min_v.z), max_v.z)); }
void GUIComponent::Render(const CU::Vector2<int>& aWindowSize, const CU::Vector2<float>& aMousePos, bool aIsActiveState) { aMousePos; myIsActiveState = aIsActiveState; my3DClosestEnemyLength = 10000.f; myClosestEnemyLength = 100000.f; myClosestEnemy = nullptr; Prism::Engine::GetInstance()->DisableZBuffer(); float halfHeight = aWindowSize.y * 0.5f; float halfWidth = aWindowSize.x * 0.5f; CU::Vector2<float> steeringPos(halfWidth + mySteeringTargetPosition.x , -halfHeight - mySteeringTargetPosition.y); if (myConversation.size() > 1) { myBackgroundConversation->Render({ 15.f, -halfHeight * 1.2f + 20.f + 128.f - 150.f }); } myBackgroundMission->Render({ 15.f, -10.f }); CU::Vector2<float> crosshairPosition(CU::Math::Lerp<CU::Vector2<float>>({ halfWidth, -halfHeight } , { steeringPos.x, steeringPos.y }, 0.3f)); myReticle->Render({ halfWidth, -halfHeight }); mySteeringTarget->Render({ steeringPos.x, steeringPos.y }); myCrosshair->Render(crosshairPosition); myFirstSpawn = myWaypointSpawn; myFirstSpawnTimer = myWaypointSpawnTimer; if (myIsActiveState == true) { Prism::Engine::GetInstance()->PrintText(myConversation, { 35.f, -halfHeight * 1.2f + 20.f + 128.f - 200.f }, Prism::eTextType::RELEASE_TEXT); CalculateAndRender(myWaypointPosition, myModel2DToRender, myWaypointArrow, myWaypointMarker , aWindowSize, myWaypointActive); for (int i = 0; i < myEnemies.Size(); ++i) { myFirstSpawn = myEnemies[i]->GetGUIStartReneringMarker(); myFirstSpawnTimer = myEnemies[i]->GetGUIStartRenderingMarkerTimer(); if (myFirstSpawn == false && myFirstSpawnTimer != 0) myEnemies[i]->ActivateGUIStartRenderingMarker(); float lengthToEnemy = CU::Length(myEnemies[i]->myOrientation.GetPos() - myCamera->GetOrientation().GetPos()); if (lengthToEnemy < my3DClosestEnemyLength) { my3DClosestEnemyLength = lengthToEnemy; } if (myEnemies[i]->GetType() == eEntityType::STRUCTURE) { CalculateAndRender(myEnemies[i]->myOrientation.GetPos(), myModel2DToRender, myStructureArrow , myStructureMarker, aWindowSize, true, 1.f, false, "", myEnemies[i]); } else { if (lengthToEnemy < myMaxDistanceToEnemies) { CalculateAndRender(myEnemies[i]->myOrientation.GetPos(), myModel2DToRender, myEnemyArrow, myEnemyMarker, aWindowSize, true); } } CU::Vector2<float> enemyScreenPos = myClosestScreenPos; float lengthFromMouseToEnemy = CU::Length(enemyScreenPos - CU::Vector2<float>(steeringPos.x, steeringPos.y)); if (lengthFromMouseToEnemy < myClosestEnemyLength) { myClosestEnemy = myEnemies[i]; myClosestEnemyLength = lengthFromMouseToEnemy; } } if (myEnemies.Size() > 0 && my3DClosestEnemyLength < 1000) { if (myBattlePlayed == false) { Prism::Audio::AudioInterface::GetInstance()->PostEvent("Pause_BackgroundMusic", 0); Prism::Audio::AudioInterface::GetInstance()->PostEvent("Resume_BattleMusic", 0); } myBackgroundMusicPlayed = false; myBattlePlayed = true; } else { if (myBackgroundMusicPlayed == false) { Prism::Audio::AudioInterface::GetInstance()->PostEvent("Resume_BackgroundMusic", 0); Prism::Audio::AudioInterface::GetInstance()->PostEvent("Pause_BattleMusic", 0); } myBattlePlayed = false; myBackgroundMusicPlayed = true; } for (int i = 0; i < myPowerUps.Size(); ++i) { myFirstSpawn = myPowerUps[i]->GetGUIStartReneringMarker(); myFirstSpawnTimer = myPowerUps[i]->GetGUIStartRenderingMarkerTimer(); if (myFirstSpawn == false && myFirstSpawnTimer != 0) myPowerUps[i]->ActivateGUIStartRenderingMarker(); CalculateAndRender(myPowerUps[i]->myOrientation.GetPos(), myModel2DToRender, myPowerUpArrow, myPowerUpMarker , aWindowSize, true, true, 1.f, myPowerUps[i]->GetComponent<PowerUpComponent>()->GetInGameName()); } if (myEnemiesTarget != nullptr) { CalculateAndRender(myEnemiesTarget->myOrientation.GetPos(), myModel2DToRender, myDefendArrow, myDefendMarker, aWindowSize, true); } float percentageToReady = 1.f; if (myHasRocketLauncher == true) { Prism::Engine::GetInstance()->PrintText("RL", { halfWidth + 550.f, -halfHeight + 15.f }, Prism::eTextType::RELEASE_TEXT); percentageToReady = *myRocketCurrentTime / *myRocketMaxTime; if (percentageToReady >= 1.f) { if (myPlayedMissilesReady == false) { myEntity.SendNote<SoundNote>(SoundNote(eSoundNoteType::PLAY, "Play_MissilesReady")); myPlayedMissilesReady = true; } Prism::Engine::GetInstance()->PrintText("RDY", { halfWidth + 550.f, -halfHeight - 20.f }, Prism::eTextType::RELEASE_TEXT); } else { myPlayedMissilesReady = false; } } if (myHasHomingWeapon == true) { if (myClosestEnemy != nullptr) { myHomingTarget->Rotate(myDeltaTime); CalculateAndRender(myClosestEnemy->myOrientation.GetPos(), nullptr, nullptr, nullptr, aWindowSize, true, 1.f); } myEntity.GetComponent<ShootingComponent>()->SetHomingTarget(myClosestEnemy); } if (myHasRocketLauncher == true && percentageToReady >= 1.f) { if (myClosestEnemy != nullptr) { myHomingTarget->Rotate(myDeltaTime); if (myClosestEnemy->GetName() != "E_enemy_turret_noShoot") { CalculateAndRender(myClosestEnemy->myOrientation.GetPos(), myModel2DToRender, myHomingTarget, myHomingTarget, aWindowSize, true, percentageToReady); } } myEntity.GetComponent<ShootingComponent>()->SetHomingTarget(myClosestEnemy); } } myEnemies.RemoveAll(); myPowerUps.RemoveAll(); myGUIBars[0]->Render(*myCamera); if (myCurrentShield <= 101.f) { myGUIBars[1]->Render(*myCamera); } else { myGUIBars[2]->Render(*myCamera); } if (myHitMarkerTimer >= 0.f) { myCurrentHitmarker->Render(crosshairPosition); } if (myDamageIndicatorTimer >= 0.f) { float alpha = fminf(1.f, myDamageIndicatorTimer); if (myCurrentShield <= 0) { myDamageIndicatorHealth->Render({ halfWidth, -halfHeight }, { 1.f, 1.f }, { 1.f, 1.f, 1.f, alpha }); } else { //myDamageIndicatorShield->Render({ halfWidth, -halfHeight }, { 1.f, 1.f }, { 1.f, 1.f, 1.f, alpha }); } } if (myIsActiveState == true) { if (myClosestEnemy != nullptr) { CalculateAndRender(myClosestEnemy->myOrientation.GetPos(), nullptr, nullptr, nullptr, aWindowSize , true, 1.f, false, "", myClosestEnemy); if (myShouldRenderHP == true && myClosestEnemy->GetName() != "E_enemy_turret_noShoot") { float alpha = CU::Length(steeringPos - myClosestScreenPos); alpha = 1.f - (alpha / CIRCLERADIUS); Prism::Engine::GetInstance()->PrintText("Hp: " + std::to_string(myClosestEnemy->GetComponent<HealthComponent>()->GetHealth()) , { myClosestScreenPos.x - 30.f, myClosestScreenPos.y + 40.f }, Prism::eTextType::RELEASE_TEXT , 0.5f, { 1.f, 1.f, 1.f, alpha }); } } myPowerUpSlots[ePowerUpType::EMP]->Render(aWindowSize, myDeltaTime); myPowerUpSlots[ePowerUpType::FIRERATEBOOST]->Render(aWindowSize, myDeltaTime); myPowerUpSlots[ePowerUpType::HOMING]->Render(aWindowSize, myDeltaTime); myPowerUpSlots[ePowerUpType::INVULNERABLITY]->Render(aWindowSize, myDeltaTime); if (myShowMessage == true) { Prism::Engine::GetInstance()->PrintText(myMessage, { halfWidth - 150.f, -halfHeight + 200.f }, Prism::eTextType::RELEASE_TEXT , 1.f, { 1.f, 1.f, 1.f, myMessageAlpha }); } if (myShowTutorialMessage == true) { Prism::Engine::GetInstance()->PrintText(myTutorialMessage, { halfWidth - 270.f, -halfHeight + 220.f }, Prism::eTextType::RELEASE_TEXT , 1.f, { 1.f, 1.f, 1.f, myMessageAlpha }); } if (myHasMachinegun == true) { Prism::Engine::GetInstance()->PrintText("MG", { halfWidth + 420.f, -halfHeight + 15.f }, Prism::eTextType::RELEASE_TEXT); if (*myCurrentWeapon == 0) { Prism::Engine::GetInstance()->PrintText("RDY", { halfWidth + 420.f, -halfHeight - 20.f }, Prism::eTextType::RELEASE_TEXT); } } if (myHasShotgun == true) { Prism::Engine::GetInstance()->PrintText("SG", { halfWidth + 480.f, -halfHeight + 15.f }, Prism::eTextType::RELEASE_TEXT); if (*myCurrentWeapon == 1) { Prism::Engine::GetInstance()->PrintText("RDY", { halfWidth + 480.f, -halfHeight - 20.f }, Prism::eTextType::RELEASE_TEXT); } } float speed = myEntity.GetComponent<PhysicsComponent>()->GetSpeed(); speed += 0.5f; int displaySpeed = int(speed); if (speed > 99.5f && speed < 102.f) { displaySpeed = 100; } if (speed > 250.f) { displaySpeed = 250; } Prism::Engine::GetInstance()->PrintText(displaySpeed , { halfWidth - 360.f, -halfHeight - 270.f }, Prism::eTextType::RELEASE_TEXT); if (myHasEMP == true) { Prism::Engine::GetInstance()->PrintText("EMP ready. Press [Space] to release." , { halfWidth - 240.f, -halfHeight - 270.f }, Prism::eTextType::RELEASE_TEXT, 1.f, { 1.f, 1.f, 1.f, myEMPMessageAlpha }); } } Prism::Engine::GetInstance()->EnableZBuffer(); }
static int dt_group_get_mask_roi(dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, const dt_iop_roi_t *roi, float *buffer) { double start2 = dt_get_wtime(); const guint nb = g_list_length(form->points); if(nb == 0) return 0; int nb_ok = 0; const int width = roi->width; const int height = roi->height; // we need to allocate a temporary buffer for intermediate creation of individual shapes float *bufs = dt_alloc_align(64, (size_t)width * height * sizeof(float)); if(bufs == NULL) return 0; // empty the output buffer memset(buffer, 0, (size_t)width * height * sizeof(float)); // and we get all masks GList *fpts = g_list_first(form->points); while(fpts) { dt_masks_point_group_t *fpt = (dt_masks_point_group_t *)fpts->data; dt_masks_form_t *sel = dt_masks_get_from_id(module->dev, fpt->formid); if(sel) { const int ok = dt_masks_get_mask_roi(module, piece, sel, roi, bufs); const float op = fpt->opacity; const int state = fpt->state; if(ok) { // first see if we need to invert this shape if(state & DT_MASKS_STATE_INVERSE) { #ifdef _OPENMP #if !defined(__SUNOS__) && !defined(__NetBSD__) #pragma omp parallel for default(none) shared(bufs) #else #pragma omp parallel for shared(bufs) #endif #endif for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) { size_t index = (size_t)y * width + x; bufs[index] = 1.0f - bufs[index]; } } if(state & DT_MASKS_STATE_UNION) { #ifdef _OPENMP #if !defined(__SUNOS__) && !defined(__NetBSD__) #pragma omp parallel for default(none) shared(bufs, buffer) #else #pragma omp parallel for shared(bufs, buffer) #endif #endif for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) { size_t index = (size_t)y * width + x; buffer[index] = fmaxf(buffer[index], bufs[index] * op); } } else if(state & DT_MASKS_STATE_INTERSECTION) { #ifdef _OPENMP #if !defined(__SUNOS__) && !defined(__NetBSD__) #pragma omp parallel for default(none) shared(bufs, buffer) #else #pragma omp parallel for shared(bufs, buffer) #endif #endif for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) { size_t index = (size_t)y * width + x; float b1 = buffer[index]; float b2 = b2 = bufs[index]; // FIXME: is this line correct? what it supposed to be doing? if(b1 > 0.0f && b2 > 0.0f) buffer[index] = fminf(b1, b2 * op); else buffer[index] = 0.0f; } } else if(state & DT_MASKS_STATE_DIFFERENCE) { #ifdef _OPENMP #if !defined(__SUNOS__) && !defined(__NetBSD__) #pragma omp parallel for default(none) shared(bufs, buffer) #else #pragma omp parallel for shared(bufs, buffer) #endif #endif for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) { size_t index = (size_t)y * width + x; float b1 = buffer[index]; float b2 = bufs[index] * op; if(b1 > 0.0f && b2 > 0.0f) buffer[index] = b1 * (1.0f - b2); } } else if(state & DT_MASKS_STATE_EXCLUSION) { #ifdef _OPENMP #if !defined(__SUNOS__) && !defined(__NetBSD__) #pragma omp parallel for default(none) shared(bufs, buffer) #else #pragma omp parallel for shared(bufs, buffer) #endif #endif for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) { size_t index = (size_t)y * width + x; float b1 = buffer[index]; float b2 = bufs[index] * op; if(b1 > 0.0f && b2 > 0.0f) buffer[index] = fmaxf((1.0f - b1) * b2, b1 * (1.0f - b2)); else buffer[index] = fmaxf(b1, b2); } } else // if we are here, this mean that we just have to copy the shape and null other parts { #ifdef _OPENMP #if !defined(__SUNOS__) && !defined(__NetBSD__) #pragma omp parallel for default(none) shared(bufs, buffer) #else #pragma omp parallel for shared(bufs, buffer) #endif #endif for(int y = 0; y < height; y++) for(int x = 0; x < width; x++) { size_t index = (size_t)y * width + x; buffer[index] = bufs[index] * op; } } if(darktable.unmuted & DT_DEBUG_PERF) dt_print(DT_DEBUG_MASKS, "[masks %d] combine took %0.04f sec\n", nb_ok, dt_get_wtime() - start2); start2 = dt_get_wtime(); nb_ok++; } } fpts = g_list_next(fpts); } // and we free the intermediate buffer dt_free_align(bufs); return (nb_ok != 0); }
/// value of the min coordinate float get_min() const { return fminf(fminf(x,y),z); }
unsigned MultirotorMixer::mix(float *outputs, unsigned space, uint16_t *status_reg) { /* Summary of mixing strategy: 1) mix roll, pitch and thrust without yaw. 2) if some outputs violate range [0,1] then try to shift all outputs to minimize violation -> increase or decrease total thrust (boost). The total increase or decrease of thrust is limited (max_thrust_diff). If after the shift some outputs still violate the bounds then scale roll & pitch. In case there is violation at the lower and upper bound then try to shift such that violation is equal on both sides. 3) mix in yaw and scale if it leads to limit violation. 4) scale all outputs to range [idle_speed,1] */ float roll = constrain(get_control(0, 0) * _roll_scale, -1.0f, 1.0f); float pitch = constrain(get_control(0, 1) * _pitch_scale, -1.0f, 1.0f); float yaw = constrain(get_control(0, 2) * _yaw_scale, -1.0f, 1.0f); float thrust = constrain(get_control(0, 3), 0.0f, 1.0f); float min_out = 1.0f; float max_out = 0.0f; // clean out class variable used to capture saturation _saturation_status.value = 0; // thrust boost parameters float thrust_increase_factor = 1.5f; float thrust_decrease_factor = 0.6f; /* perform initial mix pass yielding unbounded outputs, ignore yaw */ for (unsigned i = 0; i < _rotor_count; i++) { float out = roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale + thrust; out *= _rotors[i].out_scale; /* calculate min and max output values */ if (out < min_out) { min_out = out; } if (out > max_out) { max_out = out; } outputs[i] = out; } float boost = 0.0f; // value added to demanded thrust (can also be negative) float roll_pitch_scale = 1.0f; // scale for demanded roll and pitch if (min_out < 0.0f && max_out < 1.0f && -min_out <= 1.0f - max_out) { float max_thrust_diff = thrust * thrust_increase_factor - thrust; if (max_thrust_diff >= -min_out) { boost = -min_out; } else { boost = max_thrust_diff; roll_pitch_scale = (thrust + boost) / (thrust - min_out); } } else if (max_out > 1.0f && min_out > 0.0f && min_out >= max_out - 1.0f) { float max_thrust_diff = thrust - thrust_decrease_factor * thrust; if (max_thrust_diff >= max_out - 1.0f) { boost = -(max_out - 1.0f); } else { boost = -max_thrust_diff; roll_pitch_scale = (1 - (thrust + boost)) / (max_out - thrust); } } else if (min_out < 0.0f && max_out < 1.0f && -min_out > 1.0f - max_out) { float max_thrust_diff = thrust * thrust_increase_factor - thrust; boost = constrain(-min_out - (1.0f - max_out) / 2.0f, 0.0f, max_thrust_diff); roll_pitch_scale = (thrust + boost) / (thrust - min_out); } else if (max_out > 1.0f && min_out > 0.0f && min_out < max_out - 1.0f) { float max_thrust_diff = thrust - thrust_decrease_factor * thrust; boost = constrain(-(max_out - 1.0f - min_out) / 2.0f, -max_thrust_diff, 0.0f); roll_pitch_scale = (1 - (thrust + boost)) / (max_out - thrust); } else if (min_out < 0.0f && max_out > 1.0f) { boost = constrain(-(max_out - 1.0f + min_out) / 2.0f, thrust_decrease_factor * thrust - thrust, thrust_increase_factor * thrust - thrust); roll_pitch_scale = (thrust + boost) / (thrust - min_out); } // capture saturation if (min_out < 0.0f) { _saturation_status.flags.motor_neg = true; } if (max_out > 1.0f) { _saturation_status.flags.motor_pos = true; } // mix again but now with thrust boost, scale roll/pitch and also add yaw for (unsigned i = 0; i < _rotor_count; i++) { float out = (roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale) * roll_pitch_scale + yaw * _rotors[i].yaw_scale + thrust + boost; out *= _rotors[i].out_scale; // scale yaw if it violates limits. inform about yaw limit reached if (out < 0.0f) { if (fabsf(_rotors[i].yaw_scale) <= FLT_EPSILON) { yaw = 0.0f; } else { yaw = -((roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale) * roll_pitch_scale + thrust + boost) / _rotors[i].yaw_scale; } } else if (out > 1.0f) { // allow to reduce thrust to get some yaw response float thrust_reduction = fminf(0.15f, out - 1.0f); thrust -= thrust_reduction; if (fabsf(_rotors[i].yaw_scale) <= FLT_EPSILON) { yaw = 0.0f; } else { yaw = (1.0f - ((roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale) * roll_pitch_scale + thrust + boost)) / _rotors[i].yaw_scale; } } } /* add yaw and scale outputs to range idle_speed...1 */ for (unsigned i = 0; i < _rotor_count; i++) { outputs[i] = (roll * _rotors[i].roll_scale + pitch * _rotors[i].pitch_scale) * roll_pitch_scale + yaw * _rotors[i].yaw_scale + thrust + boost; /* implement simple model for static relationship between applied motor pwm and motor thrust model: thrust = (1 - _thrust_factor) * PWM + _thrust_factor * PWM^2 this model assumes normalized input / output in the range [0,1] so this is the right place to do it as at this stage the outputs are in that range. */ if (_thrust_factor > 0.0f) { outputs[i] = -(1.0f - _thrust_factor) / (2.0f * _thrust_factor) + sqrtf((1.0f - _thrust_factor) * (1.0f - _thrust_factor) / (4.0f * _thrust_factor * _thrust_factor) + (outputs[i] < 0.0f ? 0.0f : outputs[i] / _thrust_factor)); } outputs[i] = constrain(_idle_speed + (outputs[i] * (1.0f - _idle_speed)), _idle_speed, 1.0f); } /* slew rate limiting and saturation checking */ for (unsigned i = 0; i < _rotor_count; i++) { bool clipping_high = false; bool clipping_low = false; // check for saturation against static limits if (outputs[i] > 0.99f) { clipping_high = true; } else if (outputs[i] < _idle_speed + 0.01f) { clipping_low = true; } // check for saturation against slew rate limits if (_delta_out_max > 0.0f) { float delta_out = outputs[i] - _outputs_prev[i]; if (delta_out > _delta_out_max) { outputs[i] = _outputs_prev[i] + _delta_out_max; clipping_high = true; } else if (delta_out < -_delta_out_max) { outputs[i] = _outputs_prev[i] - _delta_out_max; clipping_low = true; } } _outputs_prev[i] = outputs[i]; // update the saturation status report update_saturation_status(i, clipping_high, clipping_low); } // this will force the caller of the mixer to always supply new slew rate values, otherwise no slew rate limiting will happen _delta_out_max = 0.0f; // Notify saturation status if (status_reg != NULL) { (*status_reg) = _saturation_status.value; } return _rotor_count; }
void modify_roi_in(struct dt_iop_module_t *self, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, dt_iop_roi_t *roi_in) { *roi_in = *roi_out; int roir = roi_in->width+roi_in->x; int roib = roi_in->height+roi_in->y; int roix = roi_in->x; int roiy = roi_in->y; //dt_iop_spots_params_t *d = (dt_iop_spots_params_t *)piece->data; dt_develop_blend_params_t *bp = self->blend_params; // We iterate through all spots or polygons dt_masks_form_t *grp = dt_masks_get_from_id(darktable.develop,bp->mask_id); if (grp && (grp->type & DT_MASKS_GROUP)) { GList *forms = g_list_first(grp->points); while(forms) { dt_masks_point_group_t *grpt = (dt_masks_point_group_t *)forms->data; //we get the spot dt_masks_form_t *form = dt_masks_get_from_id(self->dev,grpt->formid); if (form) { //we get the area for the form int fl,ft,fw,fh; if (!dt_masks_get_area(self,piece,form,&fw,&fh,&fl,&ft)) { forms = g_list_next(forms); continue; } //if the form is outside the roi, we just skip it fw *= roi_in->scale, fh *= roi_in->scale, fl *= roi_in->scale, ft *= roi_in->scale; if (ft>=roi_out->y+roi_out->height || ft+fh<=roi_out->y || fl>=roi_out->x+roi_out->width || fl+fw<=roi_out->x) { forms = g_list_next(forms); continue; } //we get the area for the source if (!dt_masks_get_source_area(self,piece,form,&fw,&fh,&fl,&ft)) { forms = g_list_next(forms); continue; } fw *= roi_in->scale, fh *= roi_in->scale, fl *= roi_in->scale, ft *= roi_in->scale; //we enlarge the roi if needed roiy = fminf(ft,roiy); roix = fminf(fl,roix); roir = fmaxf(fl+fw,roir); roib = fmaxf(ft+fh,roib); } forms = g_list_next(forms); } } //now we set the values roi_in->x = CLAMP(roix, 0, piece->pipe->iwidth*roi_in->scale-1); roi_in->y = CLAMP(roiy, 0, piece->pipe->iheight*roi_in->scale-1); roi_in->width = CLAMP(roir-roi_in->x, 1, piece->pipe->iwidth*roi_in->scale-roi_in->x); roi_in->height = CLAMP(roib-roi_in->y, 1, piece->pipe->iheight*roi_in->scale-roi_in->y); }
void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out) { const uint32_t filters = piece->pipe->dsc.filters; dt_iop_highlights_data_t *data = (dt_iop_highlights_data_t *)piece->data; const float clip = data->clip * fminf(piece->pipe->dsc.processed_maximum[0], fminf(piece->pipe->dsc.processed_maximum[1], piece->pipe->dsc.processed_maximum[2])); // const int ch = piece->colors; if(!filters) { process_clip(piece, ivoid, ovoid, roi_in, roi_out, clip); for(int k=0;k<3;k++) piece->pipe->dsc.processed_maximum[k] = fminf(piece->pipe->dsc.processed_maximum[0], fminf(piece->pipe->dsc.processed_maximum[1], piece->pipe->dsc.processed_maximum[2])); return; } switch(data->mode) { case DT_IOP_HIGHLIGHTS_INPAINT: // a1ex's (magiclantern) idea of color inpainting: { const float clips[4] = { 0.987 * data->clip * piece->pipe->dsc.processed_maximum[0], 0.987 * data->clip * piece->pipe->dsc.processed_maximum[1], 0.987 * data->clip * piece->pipe->dsc.processed_maximum[2], clip }; if(filters == 9u) { const uint8_t(*const xtrans)[6] = (const uint8_t(*const)[6])piece->pipe->dsc.xtrans; #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) default(none) #endif for(int j = 0; j < roi_out->height; j++) { interpolate_color_xtrans(ivoid, ovoid, roi_in, roi_out, 0, 1, j, clips, xtrans, 0); interpolate_color_xtrans(ivoid, ovoid, roi_in, roi_out, 0, -1, j, clips, xtrans, 1); } #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) default(none) #endif for(int i = 0; i < roi_out->width; i++) { interpolate_color_xtrans(ivoid, ovoid, roi_in, roi_out, 1, 1, i, clips, xtrans, 2); interpolate_color_xtrans(ivoid, ovoid, roi_in, roi_out, 1, -1, i, clips, xtrans, 3); } } else { #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) default(none) shared(data, piece) #endif for(int j = 0; j < roi_out->height; j++) { interpolate_color(ivoid, ovoid, roi_out, 0, 1, j, clips, filters, 0); interpolate_color(ivoid, ovoid, roi_out, 0, -1, j, clips, filters, 1); } // up/down directions #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) default(none) shared(data, piece) #endif for(int i = 0; i < roi_out->width; i++) { interpolate_color(ivoid, ovoid, roi_out, 1, 1, i, clips, filters, 2); interpolate_color(ivoid, ovoid, roi_out, 1, -1, i, clips, filters, 3); } } break; } case DT_IOP_HIGHLIGHTS_LCH: if(filters == 9u) process_lch_xtrans(self, piece, ivoid, ovoid, roi_in, roi_out, clip); else process_lch_bayer(self, piece, ivoid, ovoid, roi_in, roi_out, clip); break; default: case DT_IOP_HIGHLIGHTS_CLIP: process_clip(piece, ivoid, ovoid, roi_in, roi_out, clip); break; } // update processed maximum const float m = fmaxf(fmaxf(piece->pipe->dsc.processed_maximum[0], piece->pipe->dsc.processed_maximum[1]), piece->pipe->dsc.processed_maximum[2]); for(int k = 0; k < 3; k++) piece->pipe->dsc.processed_maximum[k] = m; if(piece->pipe->mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height); }
static gboolean dt_iop_levels_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_levels_gui_data_t *c = (dt_iop_levels_gui_data_t *)self->gui_data; dt_iop_levels_params_t *p = (dt_iop_levels_params_t *)self->params; const int inset = DT_GUI_CURVE_EDITOR_INSET; int height = widget->allocation.height - 2*inset, width = widget->allocation.width - 2*inset; if(!c->dragging) { c->mouse_x = CLAMP(event->x - inset, 0, width); c->drag_start_percentage = (p->levels[1] - p->levels[0]) / (p->levels[2] - p->levels[0]); } c->mouse_y = CLAMP(event->y - inset, 0, height); if(c->dragging) { if(c->handle_move >= 0 && c->handle_move < 3) { const float mx = (CLAMP(event->x - inset, 0, width)) / (float)width; float min_x = 0; float max_x = 1; // Determining the minimum and maximum bounds for the drag handles switch(c->handle_move) { case 0: max_x = fminf(p->levels[2] - (0.05 / c->drag_start_percentage), 1); max_x = fminf((p->levels[2] * (1 - c->drag_start_percentage) - 0.05) / (1 - c->drag_start_percentage), max_x); break; case 1: min_x = p->levels[0] + 0.05; max_x = p->levels[2] - 0.05; break; case 2: min_x = fmaxf((0.05 / c->drag_start_percentage) + p->levels[0], 0); min_x = fmaxf((p->levels[0] * (1 - c->drag_start_percentage) + 0.05) / (1 - c->drag_start_percentage), min_x); break; } p->levels[c->handle_move] = fminf(max_x, fmaxf(min_x, mx)); if(c->handle_move != 1) p->levels[1] = p->levels[0] + (c->drag_start_percentage * (p->levels[2] - p->levels[0])); } dt_dev_add_history_item(darktable.develop, self, TRUE); } else { c->handle_move = 0; const float mx = CLAMP(event->x - inset, 0, width)/(float)width; float dist = fabsf(p->levels[0] - mx); for(int k=1; k<3; k++) { float d2 = fabsf(p->levels[k] - mx); if(d2 < dist) { c->handle_move = k; dist = d2; } } } gtk_widget_queue_draw(widget); gint x, y; gdk_window_get_pointer(event->window, &x, &y, NULL); return TRUE; }
int process_cl(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out) { dt_iop_highlights_data_t *d = (dt_iop_highlights_data_t *)piece->data; dt_iop_highlights_global_data_t *gd = (dt_iop_highlights_global_data_t *)self->data; cl_int err = -999; cl_mem dev_xtrans = NULL; const int devid = piece->pipe->devid; const int width = roi_in->width; const int height = roi_in->height; const float clip = d->clip * fminf(piece->pipe->dsc.processed_maximum[0], fminf(piece->pipe->dsc.processed_maximum[1], piece->pipe->dsc.processed_maximum[2])); const uint32_t filters = piece->pipe->dsc.filters; if(!filters) { // non-raw images use dedicated kernel which just clips size_t sizes[] = { ROUNDUPWD(width), ROUNDUPHT(height), 1 }; dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_4f_clip, 0, sizeof(cl_mem), (void *)&dev_in); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_4f_clip, 1, sizeof(cl_mem), (void *)&dev_out); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_4f_clip, 2, sizeof(int), (void *)&width); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_4f_clip, 3, sizeof(int), (void *)&height); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_4f_clip, 4, sizeof(int), (void *)&d->mode); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_4f_clip, 5, sizeof(float), (void *)&clip); err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_highlights_4f_clip, sizes); if(err != CL_SUCCESS) goto error; } else if(d->mode == DT_IOP_HIGHLIGHTS_CLIP) { // raw images with clip mode (both bayer and xtrans) size_t sizes[] = { ROUNDUPWD(width), ROUNDUPHT(height), 1 }; dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 0, sizeof(cl_mem), (void *)&dev_in); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 1, sizeof(cl_mem), (void *)&dev_out); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 2, sizeof(int), (void *)&width); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 3, sizeof(int), (void *)&height); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 4, sizeof(float), (void *)&clip); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 5, sizeof(int), (void *)&roi_out->x); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 6, sizeof(int), (void *)&roi_out->y); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_clip, 7, sizeof(int), (void *)&filters); err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_highlights_1f_clip, sizes); if(err != CL_SUCCESS) goto error; } else if(d->mode == DT_IOP_HIGHLIGHTS_LCH && filters != 9u) { // bayer sensor raws with LCH mode size_t sizes[] = { ROUNDUPWD(width), ROUNDUPHT(height), 1 }; dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 0, sizeof(cl_mem), (void *)&dev_in); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 1, sizeof(cl_mem), (void *)&dev_out); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 2, sizeof(int), (void *)&width); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 3, sizeof(int), (void *)&height); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 4, sizeof(float), (void *)&clip); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 5, sizeof(int), (void *)&roi_out->x); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 6, sizeof(int), (void *)&roi_out->y); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_bayer, 7, sizeof(int), (void *)&filters); err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_highlights_1f_lch_bayer, sizes); if(err != CL_SUCCESS) goto error; } else if(d->mode == DT_IOP_HIGHLIGHTS_LCH && filters == 9u) { // xtrans sensor raws with LCH mode int blocksizex, blocksizey; dt_opencl_local_buffer_t locopt = (dt_opencl_local_buffer_t){ .xoffset = 2 * 2, .xfactor = 1, .yoffset = 2 * 2, .yfactor = 1, .cellsize = sizeof(float), .overhead = 0, .sizex = 1 << 8, .sizey = 1 << 8 }; if(dt_opencl_local_buffer_opt(devid, gd->kernel_highlights_1f_lch_xtrans, &locopt)) { blocksizex = locopt.sizex; blocksizey = locopt.sizey; } else blocksizex = blocksizey = 1; dev_xtrans = dt_opencl_copy_host_to_device_constant(devid, sizeof(piece->pipe->dsc.xtrans), piece->pipe->dsc.xtrans); if(dev_xtrans == NULL) goto error; size_t sizes[] = { ROUNDUP(width, blocksizex), ROUNDUP(height, blocksizey), 1 }; size_t local[] = { blocksizex, blocksizey, 1 }; dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 0, sizeof(cl_mem), (void *)&dev_in); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 1, sizeof(cl_mem), (void *)&dev_out); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 2, sizeof(int), (void *)&width); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 3, sizeof(int), (void *)&height); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 4, sizeof(float), (void *)&clip); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 5, sizeof(int), (void *)&roi_out->x); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 6, sizeof(int), (void *)&roi_out->y); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 7, sizeof(cl_mem), (void *)&dev_xtrans); dt_opencl_set_kernel_arg(devid, gd->kernel_highlights_1f_lch_xtrans, 8, (blocksizex + 4) * (blocksizey + 4) * sizeof(float), NULL); err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_highlights_1f_lch_xtrans, sizes, local); if(err != CL_SUCCESS) goto error; } // update processed maximum const float m = fmaxf(fmaxf(piece->pipe->dsc.processed_maximum[0], piece->pipe->dsc.processed_maximum[1]), piece->pipe->dsc.processed_maximum[2]); for(int k = 0; k < 3; k++) piece->pipe->dsc.processed_maximum[k] = m; dt_opencl_release_mem_object(dev_xtrans); return TRUE; error: dt_opencl_release_mem_object(dev_xtrans); dt_print(DT_DEBUG_OPENCL, "[opencl_highlights] couldn't enqueue kernel! %d\n", err); return FALSE; }
static inline void interpolate_color_xtrans(const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, int dim, int dir, int other, const float *const clip, const uint8_t (*const xtrans)[6], const int pass) { // In Bayer each row/col has only green/red or green/blue // transitions, hence can reconstruct color by single ratio per // row. In x-trans there can be transitions between arbitrary colors // in a row/col (and 2x2 green blocks which provide no color // transition information). Hence calculate multiple color ratios // for each row/col. // Lookup for color ratios, e.g. red -> blue is roff[0][2] and blue // -> red is roff[2][0]. Returned value is an index into ratios. If // negative, then need to invert the ratio. Identity color // transitions aren't used. const int roff[3][3] = {{ 0, -1, -2}, { 1, 0, -3}, { 2, 3, 0}}; // record ratios of color transitions 0:unused, 1:RG, 2:RB, and 3:GB float ratios[4] = {1.0f, 1.0f, 1.0f, 1.0f}; // passes are 0:+x, 1:-x, 2:+y, 3:-y // dims are 0:traverse a row, 1:traverse a column // dir is 1:left to right, -1: right to left int i = (dim == 0) ? 0 : other; int j = (dim == 0) ? other : 0; const ssize_t offs = (dim ? roi_out->width : 1) * ((dir < 0) ? -1 : 1); const ssize_t offl = offs - (dim ? 1 : roi_out->width); const ssize_t offr = offs + (dim ? 1 : roi_out->width); int beg, end; if(dir == 1) { beg = 0; end = (dim == 0) ? roi_out->width : roi_out->height; } else { beg = ((dim == 0) ? roi_out->width : roi_out->height) - 1; end = -1; } float *in, *out; if(dim == 1) { out = (float *)ovoid + (size_t)i + (size_t)beg * roi_out->width; in = (float *)ivoid + (size_t)i + (size_t)beg * roi_in->width; } else { out = (float *)ovoid + (size_t)beg + (size_t)j * roi_out->width; in = (float *)ivoid + (size_t)beg + (size_t)j * roi_in->width; } for(int k = beg; k != end; k += dir) { if(dim == 1) j = k; else i = k; const uint8_t f0 = FCxtrans(j, i, roi_in, xtrans); const uint8_t f1 = FCxtrans(dim ? (j + dir) : j, dim ? i : (i + dir), roi_in, xtrans); const uint8_t fl = FCxtrans(dim ? (j + dir) : (j - 1), dim ? (i - 1) : (i + dir), roi_in, xtrans); const uint8_t fr = FCxtrans(dim ? (j + dir) : (j + 1), dim ? (i + 1) : (i + dir), roi_in, xtrans); const float clip0 = clip[f0]; const float clip1 = clip[f1]; const float clipl = clip[fl]; const float clipr = clip[fr]; const float clip_max = fmaxf(fmaxf(clip[0], clip[1]), clip[2]); if(i == 0 || i == roi_out->width - 1 || j == 0 || j == roi_out->height - 1) { if(pass == 3) out[0] = fminf(clip_max, in[0]); } else { // ratio to next pixel if this & next are unclamped and not in // 2x2 green block if ((f0 != f1) && (in[0] < clip0 && in[0] > 1e-5f) && (in[offs] < clip1 && in[offs] > 1e-5f)) { const int r = roff[f0][f1]; assert(r != 0); if (r > 0) ratios[r] = (3.f * ratios[r] + (in[offs] / in[0])) / 4.f; else ratios[-r] = (3.f * ratios[-r] + (in[0] / in[offs])) / 4.f; } if(in[0] >= clip0 - 1e-5f) { // interplate color for clipped pixel float add; if(f0 != f1) // next pixel is different color add = interp_pix_xtrans(roff[f0][f1], offs, clip0, clip1, in, ratios); else // at start of 2x2 green block, look diagonally add = (fl != f0) ? interp_pix_xtrans(roff[f0][fl], offl, clip0, clipl, in, ratios) : interp_pix_xtrans(roff[f0][fr], offr, clip0, clipr, in, ratios); if(pass == 0) out[0] = add; else if(pass == 3) out[0] = fminf(clip_max, (out[0] + add) / 4.0f); else out[0] += add; } else { // pixel is not clipped if(pass == 3) out[0] = in[0]; } } out += offs; in += offs; } }
void App::update(float delta_time) { if (anim_play) frame_count++; if (!hide_gui) gui(); // autoreload frag shader (every 60 frames) if (shader_filepath && shader_file_autoreload && (frame_count % 60) == 0) { struct stat attr; if (!stat(shader_filepath, &attr)) { // file exists if (attr.st_mtime > shader_file_mtime) { // file has been modified shader_file_mtime = (int)attr.st_mtime; reloadShader(); } } } // update camera (-z: forward, y: up) camera_euler_angles += 2.0f*delta_time * v3(-movement_command.rotate.x, -movement_command.rotate.y, 0.0f); camera_euler_angles.x = fminf(fmaxf(-0.5f*(float)M_PI, camera_euler_angles.x), 0.5f*(float)M_PI); // clamp mat3 rot_x = rotationMatrix(v3(1.0f, 0.0f, 0.0f), camera_euler_angles.x); mat3 rot_y = rotationMatrix(v3(0.0f, 1.0f, 0.0f), camera_euler_angles.y); mat3 rot_z = rotationMatrix(v3(0.0f, 0.0f, 1.0f), camera_euler_angles.z); mat3 rot = rot_y * rot_x * rot_z; camera_location += rot * (8.0f*delta_time*movement_command.move); mat4 view_to_world = translationMatrix(camera_location) * m4(rot); mat4 world_to_view = m4(transpose(rot)) * translationMatrix(-camera_location); // bind textures for (int tsi = 0; tsi < (int)ARRAY_COUNT(texture_slots); tsi++) { glActiveTexture(GL_TEXTURE0+tsi); glBindTexture(texture_slots[tsi].target, texture_slots[tsi].texture); } // draw fullscreen triangle(s) glClearColor(0.2f, 0.21f, 0.22f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); { BindShader bind_shader(shader); if (!compile_error_log) { for (int i = 0; i < uniform_count; i++) { uniforms[i].apply(); } } // apply builtin uniforms u_time = (float)frame_count / 60.0f; glUniform1f(shader.getUniformLocation(u_time_name), u_time); vec2 u_resolution = v2(video.pixel_scale*video.width, video.pixel_scale*video.height); glUniform2fv(shader.getUniformLocation(u_resolution_name), 1, u_resolution.e); glUniformMatrix4fv(shader.getUniformLocation(u_view_to_world_name), 1, GL_FALSE, view_to_world.e); glUniformMatrix4fv(shader.getUniformLocation(u_world_to_view_name), 1, GL_FALSE, world_to_view.e); if (single_triangle_mode) { { BindArrayBuffer bind_array_buffer(single_triangle_vbo); glEnableVertexAttribArray(VAT_POSITION); glVertexAttribPointer(VAT_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(VAT_POSITION); } } else { { BindArrayBuffer bind_array_buffer(two_triangles_vbo); glEnableVertexAttribArray(VAT_POSITION); glVertexAttribPointer(VAT_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDisableVertexAttribArray(VAT_POSITION); } } } }
static gboolean dt_iop_zonesystem_preview_expose (GtkWidget *widget, GdkEventExpose *event, dt_iop_module_t *self) { const int inset = 2; int width = widget->allocation.width, height = widget->allocation.height; dt_iop_zonesystem_gui_data_t *g = (dt_iop_zonesystem_gui_data_t *)self->gui_data; dt_iop_zonesystem_params_t *p = (dt_iop_zonesystem_params_t *)self->params; cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* clear background */ GtkStateType state = gtk_widget_get_state(self->expander); GtkStyle *style = gtk_widget_get_style(self->expander); cairo_set_source_rgb (cr, style->bg[state].red/65535.0, style->bg[state].green/65535.0, style->bg[state].blue/65535.0); cairo_paint (cr); width -= 2*inset; height -= 2*inset; cairo_translate(cr, inset, inset); dt_pthread_mutex_lock(&g->lock); if( g->preview_buffer && self->enabled) { /* calculate the zonemap */ float zonemap[MAX_ZONE_SYSTEM_SIZE]= {-1}; _iop_zonesystem_calculate_zonemap (p,zonemap); /* let's generate a pixbuf from pixel zone buffer */ guchar *image = g_malloc ((g->preview_width*g->preview_height)*4); for (int k=0; k<g->preview_width*g->preview_height; k++) { int zone = 255*CLIP (((1.0/(p->size-1))*g->preview_buffer[k])); image[4*k+2] = (g->hilite_zone && g->preview_buffer[k]==g->zone_under_mouse)?255:zone; image[4*k+1] = (g->hilite_zone && g->preview_buffer[k]==g->zone_under_mouse)?255:zone; image[4*k+0] = (g->hilite_zone && g->preview_buffer[k]==g->zone_under_mouse)?0:zone; } dt_pthread_mutex_unlock(&g->lock); const int wd = g->preview_width, ht = g->preview_height; const float scale = fminf(width/(float)wd, height/(float)ht); const int stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data (image, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width/2.0, height/2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f*wd, -.5f*ht); cairo_rectangle(cr, 1, 1, wd-2, ht-2); cairo_set_source_surface (cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_GOOD); cairo_fill_preserve(cr); cairo_surface_destroy (surface); cairo_set_line_width(cr, 1.0); cairo_set_source_rgb(cr, .1, .1, .1); cairo_stroke(cr); g_free(image); } else dt_pthread_mutex_unlock(&g->lock); cairo_destroy(cr); cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget)); cairo_set_source_surface (cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return TRUE; }
// internal function: to avoid exif blob reading + 8-bit byteorder flag + high-quality override int dt_imageio_export_with_flags( const uint32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const int32_t ignore_exif, const int32_t display_byteorder, const gboolean high_quality, const int32_t thumbnail_export, const char *filter, const gboolean copy_metadata, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params) { dt_develop_t dev; dt_dev_init(&dev, 0); dt_mipmap_buffer_t buf; if(thumbnail_export && dt_conf_get_bool("plugins/lighttable/low_quality_thumbnails")) dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_F, DT_MIPMAP_BLOCKING); else dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING); dt_dev_load_image(&dev, imgid); const dt_image_t *img = &dev.image_storage; const int wd = img->width; const int ht = img->height; int res = 0; dt_times_t start; dt_get_times(&start); dt_dev_pixelpipe_t pipe; res = thumbnail_export ? dt_dev_pixelpipe_init_thumbnail(&pipe, wd, ht) : dt_dev_pixelpipe_init_export(&pipe, wd, ht, format->levels(format_params)); if(!res) { dt_control_log(_("failed to allocate memory for %s, please lower the threads used for export or buy more memory."), thumbnail_export ? C_("noun", "thumbnail export") : C_("noun", "export")); dt_dev_cleanup(&dev); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); return 1; } if(!buf.buf) { dt_control_log(_("image `%s' is not available!"), img->filename); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); dt_dev_cleanup(&dev); return 1; } // If a style is to be applied during export, add the iop params into the history if (!thumbnail_export && format_params->style[0] != '\0') { GList *stls; GList *modules = dev.iop; dt_iop_module_t *m = NULL; if ((stls=dt_styles_get_item_list(format_params->style, TRUE, -1)) == 0) { dt_control_log(_("cannot find the style '%s' to apply during export."), format_params->style); dt_dev_cleanup(&dev); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); return 1; } // Add each params while (stls) { dt_style_item_t *s = (dt_style_item_t *) stls->data; modules = dev.iop; while (modules) { m = (dt_iop_module_t *)modules->data; // since the name in the style is returned with a possible multi-name, just check the start of the name if (strncmp(m->op, s->name, strlen(m->op)) == 0) { dt_dev_history_item_t *h = malloc(sizeof(dt_dev_history_item_t)); h->params = s->params; h->blend_params = s->blendop_params; h->enabled = s->enabled; h->module = m; h->multi_priority = 1; g_strlcpy(h->multi_name, "", sizeof(h->multi_name)); if(m->legacy_params && (s->module_version != m->version())) { void *new_params = malloc(m->params_size); m->legacy_params (m, h->params, s->module_version, new_params, labs(m->version())); free (h->params); h->params = new_params; } dev.history_end++; dev.history = g_list_append(dev.history, h); break; } modules = g_list_next(modules); } stls = g_list_next(stls); } } dt_dev_pixelpipe_set_input(&pipe, &dev, (float *)buf.buf, buf.width, buf.height, 1.0); dt_dev_pixelpipe_create_nodes(&pipe, &dev); dt_dev_pixelpipe_synch_all(&pipe, &dev); dt_dev_pixelpipe_get_dimensions(&pipe, &dev, pipe.iwidth, pipe.iheight, &pipe.processed_width, &pipe.processed_height); if(filter) { if(!strncmp(filter, "pre:", 4)) dt_dev_pixelpipe_disable_after(&pipe, filter+4); if(!strncmp(filter, "post:", 5)) dt_dev_pixelpipe_disable_before(&pipe, filter+5); } dt_show_times(&start, "[export] creating pixelpipe", NULL); // find output color profile for this image: int sRGB = 1; gchar *overprofile = dt_conf_get_string("plugins/lighttable/export/iccprofile"); if(overprofile && !strcmp(overprofile, "sRGB")) { sRGB = 1; } else if(!overprofile || !strcmp(overprofile, "image")) { GList *modules = dev.iop; dt_iop_module_t *colorout = NULL; while (modules) { colorout = (dt_iop_module_t *)modules->data; if(colorout->get_p && strcmp(colorout->op, "colorout") == 0) { const char *iccprofile = colorout->get_p(colorout->params, "iccprofile"); if(!strcmp(iccprofile, "sRGB")) sRGB = 1; else sRGB = 0; } modules = g_list_next(modules); } } else { sRGB = 0; } g_free(overprofile); // get only once at the beginning, in case the user changes it on the way: const gboolean high_quality_processing = ((format_params->max_width == 0 || format_params->max_width >= pipe.processed_width ) && (format_params->max_height == 0 || format_params->max_height >= pipe.processed_height)) ? FALSE : high_quality; const int width = high_quality_processing ? 0 : format_params->max_width; const int height = high_quality_processing ? 0 : format_params->max_height; const double scalex = width > 0 ? fminf(width /(double)pipe.processed_width, 1.0) : 1.0; const double scaley = height > 0 ? fminf(height/(double)pipe.processed_height, 1.0) : 1.0; const double scale = fminf(scalex, scaley); int processed_width = scale*pipe.processed_width + .5f; int processed_height = scale*pipe.processed_height + .5f; const int bpp = format->bpp(format_params); // downsampling done last, if high quality processing was requested: uint8_t *outbuf = pipe.backbuf; uint8_t *moutbuf = NULL; // keep track of alloc'ed memory dt_get_times(&start); if(high_quality_processing) { dt_dev_pixelpipe_process_no_gamma(&pipe, &dev, 0, 0, processed_width, processed_height, scale); const double scalex = format_params->max_width > 0 ? fminf(format_params->max_width /(double)pipe.processed_width, 1.0) : 1.0; const double scaley = format_params->max_height > 0 ? fminf(format_params->max_height/(double)pipe.processed_height, 1.0) : 1.0; const double scale = fminf(scalex, scaley); processed_width = scale*pipe.processed_width + .5f; processed_height = scale*pipe.processed_height + .5f; moutbuf = (uint8_t *)dt_alloc_align(64, (size_t)sizeof(float)*processed_width*processed_height*4); outbuf = moutbuf; // now downscale into the new buffer: dt_iop_roi_t roi_in, roi_out; roi_in.x = roi_in.y = roi_out.x = roi_out.y = 0; roi_in.scale = 1.0; roi_out.scale = scale; roi_in.width = pipe.processed_width; roi_in.height = pipe.processed_height; roi_out.width = processed_width; roi_out.height = processed_height; dt_iop_clip_and_zoom((float *)outbuf, (float *)pipe.backbuf, &roi_out, &roi_in, processed_width, pipe.processed_width); } else { // do the processing (8-bit with special treatment, to make sure we can use openmp further down): if(bpp == 8) dt_dev_pixelpipe_process(&pipe, &dev, 0, 0, processed_width, processed_height, scale); else dt_dev_pixelpipe_process_no_gamma(&pipe, &dev, 0, 0, processed_width, processed_height, scale); outbuf = pipe.backbuf; } dt_show_times(&start, thumbnail_export ? "[dev_process_thumbnail] pixel pipeline processing" : "[dev_process_export] pixel pipeline processing", NULL); // downconversion to low-precision formats: if(bpp == 8) { if(display_byteorder) { if(high_quality_processing) { const float *const inbuf = (float *)outbuf; for(size_t k=0; k<(size_t)processed_width*processed_height; k++) { // convert in place, this is unfortunately very serial.. const uint8_t r = CLAMP(inbuf[4*k+2]*0xff, 0, 0xff); const uint8_t g = CLAMP(inbuf[4*k+1]*0xff, 0, 0xff); const uint8_t b = CLAMP(inbuf[4*k+0]*0xff, 0, 0xff); outbuf[4*k+0] = r; outbuf[4*k+1] = g; outbuf[4*k+2] = b; } } // else processing output was 8-bit already, and no need to swap order } else // need to flip { // ldr output: char if(high_quality_processing) { const float *const inbuf = (float *)outbuf; for(size_t k=0; k<(size_t)processed_width*processed_height; k++) { // convert in place, this is unfortunately very serial.. const uint8_t r = CLAMP(inbuf[4*k+0]*0xff, 0, 0xff); const uint8_t g = CLAMP(inbuf[4*k+1]*0xff, 0, 0xff); const uint8_t b = CLAMP(inbuf[4*k+2]*0xff, 0, 0xff); outbuf[4*k+0] = r; outbuf[4*k+1] = g; outbuf[4*k+2] = b; } } else { // !display_byteorder, need to swap: uint8_t *const buf8 = pipe.backbuf; #ifdef _OPENMP #pragma omp parallel for default(none) shared(processed_width, processed_height) schedule(static) #endif // just flip byte order for(size_t k=0; k<(size_t)processed_width*processed_height; k++) { uint8_t tmp = buf8[4*k+0]; buf8[4*k+0] = buf8[4*k+2]; buf8[4*k+2] = tmp; } } } } else if(bpp == 16) { // uint16_t per color channel float *buff = (float *) outbuf; uint16_t *buf16 = (uint16_t *)outbuf; for(int y=0; y<processed_height; y++) for(int x=0; x<processed_width ; x++) { // convert in place const size_t k = (size_t)processed_width*y + x; for(int i=0; i<3; i++) buf16[4*k+i] = CLAMP(buff[4*k+i]*0x10000, 0, 0xffff); } } // else output float, no further harm done to the pixels :) format_params->width = processed_width; format_params->height = processed_height; if(!ignore_exif) { int length; uint8_t exif_profile[65535]; // C++ alloc'ed buffer is uncool, so we waste some bits here. char pathname[PATH_MAX]; gboolean from_cache = TRUE; dt_image_full_path(imgid, pathname, sizeof(pathname), &from_cache); // last param is dng mode, it's false here length = dt_exif_read_blob(exif_profile, pathname, imgid, sRGB, processed_width, processed_height, 0); res = format->write_image (format_params, filename, outbuf, exif_profile, length, imgid); } else { res = format->write_image (format_params, filename, outbuf, NULL, 0, imgid); } dt_dev_pixelpipe_cleanup(&pipe); dt_dev_cleanup(&dev); dt_mipmap_cache_read_release(darktable.mipmap_cache, &buf); dt_free_align(moutbuf); /* now write xmp into that container, if possible */ if(copy_metadata && (format->flags(format_params) & FORMAT_FLAGS_SUPPORT_XMP)) { dt_exif_xmp_attach(imgid, filename); // no need to cancel the export if this fail } if(!thumbnail_export && strcmp(format->mime(format_params), "memory")) { dt_control_signal_raise(darktable.signals,DT_SIGNAL_IMAGE_EXPORT_TMPFILE,imgid,filename,format,format_params,storage,storage_params); } return res; }
void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out) { dt_iop_grain_data_t *data = (dt_iop_grain_data_t *)piece->data; unsigned int hash = _hash_string(piece->pipe->image.filename) % (int)fmax(roi_out->width * 0.3, 1.0); const int ch = piece->colors; // Apply grain to image const double strength = (data->strength / 100.0); const double octaves = 3; // double zoom=1.0+(8*(data->scale/100.0)); const double wd = fminf(piece->buf_in.width, piece->buf_in.height); const double zoom = (1.0 + 8 * data->scale / 100) / 800.0; const int filter = fabsf(roi_out->scale - 1.0f) > 0.01; // filter width depends on world space (i.e. reverse wd norm and roi->scale, as well as buffer input to // pixelpipe iscale) const double filtermul = piece->iscale / (roi_out->scale * wd); const float fib1 = 34.0, fib2 = 21.0; const float fib1div2 = fib1 / fib2; #ifdef _OPENMP #pragma omp parallel for default(none) shared(data, hash) #endif for(int j = 0; j < roi_out->height; j++) { float *in = ((float *)ivoid) + (size_t)roi_out->width * j * ch; float *out = ((float *)ovoid) + (size_t)roi_out->width * j * ch; const double wy = (roi_out->y + j) / roi_out->scale; const double y = wy / wd; // y: normalized to shorter side of image, so with pixel aspect = 1. for(int i = 0; i < roi_out->width; i++) { // calculate x, y in a resolution independent way: // wx,wy: worldspace in full image pixel coords: const double wx = (roi_out->x + i) / roi_out->scale; // x: normalized to shorter side of image, so with pixel aspect = 1. const double x = wx / wd; // double noise=_perlin_2d_noise(x, y, octaves,0.25, zoom)*1.5; double noise = 0.0; if(filter) { // if zoomed out a lot, use rank-1 lattice downsampling for(int l = 0; l < fib2; l++) { float px = l / fib2, py = l * fib1div2; py -= (int)py; float dx = px * filtermul, dy = py * filtermul; noise += (1.0 / fib2) * _simplex_2d_noise(x + dx + hash, y + dy, octaves, 1.0, zoom); } } else { noise = _simplex_2d_noise(x + hash, y, octaves, 1.0, zoom); } out[0] = in[0] + dt_lut_lookup_2d_1c(data->grain_lut, (noise * strength) * GRAIN_LIGHTNESS_STRENGTH_SCALE, in[0] / 100.0f); out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; out += ch; in += ch; } } }
/* ** Creates a MD5OpenGLMesh from an md5file */ static int MD5OpenGLMeshCreateWithFile( MD5OpenGLMesh** glmesh, const char* filename ) { FxsMD5Mesh* md5mesh = NULL; FxsMD5SubMesh* md5subMesh = NULL; FxsMD5Weight* md5weight = NULL; FxsMD5Vertex* md5vertex = NULL; FxsMD5Face* md5face = NULL; FxsMD5Joint* md5joint = NULL; FxsVector4 weightPosition; /* transformed weight position */ FxsVector3* vertPosition; unsigned int count = 0; /* counts the vertices loaded */ unsigned int* vertexIds = NULL; /* vertex indices of md5face */ int i = 0, j = 0, k = 0, l = 0; /* loop variables */ if (!FxsMD5MeshCreateWithFile(&md5mesh, filename)) { sprintf(errMsg, "Warning: could not load md5mesh: %s", filename); ERR_MSG(errMsg); return 0; } *glmesh = (MD5OpenGLMesh*)malloc(sizeof(MD5OpenGLMesh)); if (!glmesh) { sprintf( errMsg, "Warning: malloc for MD5OpenGL mesh failed. Could not load md5mesh: %s", filename ); ERR_MSG(errMsg) FxsMD5MeshDestroy(&md5mesh); return 0; } /* prepare gl mesh */ memset(*glmesh, 0, sizeof(MD5OpenGLMesh)); (*glmesh)->md5mesh = md5mesh; (*glmesh)->numSubMeshes = md5mesh->numSubMeshes; (*glmesh)->subMeshes = (MD5OpenGLSubMesh*)malloc( md5mesh->numSubMeshes*sizeof(MD5OpenGLSubMesh) ); if (!(*glmesh)->subMeshes) { sprintf( errMsg, "Warning: malloc failed. Could not load md5mesh: %s", filename ); ERR_MSG(errMsg); FxsMD5MeshDestroy(&md5mesh); MD5OpenGLMeshDestroy(glmesh); return 0; } memset( (*glmesh)->subMeshes, 0, (*glmesh)->numSubMeshes*sizeof(MD5OpenGLSubMesh) ); (*glmesh)->min.x = FLT_MAX; (*glmesh)->min.y = FLT_MAX; (*glmesh)->min.z = FLT_MAX; (*glmesh)->max.x = FLT_MIN; (*glmesh)->max.y = FLT_MIN; (*glmesh)->max.z = FLT_MIN; /* load the submeshes */ for (i = 0; i < md5mesh->numSubMeshes; i++) /* for each md5submesh */ { md5subMesh = &md5mesh->meshes[i]; /* alloc host memory for positions of this gl submesh */ (*glmesh)->subMeshes[i].numPositions = 3*md5subMesh->numFaces; (*glmesh)->subMeshes[i].positionsHost = (FxsVector3*)malloc( 3*md5subMesh->numFaces*sizeof(FxsVector3) ); if (!(*glmesh)->subMeshes[i].positionsHost) { sprintf( errMsg, "Warning: malloc failed. Could not load md5mesh: %s", filename ); ERR_MSG(errMsg); FxsMD5MeshDestroy(&md5mesh); MD5OpenGLMeshDestroy(glmesh); } memset( (*glmesh)->subMeshes[i].positionsHost, 0, 3*md5subMesh->numFaces*sizeof(FxsVector3) ); /* init the bounding box for the sub mesh */ (*glmesh)->subMeshes[i].min.x = FLT_MAX; (*glmesh)->subMeshes[i].min.y = FLT_MAX; (*glmesh)->subMeshes[i].min.z = FLT_MAX; (*glmesh)->subMeshes[i].max.x = FLT_MIN; (*glmesh)->subMeshes[i].max.y = FLT_MIN; (*glmesh)->subMeshes[i].max.z = FLT_MIN; count = 0; for (j = 0; j < md5subMesh->numFaces; j++) /* for each face of the ** submesh */ { md5face = &md5subMesh->faces[j]; vertexIds = &md5face->v1; for (k = 0; k < 3; k++) /* for each vertex of the face */ { md5vertex = &md5subMesh->vertices[vertexIds[k]]; /* make the current vertex position zero */ vertPosition = &(*glmesh)->subMeshes[i].positionsHost[count]; FxsVector3MakeZero(vertPosition); for (l = 0; l < md5vertex->numWeights; l++) /* for each weight ** of the vertex */ { md5weight = &md5subMesh->weights[md5vertex->weightId + l]; md5joint = &md5mesh->currentPose.joints[md5weight->jointId]; FxsMatrix4MultiplyVector3( &weightPosition, &md5joint->transform, &md5weight->position ); /* add up all weight positions to compute the final ** vertex position. */ vertPosition->x += md5weight->value*weightPosition.x; vertPosition->y += md5weight->value*weightPosition.y; vertPosition->z += md5weight->value*weightPosition.z; } /* update the bounding box */ (*glmesh)->subMeshes[i].min.x = fminf( (*glmesh)->subMeshes[i].min.x, vertPosition->x ); (*glmesh)->subMeshes[i].min.y = fminf( (*glmesh)->subMeshes[i].min.y, vertPosition->y ); (*glmesh)->subMeshes[i].min.z = fminf( (*glmesh)->subMeshes[i].min.z, vertPosition->z ); (*glmesh)->subMeshes[i].max.x = fmaxf( (*glmesh)->subMeshes[i].max.x, vertPosition->x ); (*glmesh)->subMeshes[i].max.y = fmaxf( (*glmesh)->subMeshes[i].max.y, vertPosition->y ); (*glmesh)->subMeshes[i].max.z = fmaxf( (*glmesh)->subMeshes[i].max.z, vertPosition->z ); count++; } } (*glmesh)->min.x = fminf((*glmesh)->subMeshes[i].min.x, (*glmesh)->min.x); (*glmesh)->min.y = fminf((*glmesh)->subMeshes[i].min.y, (*glmesh)->min.y); (*glmesh)->min.z = fminf((*glmesh)->subMeshes[i].min.z, (*glmesh)->min.z); (*glmesh)->max.x = fmaxf((*glmesh)->subMeshes[i].max.x, (*glmesh)->max.x); (*glmesh)->max.y = fmaxf((*glmesh)->subMeshes[i].max.y, (*glmesh)->max.y); (*glmesh)->max.z = fmaxf((*glmesh)->subMeshes[i].max.z, (*glmesh)->max.z); /* initialize the opengl data for the sub mesh */ glGenBuffers(1, &(*glmesh)->subMeshes[i].positions); glBindBuffer(GL_ARRAY_BUFFER, (*glmesh)->subMeshes[i].positions); glBufferData( GL_ARRAY_BUFFER, sizeof(FxsVector3)*(*glmesh)->subMeshes[i].numPositions, (*glmesh)->subMeshes[i].positionsHost, GL_DYNAMIC_DRAW ); glGenVertexArrays(1, &(*glmesh)->subMeshes[i].vao); glBindVertexArray((*glmesh)->subMeshes[i].vao); glBindBuffer(GL_ARRAY_BUFFER, (*glmesh)->subMeshes[i].positions); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); if (GL_NO_ERROR != glGetError()) { sprintf(errMsg, "Warning: opengl failed. Could not load md5mesh: %s", filename); ERR_MSG(errMsg); FxsMD5MeshDestroy(&md5mesh); MD5OpenGLMeshDestroy(glmesh); return 0; } } return 1; }
static void THNN_(VolumetricMaxPooling_updateOutput_frame)( real *input_p, real *output_p, real *indz_p, long nslices, long itime, long iwidth, long iheight, long otime, long owidth, long oheight, int kT, int kW, int kH, int dT, int dW, int dH, int pT, int pW, int pH) { long k; #pragma omp parallel for private(k) for (k = 0; k < nslices; k++) { /* loop over output */ long i, j, ti; for (ti = 0; ti < otime; ti++) { for (i = 0; i < oheight; i++) { for (j = 0; j < owidth; j++) { /* local pointers */ long start_t = ti * dT - pT; long start_h = i * dH - pH; long start_w = j * dW - pW; long kernel_t = fminf(kT, kT + start_t); long kernel_h = fminf(kH, kH + start_h); long kernel_w = fminf(kW, kW + start_w); start_t = fmaxf(start_t, 0); start_h = fmaxf(start_h, 0); start_w = fmaxf(start_w, 0); real *ip = input_p + k * itime * iwidth * iheight + start_t * iwidth * iheight + start_h * iwidth + start_w; real *op = output_p + k * otime * owidth * oheight + ti * owidth * oheight + i * owidth + j; real *indzp = indz_p + k * otime * owidth * oheight + ti * owidth * oheight + i * owidth + j; /* compute local max: */ real maxval = -THInf; int x,y,z; int mx, my, mz; for (z = 0; z < kernel_t; z++) { for (y = 0; y < kernel_h; y++) { for (x = 0; x < kernel_w; x++) { if ((start_t + z < itime) && (start_h + y < iheight) && (start_w + x < iwidth)) { real val = *(ip + z * iwidth * iheight + y * iwidth + x); if (val > maxval) { maxval = val; // Store indices w.r.t the kernel dimension mz = z + (kT - kernel_t); my = y + (kH - kernel_h); mx = x + (kW - kernel_w); } } } } } // set max values ((unsigned char*)(indzp))[0] = mz; ((unsigned char*)(indzp))[1] = my; ((unsigned char*)(indzp))[2] = mx; ((unsigned char*)(indzp))[3] = 0; /* set output to local max */ *op = maxval; } } } } }
/* ** updates the md5mesh of mesh according to the passed animation and the frame. ** updates geometry on host and opengl side according to the updated pose. */ static int MD5OpenGLMeshUpdatePoseWithAnimationFrame( MD5OpenGLMesh* mesh, const FxsMD5Animation* animation, unsigned int frame ) { int i = 0, j = 0, k = 0, l = 0; FxsMD5Mesh* md5mesh = mesh->md5mesh; FxsMD5SubMesh* md5submesh = NULL; FxsMD5Face* face = NULL; FxsMD5Vertex* vertex = NULL; FxsMD5Weight* weight = NULL; FxsMD5Joint* joint = NULL; FxsVector3* vertPosition = NULL; FxsVector4 weightPosition; unsigned int* vertexIds = NULL; MD5OpenGLSubMesh* glsubmesh = NULL; int count = 0; if (!FxsMD5MeshUpdatePoseWithAnimationFrame(mesh->md5mesh, animation, frame)) { return 0; } mesh->min.x = FLT_MAX; mesh->min.y = FLT_MAX; mesh->min.z = FLT_MAX; mesh->max.x = FLT_MIN; mesh->max.y = FLT_MIN; mesh->max.z = FLT_MIN; /* for all submeshes of the md5mesh, let's update the host and opengl data ** of the opengl submeshes geometry (positions ...) */ for (i = 0; i < md5mesh->numSubMeshes; i++) { glsubmesh = &mesh->subMeshes[i]; md5submesh = &md5mesh->meshes[i]; count = 0; mesh->subMeshes[i].min.x = FLT_MAX; mesh->subMeshes[i].min.y = FLT_MAX; mesh->subMeshes[i].min.z = FLT_MAX; mesh->subMeshes[i].max.x = FLT_MIN; mesh->subMeshes[i].max.y = FLT_MIN; mesh->subMeshes[i].max.z = FLT_MIN; /* for each face in the md5submesh ... */ for (j = 0; j < md5submesh->numFaces; j++) { face = &md5submesh->faces[j]; vertexIds = &face->v1; /* ... update each vertex */ for (k = 0; k < 3; k++) { vertex = &md5submesh->vertices[vertexIds[k]]; /* make the current vertex position zero */ vertPosition = &mesh->subMeshes[i].positionsHost[count]; FxsVector3MakeZero(vertPosition); /* update the position of each vertex by interation over ** each of its weights */ for (l = 0; l < vertex->numWeights; l++) { weight = &md5submesh->weights[vertex->weightId + l]; joint = &md5mesh->currentPose.joints[weight->jointId]; FxsMatrix4MultiplyVector3( &weightPosition, &joint->transform, &weight->position ); /* add up all weight positions to compute the final ** vertex position. */ vertPosition->x += weight->value*weightPosition.x; vertPosition->y += weight->value*weightPosition.y; vertPosition->z += weight->value*weightPosition.z; } /* update the bounding box */ mesh->subMeshes[i].min.x = fminf( mesh->subMeshes[i].min.x, vertPosition->x ); mesh->subMeshes[i].min.y = fminf( mesh->subMeshes[i].min.y, vertPosition->y ); mesh->subMeshes[i].min.z = fminf( mesh->subMeshes[i].min.z, vertPosition->z ); mesh->subMeshes[i].max.x = fmaxf( mesh->subMeshes[i].max.x, vertPosition->x ); mesh->subMeshes[i].max.y = fmaxf( mesh->subMeshes[i].max.y, vertPosition->y ); mesh->subMeshes[i].max.z = fmaxf( mesh->subMeshes[i].max.z, vertPosition->z ); count++; } } mesh->min.x = fminf(mesh->subMeshes[i].min.x, mesh->min.x); mesh->min.y = fminf(mesh->subMeshes[i].min.y, mesh->min.y); mesh->min.z = fminf(mesh->subMeshes[i].min.z, mesh->min.z); mesh->max.x = fmaxf(mesh->subMeshes[i].max.x, mesh->max.x); mesh->max.y = fmaxf(mesh->subMeshes[i].max.y, mesh->max.y); mesh->max.z = fmaxf(mesh->subMeshes[i].max.z, mesh->max.z); /* update the opengl data for the sub mesh */ glBindBuffer(GL_ARRAY_BUFFER, mesh->subMeshes[i].positions); glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(FxsVector3)*mesh->subMeshes[i].numPositions, mesh->subMeshes[i].positionsHost ); // glGenVertexArrays(1, &(*glmesh)->subMeshes[i].vao); // glBindVertexArray((*glmesh)->subMeshes[i].vao); // glBindBuffer(GL_ARRAY_BUFFER, (*glmesh)->subMeshes[i].positions); // glEnableVertexAttribArray(0); // glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); if (GL_NO_ERROR != glGetError()) { sprintf(errMsg, "Warning: opengl failed. Could not update md5mesh"); ERR_MSG(errMsg); return 0; } } return 1; }
void test2f(float x, float y) { if (-tanf(x-y) != tanf(y-x)) link_error (); if (-sinf(x-y) != sinf(y-x)) link_error (); if (cosf(-x*y) != cosf(x*y)) link_error (); if (cosf(x*-y) != cosf(x*y)) link_error (); if (cosf(-x/y) != cosf(x/y)) link_error (); if (cosf(x/-y) != cosf(x/y)) link_error (); if (cosf(-fabsf(tanf(x/-y))) != cosf(tanf(x/y))) link_error (); if (cosf(y<10 ? -x : y) != cosf(y<10 ? x : y)) link_error (); if (cosf(y<10 ? x : -y) != cosf(y<10 ? x : y)) link_error (); if (cosf(y<10 ? -fabsf(x) : tanf(x<20 ? -x : -fabsf(y))) != cosf(y<10 ? x : tanf(x<20 ? x : y))) link_error (); if (cosf((y*=3, -x)) != cosf((y*=3,x))) link_error (); if (cosf((y*=2, -fabsf(tanf(x/-y)))) != cosf((y*=2,tanf(x/y)))) link_error (); if (cosf(copysignf(x,y)) != cosf(x)) link_error (); if (cosf(copysignf(-fabsf(x),y*=2)) != cosf((y*=2,x))) link_error (); if (hypotf (x, 0) != fabsf(x)) link_error (); if (hypotf (0, x) != fabsf(x)) link_error (); if (hypotf (x, x) != fabsf(x) * __builtin_sqrtf(2)) link_error (); if (hypotf (-x, y) != hypotf (x, y)) link_error (); if (hypotf (x, -y) != hypotf (x, y)) link_error (); if (hypotf (-x, -y) != hypotf (x, y)) link_error (); if (hypotf (fabsf(x), y) != hypotf (x, y)) link_error (); if (hypotf (x, fabsf(y)) != hypotf (x, y)) link_error (); if (hypotf (fabsf(x), fabsf(y)) != hypotf (x, y)) link_error (); if (hypotf (-fabsf(-x), -fabsf(fabsf(fabsf(-y)))) != hypotf (x, y)) link_error (); if (hypotf (-x, 0) != fabsf(x)) link_error (); if (hypotf (-x, x) != fabsf(x) * __builtin_sqrtf(2)) link_error (); if (hypotf (puref(x), -puref(x)) != fabsf(puref(x)) * __builtin_sqrtf(2)) link_error (); if (hypotf (tanf(-x), tanf(-fabsf(y))) != hypotf (tanf(x), tanf(y))) link_error (); if (fminf (fmaxf(x,y),y) != y) link_error (); if (fminf (fmaxf(y,x),y) != y) link_error (); if (fminf (x,fmaxf(x,y)) != x) link_error (); if (fminf (x,fmaxf(y,x)) != x) link_error (); if (fmaxf (fminf(x,y),y) != y) link_error (); if (fmaxf (fminf(y,x),y) != y) link_error (); if (fmaxf (x,fminf(x,y)) != x) link_error (); if (fmaxf (x,fminf(y,x)) != x) link_error (); if ((__complex__ float) x != -(__complex__ float) (-x)) link_error (); if (x+(x-y)*1i != -(-x+(y-x)*1i)) link_error (); if (x+(x-y)*1i != -(-x-(x-y)*1i)) link_error (); if (ccosf(tanf(x)+sinf(y)*1i) != ccosf(-tanf(-x)+-sinf(-y)*1i)) link_error (); if (ccosf(tanf(x)+sinf(x-y)*1i) != ccosf(-tanf(-x)-sinf(y-x)*1i)) link_error (); if (-5+x*1i != -~(5+x*1i)) link_error (); if (tanf(x)+tanf(y)*1i != -~(tanf(-x)+tanf(y)*1i)) link_error (); }
Vector4 Vector4::lerp(const Vector4& a, const Vector4& b, float t) { t = fmaxf(t, 0); t = fminf(t, 1); return Vector4(b.x*t + a.x*(1 - t), b.y*t + a.y*(1 - t), b.z*t + a.z*(1 - t), b.w*t + a.w*(1 - t)); }
static int dt_group_get_mask(dt_iop_module_t *module, dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, float **buffer, int *width, int *height, int *posx, int *posy) { double start2; // we allocate buffers and values const guint nb = g_list_length(form->points); if(nb == 0) return 0; float *bufs[nb]; int w[nb]; int h[nb]; int px[nb]; int py[nb]; int ok[nb]; int states[nb]; float op[nb]; // and we get all masks GList *fpts = g_list_first(form->points); int pos = 0; int nb_ok = 0; while(fpts) { dt_masks_point_group_t *fpt = (dt_masks_point_group_t *)fpts->data; dt_masks_form_t *sel = dt_masks_get_from_id(module->dev, fpt->formid); if(sel) { ok[pos] = dt_masks_get_mask(module, piece, sel, &bufs[pos], &w[pos], &h[pos], &px[pos], &py[pos]); if(fpt->state & DT_MASKS_STATE_INVERSE) { start2 = dt_get_wtime(); _inverse_mask(module, piece, sel, &bufs[pos], &w[pos], &h[pos], &px[pos], &py[pos]); if(darktable.unmuted & DT_DEBUG_PERF) dt_print(DT_DEBUG_MASKS, "[masks %s] inverse took %0.04f sec\n", sel->name, dt_get_wtime() - start2); // start2 = dt_get_wtime(); } op[pos] = fpt->opacity; states[pos] = fpt->state; if(ok[pos]) nb_ok++; } fpts = g_list_next(fpts); pos++; } if(nb_ok == 0) return 0; // now we get the min, max, width, height of the final mask int l, r, t, b; l = t = INT_MAX; r = b = INT_MIN; for(int i = 0; i < nb; i++) { l = MIN(l, px[i]); t = MIN(t, py[i]); r = MAX(r, px[i] + w[i]); b = MAX(b, py[i] + h[i]); } *posx = l; *posy = t; *width = r - l; *height = b - t; // we allocate the buffer *buffer = malloc(sizeof(float) * (r - l) * (b - t)); // and we copy each buffer inside, row by row for(int i = 0; i < nb; i++) { start2 = dt_get_wtime(); if(states[i] & DT_MASKS_STATE_UNION) { for(int y = 0; y < h[i]; y++) { for(int x = 0; x < w[i]; x++) { (*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l] = fmaxf((*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l], bufs[i][y * w[i] + x] * op[i]); } } } else if(states[i] & DT_MASKS_STATE_INTERSECTION) { for(int y = 0; y < b - t; y++) { for(int x = 0; x < r - l; x++) { float b1 = (*buffer)[y * (r - l) + x]; float b2 = 0.0f; if(y + t - py[i] >= 0 && y + t - py[i] < h[i] && x + l - px[i] >= 0 && x + l - px[i] < w[i]) b2 = bufs[i][(y + t - py[i]) * w[i] + x + l - px[i]]; if(b1 > 0.0f && b2 > 0.0f) (*buffer)[y * (r - l) + x] = fminf(b1, b2 * op[i]); else (*buffer)[y * (r - l) + x] = 0.0f; } } } else if(states[i] & DT_MASKS_STATE_DIFFERENCE) { for(int y = 0; y < h[i]; y++) { for(int x = 0; x < w[i]; x++) { float b1 = (*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l]; float b2 = bufs[i][y * w[i] + x] * op[i]; if(b1 > 0.0f && b2 > 0.0f) (*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l] = b1 * (1.0f - b2); } } } else if(states[i] & DT_MASKS_STATE_EXCLUSION) { for(int y = 0; y < h[i]; y++) { for(int x = 0; x < w[i]; x++) { float b1 = (*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l]; float b2 = bufs[i][y * w[i] + x] * op[i]; if(b1 > 0.0f && b2 > 0.0f) (*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l] = fmaxf((1.0f - b1) * b2, b1 * (1.0f - b2)); else (*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l] = fmaxf((*buffer)[(py[i] + y - t) * (r - l) + px[i] + x - l], bufs[i][y * w[i] + x] * op[i]); } } } else // if we are here, this mean that we just have to copy the shape and null other parts { for(int y = 0; y < b - t; y++) { for(int x = 0; x < r - l; x++) { float b2 = 0.0f; if(y + t - py[i] >= 0 && y + t - py[i] < h[i] && x + l - px[i] >= 0 && x + l - px[i] < w[i]) b2 = bufs[i][(y + t - py[i]) * w[i] + x + l - px[i]]; (*buffer)[y * (r - l) + x] = b2 * op[i]; } } } // and we free the buffer free(bufs[i]); if(darktable.unmuted & DT_DEBUG_PERF) dt_print(DT_DEBUG_MASKS, "[masks %d] combine took %0.04f sec\n", i, dt_get_wtime() - start2); // start2 = dt_get_wtime(); } return 1; }
Vector4 Vector4::min(const Vector4& a, const Vector4& b) { return Vector4(fminf(a.x, b.x), fminf(a.y, b.y), fminf(a.z, b.z), fminf(a.w, b.w)); }
int main( int argc, char *argv[] ) { /* parameters of strings */ double Gamma = LOOP_RAD_POWER; /* power radiated by loops */ double c = CUSPS_PER_LOOP; /* cusps per loop */ double p,epsilon,f,Gmu,alpha; double gammaAverage = 0, gammaMin = 0, gammaMax =0; char filename[FILENAME_MAX]; FILE *fp; int i,j,k,l; /* read the command line */ if (ReadCommandLine(argc,argv,&CLA)) return 1; f=CLA.f; /* read efficiency function */ if (ReadEfficiencyFile(CLA)) return 2; snprintf( filename, sizeof( filename ), "gamma.dat"); fp = fopen( filename, "w" ); fprintf( fp,"%% p n epsilon Gmu gammaAverage gammaMin gammaMax\n"); for ( i = 0; i < CLA.nepsilon; i++ ) { epsilon=pow(10.0,CLA.logepsilonstart+i*(CLA.logepsilonend-CLA.logepsilonstart)/(CLA.nepsilon-1)); for ( j = 0; j < CLA.nGmu; j++ ) { Gmu=pow(10.0,CLA.logGmustart+j*(CLA.logGmuend-CLA.logGmustart)/(CLA.nGmu-1)); alpha = epsilon * pow( Gamma * Gmu, CLA.n ); /* find the z's corresponding to those A's */ if(findzofA(Gmu, alpha)) return 3; /* compute the rate derivative at those z's */ if(finddRdz(Gmu, alpha, f, Gamma)) return 4; for ( k = 0; k < CLA.np; k++ ) { p=pow(10.0, CLA.logpstart+k*(CLA.logpend-CLA.logpstart)/(CLA.np)); fprintf(stdout,"%%Computing effective rate for Gmu=%e, epsilon=%e, p=%e\n ",Gmu, epsilon, p); /* Compute the rate of bursts */ gammaAverage=0.0; gammaMin = 0.0; gammaMax = 0.0; for (l = 0; l < Namp-1; l++) { Dlnz = (-log(zofA[l+1])+log(zofA[l])); gammaAverage += eff[l] * zofA[l] * dRdz[l] * Dlnz; gammaMin += fmaxf((eff[l]-Deff[l]),0.0) * zofA[l] * dRdz[l] * Dlnz; gammaMax += fminf((eff[l]+Deff[l]),1.0) * zofA[l] * dRdz[l] * Dlnz; } gammaAverage *= c/p; gammaMin *= c/p; gammaMax *= c/p; fprintf( fp,"%e %e %e %e %e %e %e\n", p,CLA.n,epsilon,Gmu,gammaAverage,gammaMin,gammaMax); } } } fclose( fp ); free(amp); free(lnamp); free(eff); free(Deff); free(zofA); free(dzdA); free(dRdz); return 0; }
void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *ivoid, void *ovoid, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out) { dt_iop_highlights_data_t *data = (dt_iop_highlights_data_t *)piece->data; float *in; float *out; const int ch = piece->colors; const float clip = data->clip * fminf(piece->pipe->processed_maximum[0], fminf(piece->pipe->processed_maximum[1], piece->pipe->processed_maximum[2])); float inc[3], lch[3], lchc[3], lchi[3]; switch(data->mode) { case DT_IOP_HIGHLIGHTS_LCH: #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) default(none) shared(ovoid, ivoid, roi_out, data, piece) private(in, out, inc, lch, lchc, lchi) #endif for(int j=0; j<roi_out->height; j++) { out = (float *)ovoid + ch*roi_out->width*j; in = (float *)ivoid + ch*roi_out->width*j; for(int i=0; i<roi_out->width; i++) { if(in[0] <= clip && in[1] <= clip && in[2] <= clip) { // fast path for well-exposed pixels. for(int c=0; c<3; c++) out[c] = in[c]; } else { for(int c=0; c<3; c++) inc[c] = fminf(clip, in[c]); rgb_to_lch(in, lchi); rgb_to_lch(inc, lchc); lch[0] = lchc[0] + data->blendL * (lchi[0] - lchc[0]); lch[1] = lchc[1] + data->blendC * (lchi[1] - lchc[1]); lch[2] = lchc[2] + data->blendh * (lchi[2] - lchc[2]); lch_to_rgb(lch, out); } out += ch; in += ch; } } break; default: case DT_IOP_HIGHLIGHTS_CLIP: #ifdef _OPENMP #pragma omp parallel for schedule(dynamic) default(none) shared(ovoid, ivoid, roi_out) private(in, out, inc, lch, lchc, lchi) #endif for(int j=0; j<roi_out->height; j++) { out = (float *)ovoid + ch*roi_out->width*j; in = (float *)ivoid + ch*roi_out->width*j; for(int i=0; i<roi_out->width; i++) { for(int c=0; c<3; c++) out[c] = fminf(clip, in[c]); out += ch; in += ch; } } break; } if(piece->pipe->mask_display) dt_iop_alpha_copy(ivoid, ovoid, roi_out->width, roi_out->height); }
/// clamp each vector values Vec3 clamp(float min_v, float max_v) const { return Vec3( fminf( fmaxf(x, min_v), max_v), fminf( fmaxf(y, min_v), max_v), fminf( fmaxf(z, min_v), max_v)); }
/* Minimum of input signals */ float tf_min(struct sampleclock sc, void **storage, float a, float b) { return fminf(a, b); }
static inline float min(float a, float b) { return fminf(a, b); }
static void auto_apply_presets(dt_develop_t *dev) { const int imgid = dev->image_storage.id; if(imgid <= 0) return; int run = 0; const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); if(!(cimg->flags & DT_IMAGE_AUTO_PRESETS_APPLIED)) run = 1; // flag was already set? only apply presets once in the lifetime of a history stack. // (the flag will be cleared when removing it) if(!run || cimg->id <= 0) { dt_image_cache_read_release(darktable.image_cache, cimg); return; } // keep locked, we want to be alone messing with the history of the poor fellow: dt_image_t *image = dt_image_cache_write_get(darktable.image_cache, cimg); // be extra sure that we don't mess up history in separate threads: dt_pthread_mutex_lock(&darktable.db_insert); // cleanup DT_DEBUG_SQLITE3_EXEC(dt_database_get(darktable.db), "delete from memory.history", NULL, NULL, NULL); const char *preset_table[2] = {"presets", "legacy_presets"}; const int legacy = (image->flags & DT_IMAGE_NO_LEGACY_PRESETS) ? 0 : 1; char query[1024]; snprintf(query, 1024, "insert into memory.history select ?1, 0, op_version, operation, op_params, enabled, blendop_params, blendop_version, multi_priority, multi_name " "from %s where autoapply=1 and " "?2 like model and ?3 like maker and ?4 like lens and " "?5 between iso_min and iso_max and " "?6 between exposure_min and exposure_max and " "?7 between aperture_min and aperture_max and " "?8 between focal_length_min and focal_length_max and " "(isldr = 0 or isldr=?9) order by writeprotect desc, " "length(model), length(maker), length(lens)", preset_table[legacy]); // query for all modules at once: sqlite3_stmt *stmt; DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), query, -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, imgid); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 2, cimg->exif_model, strlen(cimg->exif_model), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 3, cimg->exif_maker, strlen(cimg->exif_maker), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_TEXT(stmt, 4, cimg->exif_lens, strlen(cimg->exif_lens), SQLITE_TRANSIENT); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 5, fmaxf(0.0f, fminf(1000000, cimg->exif_iso))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 6, fmaxf(0.0f, fminf(1000000, cimg->exif_exposure))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 7, fmaxf(0.0f, fminf(1000000, cimg->exif_aperture))); DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 8, fmaxf(0.0f, fminf(1000000, cimg->exif_focal_length))); // 0: dontcare, 1: ldr, 2: raw DT_DEBUG_SQLITE3_BIND_DOUBLE(stmt, 9, 2-dt_image_is_ldr(cimg)); if(sqlite3_step(stmt) == SQLITE_DONE) { sqlite3_finalize(stmt); int cnt = 0; // count what we found: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "select count(*) from memory.history", -1, &stmt, NULL); if(sqlite3_step(stmt) == SQLITE_ROW) { // if there is anything.. cnt = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); // fprintf(stderr, "[auto_apply_presets] imageid %d found %d matching presets (legacy %d)\n", imgid, cnt, legacy); // advance the current history by that amount: DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "update history set num=num+?1 where imgid=?2", -1, &stmt, NULL); DT_DEBUG_SQLITE3_BIND_INT(stmt, 1, cnt); DT_DEBUG_SQLITE3_BIND_INT(stmt, 2, imgid); if(sqlite3_step(stmt) == SQLITE_DONE) { // and finally prepend the rest with increasing numbers (starting at 0) sqlite3_finalize(stmt); DT_DEBUG_SQLITE3_PREPARE_V2(dt_database_get(darktable.db), "insert into history select imgid, rowid-1, module, operation, op_params, enabled, " "blendop_params, blendop_version, multi_priority, multi_name from memory.history", -1, &stmt, NULL); sqlite3_step(stmt); } } } sqlite3_finalize(stmt); // first time we are loading the image, try to import lightroom .xmp if any if (dev->image_loading) dt_lightroom_import(dev->image_storage.id, dev, TRUE); image->flags |= DT_IMAGE_AUTO_PRESETS_APPLIED | DT_IMAGE_NO_LEGACY_PRESETS; dt_pthread_mutex_unlock(&darktable.db_insert); // make sure these end up in the image_cache + xmp (sync through here if we set the flag) dt_image_cache_write_release(darktable.image_cache, image, DT_IMAGE_CACHE_SAFE); dt_image_cache_read_release(darktable.image_cache, cimg); }
//Chase firing bool Enemy::chaseFire(b2Vec2 & rFireV) { bool trigger = false; //Did we fire? if (fired_) { angry_ = fmaxf(angry_ - triggerSatisfaction_[brainStem_.weapon_training], 0); fired_ = false; } //Fire at player? if (play_) { b2Vec2 myPos = getPosition(); b2Vec2 pPos = player_->getPosition(); b2Vec2 between = (pPos - myPos); float dist = between.Length(); //Fire if in visible range and if (dist < visRange_[brainStem_.sensitivity] && chill_ > freezingPoint_) { rFireV = LJP(pPos, 100, 0, 2.0, 0); //*//Fire LJP const? } } //DECIDE TO FIRE float seePlayer = rFireV.Length(); float ammo = (float)getWeaponBar() / (float)getWeaponBarMAX(); //Otherwise, heat up, chill first if (seePlayer != 0) { orient(rFireV); if (chill_ != 0) chill_ = fminf(chill_ += seePlayer * 4 * moodMult_[brainStem_.aggression], 0); else angry_ = fminf(angry_ + seePlayer * moodMult_[brainStem_.aggression], angryMAX_); } //If we're mad enough and we can see the player, fire if (angry_ > boilingPoint_ && seePlayer != 0) { trigger = true; } //Reload if we're cool enough if (angry_ - boilingPoint_ > (angryMAX_ - boilingPoint_) * accuracy_[brainStem_.weapon_training] * moodMult_[brainStem_.aggression]) //*//weapon training, aggression { if (ammo < accuracy_[brainStem_.weapon_training]) //*// weapon training causes later reloads reup(); } //Chill out when idle if (angry_ == 0 && seePlayer == 0) { chill_ -= 1 * moodMult_[brainStem_.inner_peace]; if (chill_ <= freezingPoint_) { if (ammo < 1.f) reup(); spin(-0.05f); } } chill_ = fmax(chill_, chillMIN_); return trigger; }
// internal function: to avoid exif blob reading + 8-bit byteorder flag + high-quality override int dt_imageio_export_with_flags(const uint32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const int32_t ignore_exif, const int32_t display_byteorder, const gboolean high_quality, const gboolean upscale, const int32_t thumbnail_export, const char *filter, const gboolean copy_metadata, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params, int num, int total) { dt_develop_t dev; dt_dev_init(&dev, 0); dt_dev_load_image(&dev, imgid); const int buf_is_downscaled = (thumbnail_export && dt_conf_get_bool("plugins/lighttable/low_quality_thumbnails")); dt_mipmap_buffer_t buf; if(buf_is_downscaled) dt_mipmap_cache_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_F, DT_MIPMAP_BLOCKING, 'r'); else dt_mipmap_cache_get(darktable.mipmap_cache, &buf, imgid, DT_MIPMAP_FULL, DT_MIPMAP_BLOCKING, 'r'); const dt_image_t *img = &dev.image_storage; if(!buf.buf || !buf.width || !buf.height) { fprintf(stderr, "allocation failed???\n"); dt_control_log(_("image `%s' is not available!"), img->filename); goto error_early; } const int wd = img->width; const int ht = img->height; const float max_scale = upscale ? 100.0 : 1.0; int res = 0; dt_times_t start; dt_get_times(&start); dt_dev_pixelpipe_t pipe; res = thumbnail_export ? dt_dev_pixelpipe_init_thumbnail(&pipe, wd, ht) : dt_dev_pixelpipe_init_export(&pipe, wd, ht, format->levels(format_params)); if(!res) { dt_control_log( _("failed to allocate memory for %s, please lower the threads used for export or buy more memory."), thumbnail_export ? C_("noun", "thumbnail export") : C_("noun", "export")); goto error; } // If a style is to be applied during export, add the iop params into the history if(!thumbnail_export && format_params->style[0] != '\0') { GList *style_items = dt_styles_get_item_list(format_params->style, TRUE, -1); if(!style_items) { dt_control_log(_("cannot find the style '%s' to apply during export."), format_params->style); goto error; } // remove everything above history_end GList *history = g_list_nth(dev.history, dev.history_end); while(history) { GList *next = g_list_next(history); dt_dev_history_item_t *hist = (dt_dev_history_item_t *)(history->data); free(hist->params); free(hist->blend_params); free(history->data); dev.history = g_list_delete_link(dev.history, history); history = next; } // Add each params for(GList *iter = style_items; iter; iter = g_list_next(iter)) { dt_style_item_t *s = (dt_style_item_t *)iter->data; for(GList *module = dev.iop; module; module = g_list_next(module)) { dt_iop_module_t *m = (dt_iop_module_t *)module->data; if(!strcmp(m->op, s->operation)) { dt_dev_history_item_t *h = malloc(sizeof(dt_dev_history_item_t)); dt_iop_module_t *style_module = m; if((format_params->style_append && !(m->flags() & IOP_FLAGS_ONE_INSTANCE)) || m->multi_priority != s->multi_priority) { // dt_dev_module_duplicate() doesn't work here, it's trying too hard to be clever style_module = (dt_iop_module_t *)calloc(1, sizeof(dt_iop_module_t)); if(style_module && !dt_iop_load_module(style_module, m->so, m->dev)) { style_module->instance = m->instance; style_module->multi_priority = s->multi_priority; snprintf(style_module->multi_name, sizeof(style_module->multi_name), "%s", s->name); dev.iop = g_list_insert_sorted(dev.iop, style_module, sort_plugins); } else { free(h); goto error; } } h->params = s->params; h->blend_params = s->blendop_params; h->enabled = s->enabled; h->module = style_module; h->multi_priority = s->multi_priority; g_strlcpy(h->multi_name, s->name, sizeof(h->multi_name)); if(m->legacy_params && (s->module_version != m->version())) { void *new_params = malloc(m->params_size); m->legacy_params(m, h->params, s->module_version, new_params, labs(m->version())); free(h->params); h->params = new_params; } dev.history_end++; dev.history = g_list_append(dev.history, h); // make sure that dt_style_item_free doesn't free data we still use s->params = NULL; s->blendop_params = NULL; break; } } } g_list_free_full(style_items, dt_style_item_free); } dt_dev_pixelpipe_set_icc(&pipe, icc_type, icc_filename, icc_intent); dt_dev_pixelpipe_set_input(&pipe, &dev, (float *)buf.buf, buf.width, buf.height, buf.iscale); dt_dev_pixelpipe_create_nodes(&pipe, &dev); dt_dev_pixelpipe_synch_all(&pipe, &dev); if(filter) { if(!strncmp(filter, "pre:", 4)) dt_dev_pixelpipe_disable_after(&pipe, filter + 4); if(!strncmp(filter, "post:", 5)) dt_dev_pixelpipe_disable_before(&pipe, filter + 5); } dt_dev_pixelpipe_get_dimensions(&pipe, &dev, pipe.iwidth, pipe.iheight, &pipe.processed_width, &pipe.processed_height); dt_show_times(&start, "[export] creating pixelpipe", NULL); // find output color profile for this image: int sRGB = 1; if(icc_type == DT_COLORSPACE_SRGB) { sRGB = 1; } else if(icc_type == DT_COLORSPACE_NONE) { GList *modules = dev.iop; dt_iop_module_t *colorout = NULL; while(modules) { colorout = (dt_iop_module_t *)modules->data; if(colorout->get_p && strcmp(colorout->op, "colorout") == 0) { const dt_colorspaces_color_profile_type_t *type = colorout->get_p(colorout->params, "type"); sRGB = (!type || *type == DT_COLORSPACE_SRGB); break; // colorout can't have > 1 instance } modules = g_list_next(modules); } } else { sRGB = 0; } // get only once at the beginning, in case the user changes it on the way: const gboolean high_quality_processing = ((format_params->max_width == 0 || format_params->max_width >= pipe.processed_width) && (format_params->max_height == 0 || format_params->max_height >= pipe.processed_height)) ? FALSE : high_quality; const int width = format_params->max_width; const int height = format_params->max_height; const double scalex = width > 0 ? fminf(width / (double)pipe.processed_width, max_scale) : 1.0; const double scaley = height > 0 ? fminf(height / (double)pipe.processed_height, max_scale) : 1.0; const double scale = fminf(scalex, scaley); const int processed_width = scale * pipe.processed_width + .5f; const int processed_height = scale * pipe.processed_height + .5f; const int bpp = format->bpp(format_params); dt_get_times(&start); if(high_quality_processing) { /* * if high quality processing was requested, downsampling will be done * at the very end of the pipe (just before border and watermark) */ dt_dev_pixelpipe_process_no_gamma(&pipe, &dev, 0, 0, processed_width, processed_height, scale); } else { // else, downsampling will be right after demosaic // so we need to turn temporarily disable in-pipe late downsampling iop. // find the finalscale module dt_dev_pixelpipe_iop_t *finalscale = NULL; { GList *nodes = g_list_last(pipe.nodes); while(nodes) { dt_dev_pixelpipe_iop_t *node = (dt_dev_pixelpipe_iop_t *)(nodes->data); if(!strcmp(node->module->op, "finalscale")) { finalscale = node; break; } nodes = g_list_previous(nodes); } } if(finalscale) finalscale->enabled = 0; // do the processing (8-bit with special treatment, to make sure we can use openmp further down): if(bpp == 8) dt_dev_pixelpipe_process(&pipe, &dev, 0, 0, processed_width, processed_height, scale); else dt_dev_pixelpipe_process_no_gamma(&pipe, &dev, 0, 0, processed_width, processed_height, scale); if(finalscale) finalscale->enabled = 1; } dt_show_times(&start, thumbnail_export ? "[dev_process_thumbnail] pixel pipeline processing" : "[dev_process_export] pixel pipeline processing", NULL); uint8_t *outbuf = pipe.backbuf; // downconversion to low-precision formats: if(bpp == 8) { if(display_byteorder) { if(high_quality_processing) { const float *const inbuf = (float *)outbuf; for(size_t k = 0; k < (size_t)processed_width * processed_height; k++) { // convert in place, this is unfortunately very serial.. const uint8_t r = CLAMP(inbuf[4 * k + 2] * 0xff, 0, 0xff); const uint8_t g = CLAMP(inbuf[4 * k + 1] * 0xff, 0, 0xff); const uint8_t b = CLAMP(inbuf[4 * k + 0] * 0xff, 0, 0xff); outbuf[4 * k + 0] = r; outbuf[4 * k + 1] = g; outbuf[4 * k + 2] = b; } } // else processing output was 8-bit already, and no need to swap order } else // need to flip { // ldr output: char if(high_quality_processing) { const float *const inbuf = (float *)outbuf; for(size_t k = 0; k < (size_t)processed_width * processed_height; k++) { // convert in place, this is unfortunately very serial.. const uint8_t r = CLAMP(inbuf[4 * k + 0] * 0xff, 0, 0xff); const uint8_t g = CLAMP(inbuf[4 * k + 1] * 0xff, 0, 0xff); const uint8_t b = CLAMP(inbuf[4 * k + 2] * 0xff, 0, 0xff); outbuf[4 * k + 0] = r; outbuf[4 * k + 1] = g; outbuf[4 * k + 2] = b; } } else { // !display_byteorder, need to swap: uint8_t *const buf8 = pipe.backbuf; #ifdef _OPENMP #pragma omp parallel for default(none) schedule(static) #endif // just flip byte order for(size_t k = 0; k < (size_t)processed_width * processed_height; k++) { uint8_t tmp = buf8[4 * k + 0]; buf8[4 * k + 0] = buf8[4 * k + 2]; buf8[4 * k + 2] = tmp; } } } } else if(bpp == 16) { // uint16_t per color channel float *buff = (float *)outbuf; uint16_t *buf16 = (uint16_t *)outbuf; for(int y = 0; y < processed_height; y++) for(int x = 0; x < processed_width; x++) { // convert in place const size_t k = (size_t)processed_width * y + x; for(int i = 0; i < 3; i++) buf16[4 * k + i] = CLAMP(buff[4 * k + i] * 0x10000, 0, 0xffff); } } // else output float, no further harm done to the pixels :) format_params->width = processed_width; format_params->height = processed_height; if(!ignore_exif) { int length; uint8_t *exif_profile = NULL; // Exif data should be 65536 bytes max, but if original size is close to that, // adding new tags could make it go over that... so let it be and see what // happens when we write the image char pathname[PATH_MAX] = { 0 }; gboolean from_cache = TRUE; dt_image_full_path(imgid, pathname, sizeof(pathname), &from_cache); // last param is dng mode, it's false here length = dt_exif_read_blob(&exif_profile, pathname, imgid, sRGB, processed_width, processed_height, 0); res = format->write_image(format_params, filename, outbuf, icc_type, icc_filename, exif_profile, length, imgid, num, total); free(exif_profile); } else { res = format->write_image(format_params, filename, outbuf, icc_type, icc_filename, NULL, 0, imgid, num, total); } dt_dev_pixelpipe_cleanup(&pipe); dt_dev_cleanup(&dev); dt_mipmap_cache_release(darktable.mipmap_cache, &buf); /* now write xmp into that container, if possible */ if(copy_metadata && (format->flags(format_params) & FORMAT_FLAGS_SUPPORT_XMP)) { dt_exif_xmp_attach(imgid, filename); // no need to cancel the export if this fail } if(!thumbnail_export && strcmp(format->mime(format_params), "memory") && !(format->flags(format_params) & FORMAT_FLAGS_NO_TMPFILE)) { #ifdef USE_LUA //Synchronous calling of lua intermediate-export-image events dt_lua_lock(); lua_State *L = darktable.lua_state.state; luaA_push(L, dt_lua_image_t, &imgid); lua_pushstring(L, filename); luaA_push_type(L, format->parameter_lua_type, format_params); if (storage) luaA_push_type(L, storage->parameter_lua_type, storage_params); else lua_pushnil(L); dt_lua_event_trigger(L, "intermediate-export-image", 4); dt_lua_unlock(); #endif dt_control_signal_raise(darktable.signals, DT_SIGNAL_IMAGE_EXPORT_TMPFILE, imgid, filename, format, format_params, storage, storage_params); } return res; error: dt_dev_pixelpipe_cleanup(&pipe); error_early: dt_dev_cleanup(&dev); dt_mipmap_cache_release(darktable.mipmap_cache, &buf); return 1; }