static void inline fxHorizontalFoldsModelStepObject(CompWindow * w, Model * model, Object * object, float forwardProgress, float sinForProg, float foldMaxAmp, int rowNo) { ANIM_WINDOW(w); float origx = w->attrib.x + (WIN_W(w) * object->gridPosition.x - w->output.left) * model->scale.x; float origy = w->attrib.y + (WIN_H(w) * object->gridPosition.y - w->output.top) * model->scale.y; object->position.x = origx; if (aw->com.curWindowEvent == WindowEventShade || aw->com.curWindowEvent == WindowEventUnshade) { // Execute shade mode float relDistToFoldCenter = (rowNo % 2 == 1 ? 0.5 : 0); if (object->gridPosition.y == 0) { object->position.y = WIN_Y(w); object->position.z = 0; } else if (object->gridPosition.y == 1) { object->position.y = (1 - forwardProgress) * origy + forwardProgress * (WIN_Y(w) + model->topHeight + model->bottomHeight); object->position.z = 0; } else { object->position.y = (1 - forwardProgress) * origy + forwardProgress * (WIN_Y(w) + model->topHeight); object->position.z = getObjectZ(model, forwardProgress, sinForProg, relDistToFoldCenter, foldMaxAmp); } } else { // Execute normal mode float relDistToFoldCenter; relDistToFoldCenter = (rowNo % 2 == 0 ? 0.5 : 0); object->position.y = (1 - forwardProgress) * origy + forwardProgress * (BORDER_Y(w) + BORDER_H(w) / 2.0); object->position.z = getObjectZ(model, forwardProgress, sinForProg, relDistToFoldCenter, foldMaxAmp); } }
void fxHorizontalFoldsModelStep(CompWindow * w, float time) { defaultAnimStep(w, time); ANIM_WINDOW(w); Model *model = aw->com.model; float winHeight = 0; if (aw->com.curWindowEvent == WindowEventShade || aw->com.curWindowEvent == WindowEventUnshade) { winHeight = (w)->height; } else { winHeight = BORDER_H(w); } int nHalfFolds = 2.0 * animGetI(w, ANIM_SCREEN_OPTION_HORIZONTAL_FOLDS_NUM_FOLDS); float foldMaxAmp = 0.3 * pow((winHeight / nHalfFolds) / w->screen->height, 0.3) * animGetF(w, ANIM_SCREEN_OPTION_HORIZONTAL_FOLDS_AMP_MULT); float forwardProgress = getProgressAndCenter(w, NULL); float sinForProg = sin(forwardProgress * M_PI / 2); Object *object = model->objects; int i; for (i = 0; i < model->numObjects; i++, object++) fxHorizontalFoldsModelStepObject(w, model, object, forwardProgress, sinForProg, foldMaxAmp, i / model->gridWidth); }
Bool fxDominoInit (CompWindow * w) { if (!polygonsAnimInit (w)) return FALSE; ANIMADDON_DISPLAY (w->screen->display); ANIMADDON_WINDOW (w); Bool isRazr = (aw->com->curAnimEffect == AnimEffectRazr); int fallDir; if (isRazr) fallDir = ad->animBaseFunctions->getActualAnimDirection (w, animGetI (w, ANIMADDON_SCREEN_OPTION_RAZR_DIRECTION), TRUE); else fallDir = ad->animBaseFunctions->getActualAnimDirection (w, animGetI (w, ANIMADDON_SCREEN_OPTION_DOMINO_DIRECTION), TRUE); int defaultGridSize = 20; float minCellSize = 30; int gridSizeX; int gridSizeY; int fallDirGridSize; float minDistStartEdge; // half piece size in [0,1] range float gridCellW; float gridCellH; float cellAspectRatio = 1.25; if (isRazr) cellAspectRatio = 1; // Determine sensible domino piece sizes if (fallDir == AnimDirectionDown || fallDir == AnimDirectionUp) { if (minCellSize > BORDER_W(w)) minCellSize = BORDER_W(w); if (BORDER_W(w) / defaultGridSize < minCellSize) gridSizeX = (int)(BORDER_W(w) / minCellSize); else gridSizeX = defaultGridSize; gridCellW = BORDER_W(w) / gridSizeX; gridSizeY = (int)(BORDER_H(w) / (gridCellW * cellAspectRatio)); if (gridSizeY == 0) gridSizeY = 1; gridCellH = BORDER_H(w) / gridSizeY; fallDirGridSize = gridSizeY; } else { if (minCellSize > BORDER_H(w)) minCellSize = BORDER_H(w); if (BORDER_H(w) / defaultGridSize < minCellSize) gridSizeY = (int)(BORDER_H(w) / minCellSize); else gridSizeY = defaultGridSize; gridCellH = BORDER_H(w) / gridSizeY; gridSizeX = (int)(BORDER_W(w) / (gridCellH * cellAspectRatio)); if (gridSizeX == 0) gridSizeX = 1; gridCellW = BORDER_W(w) / gridSizeX; fallDirGridSize = gridSizeX; } minDistStartEdge = (1.0 / fallDirGridSize) / 2; float thickness = MIN(gridCellW, gridCellH) / 3.5; if (!tessellateIntoRectangles(w, gridSizeX, gridSizeY, thickness)) return FALSE; float rotAxisX = 0; float rotAxisY = 0; Point3d rotAxisOff = { 0, 0, thickness / 2 }; float posX = 0; // position of standing piece float posY = 0; float posZ = 0; int nFallingColumns = gridSizeX; float gridCellHalfW = gridCellW / 2; float gridCellHalfH = gridCellH / 2; switch (fallDir) { case AnimDirectionDown: rotAxisX = -1; if (isRazr) rotAxisOff.y = -gridCellHalfH; else { posY = -(gridCellHalfH + thickness); posZ = gridCellHalfH - thickness / 2; } break; case AnimDirectionLeft: rotAxisY = -1; if (isRazr) rotAxisOff.x = gridCellHalfW; else { posX = gridCellHalfW + thickness; posZ = gridCellHalfW - thickness / 2; } nFallingColumns = gridSizeY; break; case AnimDirectionUp: rotAxisX = 1; if (isRazr) rotAxisOff.y = gridCellHalfH; else { posY = gridCellHalfH + thickness; posZ = gridCellHalfH - thickness / 2; } break; case AnimDirectionRight: rotAxisY = 1; if (isRazr) rotAxisOff.x = -gridCellHalfW; else { posX = -(gridCellHalfW + thickness); posZ = gridCellHalfW - thickness / 2; } nFallingColumns = gridSizeY; break; } float fadeDuration; float riseDuration; float riseTimeRandMax = 0.2; if (isRazr) { riseDuration = (1 - riseTimeRandMax) / fallDirGridSize; fadeDuration = riseDuration / 2; } else { fadeDuration = 0.18; riseDuration = 0.2; } float *riseTimeRandSeed = calloc(nFallingColumns, sizeof(float)); if (!riseTimeRandSeed) // TODO: log error here return FALSE; int i; for (i = 0; i < nFallingColumns; i++) riseTimeRandSeed[i] = RAND_FLOAT(); PolygonSet *pset = aw->eng.polygonSet; PolygonObject *p = pset->polygons; for (i = 0; i < pset->nPolygons; i++, p++) { p->rotAxis.x = rotAxisX; p->rotAxis.y = rotAxisY; p->rotAxis.z = 0; p->finalRelPos.x = posX; p->finalRelPos.y = posY; p->finalRelPos.z = posZ; // dist. from rise-start / fall-end edge in window ([0,1] range) float distStartEdge = 0; // dist. from edge perpendicular to movement (for move start time) // so that same the blocks in same row/col. appear to knock down // the next one float distPerpEdge = 0; switch (fallDir) { case AnimDirectionUp: distStartEdge = p->centerRelPos.y; distPerpEdge = p->centerRelPos.x; break; case AnimDirectionRight: distStartEdge = 1 - p->centerRelPos.x; distPerpEdge = p->centerRelPos.y; break; case AnimDirectionDown: distStartEdge = 1 - p->centerRelPos.y; distPerpEdge = p->centerRelPos.x; break; case AnimDirectionLeft: distStartEdge = p->centerRelPos.x; distPerpEdge = p->centerRelPos.y; break; } float riseTimeRand = riseTimeRandSeed[(int)(distPerpEdge * nFallingColumns)] * riseTimeRandMax; p->moveDuration = riseDuration; float mult = 1; if (fallDirGridSize > 1) mult = ((distStartEdge - minDistStartEdge) / (1 - 2 * minDistStartEdge)); if (isRazr) { p->moveStartTime = mult * (1 - riseDuration - riseTimeRandMax) + riseTimeRand; p->fadeStartTime = p->moveStartTime + riseDuration / 2; p->finalRotAng = -180; p->rotAxisOffset.x = rotAxisOff.x; p->rotAxisOffset.y = rotAxisOff.y; p->rotAxisOffset.z = rotAxisOff.z; } else { p->moveStartTime = mult * (1 - riseDuration - riseTimeRandMax) + riseTimeRand; p->fadeStartTime = p->moveStartTime + riseDuration - riseTimeRand + 0.03; p->finalRotAng = -90; } if (p->fadeStartTime > 1 - fadeDuration) p->fadeStartTime = 1 - fadeDuration; p->fadeDuration = fadeDuration; } free(riseTimeRandSeed); pset->doDepthTest = TRUE; pset->doLighting = TRUE; pset->correctPerspective = CorrectPerspectivePolygon; aw->com->animTotalTime /= DOMINO_PERCEIVED_T; aw->com->animRemainingTime = aw->com->animTotalTime; return TRUE; }
// Divide the window in 8 polygons (6 quadrilaters and 2 triangles (all of them draw as quadrilaters)) // Based on tessellateIntoRectangles and tessellateIntoHexagons. Improperly called tessellation. static Bool tessellateIntoAirplane (CompWindow * w) { ANIMADDON_WINDOW (w); PolygonSet *pset = aw->eng.polygonSet; if (!pset) return FALSE; float winLimitsX; // boundaries of polygon tessellation float winLimitsY; float winLimitsW; float winLimitsH; winLimitsX = BORDER_X (w); winLimitsY = BORDER_Y (w); winLimitsW = BORDER_W (w); winLimitsH = BORDER_H (w); int numpol = 8; if (pset->nPolygons != numpol) { if (pset->nPolygons > 0) freePolygonObjects (pset); pset->nPolygons = numpol; pset->polygons = calloc (pset->nPolygons, sizeof (PolygonObject)); if (!pset->polygons) { compLogMessage ("animationaddon", CompLogLevelError, "Not enough memory"); pset->nPolygons = 0; return FALSE; } } float thickness = 0; thickness /= w->screen->width; pset->thickness = thickness; pset->nTotalFrontVertices = 0; float W = (float)winLimitsW; float H2 = (float)winLimitsH / 2; float H3 = (float)winLimitsH / 3; float H6 = (float)winLimitsH / 6; float halfThick = pset->thickness / 2; /** * * These correspond to the polygons: * based on GLUT sample origami.c code by Mark J. Kilgard * * |- W -| * |- H2 -| * * - -- +----+--------+------------------+ * | | | / | * | | 6 / | * | 7 | / 5 | * H2 | | + | * | +--------+------------------+ * | / 4 | * H __ |/____________.__________________| * |\ center | * | \ 3 | * | +--------+------------------+ * | | + | * | 0 | \ | * | | 1 \ 2 | * | | | \ | * - +----+--------+------------------+ * * */ PolygonObject *p = pset->polygons; int i; for (i = 0; i < 8; i++, p++) { float topRightY, topLeftY, bottomLeftY, bottomRightY; float topLeftX, topRightX, bottomLeftX, bottomRightX; p->centerPos.x = p->centerPosStart.x = winLimitsX + H2; p->centerPos.y = p->centerPosStart.y = winLimitsY + H2; p->centerPos.z = p->centerPosStart.z = -halfThick; p->rotAngle = p->rotAngleStart = 0; p->nSides = 4; p->nVertices = 2 * 4; pset->nTotalFrontVertices += 4; switch (i) { case 0: topLeftX = -H2; topLeftY = 0; bottomLeftX = -H2; bottomLeftY = H2; bottomRightX = -H3; bottomRightY = H2; topRightX = -H3; topRightY = H6; break; case 1: topLeftX = -H3; topLeftY = H6; bottomLeftX = -H3; bottomLeftY = H2; bottomRightX = 0; bottomRightY = H2; topRightX = 0; topRightY = H2; break; case 2: topLeftX = -H3; topLeftY = H6; bottomLeftX = 0; bottomLeftY = H2; bottomRightX = W - H2; bottomRightY = H2; topRightX = W - H2; topRightY = H6; break; case 3: topLeftX = -H2; topLeftY = 0; bottomLeftX = -H3; bottomLeftY = H6; bottomRightX = W - H2; bottomRightY = H6; topRightX = W - H2; topRightY = 0; break; case 4: topLeftX = -H3; topLeftY = -H6; bottomLeftX = -H2; bottomLeftY = 0; bottomRightX = W - H2; bottomRightY = 0; topRightX = W - H2; topRightY = -H6; break; case 5: topLeftX = 0; topLeftY = -H2; bottomLeftX = -H3; bottomLeftY = -H6; bottomRightX = W - H2; bottomRightY = -H6; topRightX = W - H2; topRightY = -H2; break; case 6: topLeftX = -H3; topLeftY = -H2; bottomLeftX = -H3; bottomLeftY = -H6; bottomRightX = -H3; bottomRightY = -H6; topRightX = 0; topRightY = -H2; break; default: topLeftX = -H2; topLeftY = -H2; bottomLeftX = -H2; bottomLeftY = 0; bottomRightX = -H3; bottomRightY = -H6; topRightX = -H3; topRightY = -H2; break; } // 4 front, 4 back vertices if (!p->vertices) { p->vertices = calloc (8 * 3, sizeof (GLfloat)); } if (!p->vertices) { compLogMessage ("animation", CompLogLevelError, "Not enough memory"); freePolygonObjects (pset); return FALSE; } GLfloat *pv = p->vertices; // Determine 4 front vertices in ccw direction pv[0] = topLeftX; pv[1] = topLeftY; pv[2] = halfThick; pv[3] = bottomLeftX; pv[4] = bottomLeftY; pv[5] = halfThick; pv[6] = bottomRightX; pv[7] = bottomRightY; pv[8] = halfThick; pv[9] = topRightX; pv[10] = topRightY; pv[11] = halfThick; // Determine 4 back vertices in cw direction pv[12] = topRightX; pv[13] = topRightY; pv[14] = -halfThick; pv[15] = bottomRightX; pv[16] = bottomRightY; pv[17] = -halfThick; pv[18] = bottomLeftX; pv[19] = bottomLeftY; pv[20] = -halfThick; pv[21] = topLeftX; pv[22] = topLeftY; pv[23] = -halfThick; // 16 indices for 4 sides (for quad strip) if (!p->sideIndices) { p->sideIndices = calloc (4 * 4, sizeof (GLushort)); } if (!p->sideIndices) { compLogMessage ("animation", CompLogLevelError, "Not enough memory"); freePolygonObjects (pset); return FALSE; } GLushort *ind = p->sideIndices; int id = 0; ind[id++] = 0; ind[id++] = 7; ind[id++] = 6; ind[id++] = 1; ind[id++] = 1; ind[id++] = 6; ind[id++] = 5; ind[id++] = 2; ind[id++] = 2; ind[id++] = 5; ind[id++] = 4; ind[id++] = 3; ind[id++] = 3; ind[id++] = 4; ind[id++] = 7; ind[id++] = 0; if (i < 4) { p->boundingBox.x1 = p->centerPos.x + topLeftX; p->boundingBox.y1 = p->centerPos.y + topLeftY; p->boundingBox.x2 = ceil (p->centerPos.x + bottomRightX); p->boundingBox.y2 = ceil (p->centerPos.y + bottomRightY); } else { p->boundingBox.x1 = p->centerPos.x + bottomLeftX; p->boundingBox.y1 = p->centerPos.y + topLeftY; p->boundingBox.x2 = ceil (p->centerPos.x + bottomRightX); p->boundingBox.y2 = ceil (p->centerPos.y + bottomLeftY); } } return TRUE; }
Bool fxAirplaneInit (CompWindow * w) { if (!polygonsAnimInit (w)) return FALSE; if (!tessellateIntoAirplane (w)) return FALSE; ANIMADDON_WINDOW (w); float airplanePathLength = animGetF (w, ANIMADDON_SCREEN_OPTION_AIRPLANE_PATHLENGTH); PolygonSet *pset = aw->eng.polygonSet; PolygonObject *p = pset->polygons; float winLimitsW; // boundaries of polygon tessellation float winLimitsH; winLimitsW = BORDER_W (w); winLimitsH = BORDER_H (w); float H4 = (float)winLimitsH / 4; float H6 = (float)winLimitsH / 6; int i; for (i = 0; i < pset->nPolygons; i++, p++) { if (!p->effectParameters) { p->effectParameters = calloc (1, sizeof (AirplaneEffectParameters)); } if (!p->effectParameters) { compLogMessage ("animation", CompLogLevelError, "Not enough memory"); return FALSE; } AirplaneEffectParameters *aep = p->effectParameters; p->moveStartTime = 0.00; p->moveDuration = 0.19; aep->moveStartTime2 = 0.19; aep->moveDuration2 = 0.19; aep->moveStartTime3 = 0.38; aep->moveDuration3 = 0.19; aep->moveStartTime4 = 0.58; aep->moveDuration4 = 0.09; aep->moveDuration5 = 0.41; aep->flyFinalRotation.x = 90; aep->flyFinalRotation.y = 10; aep->flyTheta = 0; aep->centerPosFly.x = 0; aep->centerPosFly.y = 0; aep->centerPosFly.z = 0; aep->flyScale = 0; aep->flyFinalScale = 6 * (winLimitsW / (w->screen->width / 2)); switch (i) { case 0: p->rotAxisOffset.x = -H4; p->rotAxisOffset.y = H4; p->rotAxis.x = 1.00; p->rotAxis.y = 1.00; p->rotAxis.z = 0.00; p->finalRotAng = 179.5; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = 84; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = 0; aep->rotAxisB.x = 0.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = 0; break; case 1: p->rotAxisOffset.x = -H4; p->rotAxisOffset.y = H4; p->rotAxis.x = 1.00; p->rotAxis.y = 1.00; p->rotAxis.z = 0.00; p->finalRotAng = 179.5; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = 84; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = H6; aep->rotAxisB.x = 1.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = -84; break; case 2: p->moveDuration = 0.00; p->rotAxisOffset.x = 0; p->rotAxisOffset.y = 0; p->rotAxis.x = 0.00; p->rotAxis.y = 0.00; p->rotAxis.z = 0.00; p->finalRotAng = 0; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = 84; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = H6; aep->rotAxisB.x = 1.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = -84; break; case 3: p->moveDuration = 0.00; p->rotAxisOffset.x = 0; p->rotAxisOffset.y = 0; p->rotAxis.x = 0.00; p->rotAxis.y = 0.00; p->rotAxis.z = 0.00; p->finalRotAng = 0; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = 84; aep->moveDuration3 = 0.00; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = 0; aep->rotAxisB.x = 0.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = 0; break; case 4: p->moveDuration = 0.00; p->rotAxisOffset.x = 0; p->rotAxisOffset.y = 0; p->rotAxis.x = 0.00; p->rotAxis.y = 0.00; p->rotAxis.z = 0.00; p->finalRotAng = 0; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = -84; aep->moveDuration3 = 0.00; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = 0; aep->rotAxisB.x = 0.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = 0; break; case 5: p->moveDuration = 0.00; p->rotAxisOffset.x = 0; p->rotAxisOffset.y = 0; p->rotAxis.x = 0.00; p->rotAxis.y = 0.00; p->rotAxis.z = 0.00; p->finalRotAng = 0; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = -84; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = -H6; aep->rotAxisB.x = 1.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = 84; break; case 6: p->rotAxisOffset.x = -H4; p->rotAxisOffset.y = -H4; p->rotAxis.x = 1.00; p->rotAxis.y = -1.00; p->rotAxis.z = 0.00; p->finalRotAng = -179.5; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = -84; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = -H6; aep->rotAxisB.x = 1.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = 84; break; case 7: p->rotAxisOffset.x = -H4; p->rotAxisOffset.y = -H4; p->rotAxis.x = 1.00; p->rotAxis.y = -1.00; p->rotAxis.z = 0.00; p->finalRotAng = -179.5; aep->rotAxisOffsetA.x = 0; aep->rotAxisOffsetA.y = 0; aep->rotAxisA.x = 1.00; aep->rotAxisA.y = 0.00; aep->rotAxisA.z = 0.00; aep->finalRotAngA = -84; aep->rotAxisOffsetB.x = 0; aep->rotAxisOffsetB.y = 0; aep->rotAxisB.x = 0.00; aep->rotAxisB.y = 0.00; aep->rotAxisB.z = 0.00; aep->finalRotAngB = 0; break; } } if (airplanePathLength >= 1) pset->allFadeDuration = 0.30f / airplanePathLength; else pset->allFadeDuration = 0.30f; pset->doDepthTest = TRUE; pset->doLighting = TRUE; pset->correctPerspective = CorrectPerspectivePolygon; pset->extraPolygonTransformFunc = &AirplaneExtraPolygonTransformFunc; // Duration extension aw->com->animTotalTime *= 2 + airplanePathLength; aw->com->animRemainingTime = aw->com->animTotalTime; return TRUE; }
static void fxCurvedFoldModelStepObject(CompWindow *w, Model *model, Object *object, float forwardProgress, float curveMaxAmp) { ANIM_WINDOW(w); float origx = w->attrib.x + (WIN_W(w) * object->gridPosition.x - w->output.left) * model->scale.x; float origy = w->attrib.y + (WIN_H(w) * object->gridPosition.y - w->output.top) * model->scale.y; if (aw->curWindowEvent == WindowEventShade || aw->curWindowEvent == WindowEventUnshade) { // Execute shade mode // find position in window contents // (window contents correspond to 0.0-1.0 range) float relPosInWinContents = (object->gridPosition.y * WIN_H(w) - model->topHeight) / w->height; float relDistToCenter = fabs(relPosInWinContents - 0.5); if (object->gridPosition.y == 0) { object->position.x = origx; object->position.y = WIN_Y(w); } else if (object->gridPosition.y == 1) { object->position.x = origx; object->position.y = (1 - forwardProgress) * origy + forwardProgress * (WIN_Y(w) + model->topHeight + model->bottomHeight); } else { object->position.x = origx + sin(forwardProgress * M_PI / 2) * (0.5 - object->gridPosition.x) * 2 * model->scale.x * curveMaxAmp * (1 - pow (pow(2 * relDistToCenter, 1.3), 2)); object->position.y = (1 - forwardProgress) * origy + forwardProgress * (WIN_Y(w) + model->topHeight); } } else { // Execute normal mode // find position within window borders // (border contents correspond to 0.0-1.0 range) float relPosInWinBorders = (object->gridPosition.y * WIN_H(w) - (w->output.top - w->input.top)) / BORDER_H(w); float relDistToCenter = fabs(relPosInWinBorders - 0.5); // prevent top & bottom shadows from extending too much if (relDistToCenter > 0.5) relDistToCenter = 0.5; object->position.x = origx + sin(forwardProgress * M_PI / 2) * (0.5 - object->gridPosition.x) * 2 * model->scale.x * curveMaxAmp * (1 - pow (pow(2 * relDistToCenter, 1.3), 2)); object->position.y = (1 - forwardProgress) * origy + forwardProgress * (BORDER_Y(w) + BORDER_H(w) / 2.0); } }
void fxFoldAnimStepPolygon (CompWindow *w, PolygonObject *p, float forwardProgress) { const BananaValue * option_fold_gridx = bananaGetOption (bananaIndex, "fold_gridx", w->screen->screenNum); const BananaValue * option_fold_gridy = bananaGetOption (bananaIndex, "fold_gridy", w->screen->screenNum); const BananaValue * option_fold_dir = bananaGetOption (bananaIndex, "fold_dir", w->screen->screenNum); int dir = option_fold_dir->i == 0 ? 1 : -1; int gridSizeX = option_fold_gridx->i; int gridSizeY = option_fold_gridy->i; float moveProgress = forwardProgress - p->moveStartTime; if (p->moveDuration > 0) moveProgress /= p->moveDuration; if (moveProgress < 0) moveProgress = 0; else if (moveProgress > 1) moveProgress = 1; float const_x = BORDER_W (w) / (float)gridSizeX; // width of single piece float const_y = BORDER_H (w) / (float)gridSizeY; // height of single piece p->rotAngle = dir * moveProgress * p->finalRotAng; if (p->rotAxis.x == 180) { if (p->finalRelPos.y == gridSizeY - 2) { // it means the last row p->centerPos.y = p->centerPosStart.y + const_y / 2.0f - cos (p->rotAngle * M_PI / 180.0f) * const_y / 2.0f; p->centerPos.z = p->centerPosStart.z + 1.0f / w->screen->width * (sin (-p->rotAngle * M_PI / 180.0f) * const_y / 2.0f); } else { // rows if (fabs (p->rotAngle) < 90) { // 1. rotate 90 p->centerPos.y = p->centerPosStart.y + const_y / 2.0f - cos (p->rotAngle * M_PI / 180.0f) * const_y / 2.0f; p->centerPos.z = p->centerPosStart.z + 1.0f / w->screen->width * (sin (-p->rotAngle * M_PI / 180.0f) * const_y / 2.0f); } else { // 2. rotate faster 180 float alpha = p->rotAngle - dir * 90; // [0 - 45] float alpha2 = 2 * alpha; // [0 - 90] p->rotAngle = (p->rotAngle - dir * 90) * 2 + dir * 90; p->centerPos.y = p->centerPosStart.y + const_y / 2.0f + const_y - cos (alpha * M_PI / 180.0f) * const_y + dir * sin (alpha2 * M_PI / 180.0f) * const_y / 2.0f; p->centerPos.z = p->centerPosStart.z + 1.0f / w->screen->width * (-sin (alpha * M_PI / 180.0f) * const_y - dir * cos (alpha2 * M_PI / 180.0f) * const_y / 2.0f); } } } else if (p->rotAxis.y == -180) { // simple blocks left p->centerPos.x = p->centerPosStart.x + const_x / 2.0f - cos (p->rotAngle * M_PI / 180.0f) * const_x / 2.0f; p->centerPos.z = p->centerPosStart.z - 1.0f / w->screen->width * (sin (p->rotAngle * M_PI / 180.0f) * const_x / 2.0f); } else if (p->rotAxis.y == 180) { // simple blocks right p->centerPos.x = p->centerPosStart.x - const_x / 2.0f + cos (-p->rotAngle * M_PI / 180.0f) * const_x / 2.0f; p->centerPos.z = p->centerPosStart.z + 1.0f / w->screen->width * (sin (-p->rotAngle * M_PI / 180.0f) * const_x / 2.0f); } }