CompRegion CompRegion::xored (const CompRegion &r) const { CompRegion rv; rv.priv->makeReal (); XXorRegion (handle (), r.handle (), rv.handle ()); return rv; }
CompRegion CompRegion::united (const CompRect &r) const { CompRegion rv; rv.priv->makeReal (); XUnionRegion (handle (), r.region (), rv.handle ()); return rv; }
CompRegion CompRegion::subtracted (const CompRect &r) const { CompRegion rv; rv.priv->makeReal (); XSubtractRegion (handle (), r.region (), rv.handle ()); return rv; }
CompRegion CompRegion::intersected (const CompRect &r) const { CompRegion reg (r); reg.priv->makeReal (); XIntersectRegion (reg.handle (), handle (), reg.handle ()); return reg; }
bool GLScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib, const GLMatrix &transform, const CompRegion ®ion, CompOutput *output, unsigned int mask) { WRAPABLE_HND_FUNCTN_RETURN (bool, glPaintOutput, sAttrib, transform, region, output, mask) GLMatrix sTransform = transform; if (mask & PAINT_SCREEN_REGION_MASK) { if (mask & PAINT_SCREEN_TRANSFORMED_MASK) { if (mask & PAINT_SCREEN_FULL_MASK) { glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output), output, mask); return true; } return false; } setLighting (false); sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); /* * Sometimes region might be empty but we still need to force the * repaint. This can happen when a fullscreen window is unredirected, * and damageScreen is called. CompositeScreen::handlePaintTimeout * then subtracts the whole screen of damage because it's an overlay * and we're left with an empty damage region. * Even when this happens we may want to force the repaint if * windows are getting transformed (and so the unredirected window * needs to be redirected again). */ if (!region.isEmpty () || (mask & PAINT_SCREEN_FULL_MASK) || (mask & PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK)) priv->paintOutputRegion (sTransform, region, output, mask); return true; } else if (mask & PAINT_SCREEN_FULL_MASK) { glPaintTransformedOutput (sAttrib, sTransform, CompRegion (*output), output, mask); return true; } else { return false; } }
bool ShowrepaintScreen::glPaintOutput (const GLScreenPaintAttrib &attrib, const GLMatrix &transform, const CompRegion ®ion, CompOutput *output, unsigned int mask) { bool status; GLMatrix sTransform; // initially identity matrix unsigned short color[4]; status = gScreen->glPaintOutput (attrib, transform, region, output, mask); tmpRegion = region.intersected (*output); if (tmpRegion.isEmpty ()) return status; sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); color[3] = optionGetIntensity () * 0xffff / 100; color[0] = (rand () & 7) * color[3] / 8; color[1] = (rand () & 7) * color[3] / 8; color[2] = (rand () & 7) * color[3] / 8; glColor4usv (color); glPushMatrix (); glLoadMatrixf (sTransform.getMatrix ()); glEnable (GL_BLEND); glBegin (GL_QUADS); foreach (const CompRect &box, tmpRegion.rects ()) { glVertex2i (box.x1 (), box.y1 ()); glVertex2i (box.x1 (), box.y2 ()); glVertex2i (box.x2 (), box.y2 ()); glVertex2i (box.x2 (), box.y1 ()); } glEnd (); glDisable (GL_BLEND); glPopMatrix(); glColor4usv (defaultColor); return status; }
CompPoint compiz::wall::movementWindowOnScreen (const CompRect &serverBorderRect, const CompRegion &screenRegion) { CompRegion sbrRegion (serverBorderRect); /* If the window would be partially offscreen * after it was moved then we should move it back * so that it is completely onscreen, since we moved * from mostly offscreen on B to mostly onscreen on A, * the user should be able to see their selected window */ CompRegion inter = sbrRegion.intersected (screenRegion); CompRegion rem = sbrRegion - screenRegion; int dx = 0; int dy = 0; const CompRect::vector &rects (rem.rects ()); for (std::vector <CompRect>::const_iterator it = rects.begin (); it != rects.end (); ++it) { const CompRect &r = *it; if (r.x1 () >= inter.boundingRect ().x2 ()) dx -= r.width (); else if (r.x2 () <= inter.boundingRect ().x1 ()) dx += r.width (); if (r.y1 () >= inter.boundingRect ().y2 ()) dy -= r.height (); else if (r.y2 () <= inter.boundingRect ().y1 ()) dy += r.height (); } return CompPoint (dx, dy); }
void GLWindow::glAddGeometry (const GLTexture::MatrixList &matrix, const CompRegion ®ion, const CompRegion &clip, unsigned int maxGridWidth, unsigned int maxGridHeight) { WRAPABLE_HND_FUNCTN (glAddGeometry, matrix, region, clip) BoxRec full; int nMatrix = matrix.size (); full = clip.handle ()->extents; if (region.handle ()->extents.x1 > full.x1) full.x1 = region.handle ()->extents.x1; if (region.handle ()->extents.y1 > full.y1) full.y1 = region.handle ()->extents.y1; if (region.handle ()->extents.x2 < full.x2) full.x2 = region.handle ()->extents.x2; if (region.handle ()->extents.y2 < full.y2) full.y2 = region.handle ()->extents.y2; if (full.x1 < full.x2 && full.y1 < full.y2) { BoxPtr pBox; int nBox; BoxPtr pClip; int nClip; BoxRec cbox; int it, x1, y1, x2, y2; bool rect = true; for (it = 0; it < nMatrix; it++) { if (matrix[it].xy != 0.0f || matrix[it].yx != 0.0f) { rect = false; break; } } pBox = const_cast <Region> (region.handle ())->rects; nBox = const_cast <Region> (region.handle ())->numRects; while (nBox--) { x1 = pBox->x1; y1 = pBox->y1; x2 = pBox->x2; y2 = pBox->y2; pBox++; if (x1 < full.x1) x1 = full.x1; if (y1 < full.y1) y1 = full.y1; if (x2 > full.x2) x2 = full.x2; if (y2 > full.y2) y2 = full.y2; if (x1 < x2 && y1 < y2) { nClip = const_cast <Region> (clip.handle ())->numRects; if (nClip == 1) { addQuads (priv->vertexBuffer, matrix, nMatrix, x1, y1, x2, y2, rect, maxGridWidth, maxGridHeight); } else { pClip = const_cast <Region> (clip.handle ())->rects; while (nClip--) { cbox = *pClip; pClip++; if (cbox.x1 < x1) cbox.x1 = x1; if (cbox.y1 < y1) cbox.y1 = y1; if (cbox.x2 > x2) cbox.x2 = x2; if (cbox.y2 > y2) cbox.y2 = y2; if (cbox.x1 < cbox.x2 && cbox.y1 < cbox.y2) { addQuads (priv->vertexBuffer, matrix, nMatrix, cbox.x1, cbox.y1, cbox.x2, cbox.y2, rect, maxGridWidth, maxGridHeight); } } } } } } }
void PrivateGLScreen::paintBackground (const GLMatrix &transform, const CompRegion ®ion, bool transformed) { GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer (); GLfloat vertexData[18]; GLushort colorData[4]; BoxPtr pBox = const_cast <Region> (region.handle ())->rects; int n, nBox = const_cast <Region> (region.handle ())->numRects; if (!nBox) return; if (screen->desktopWindowCount ()) { if (!backgroundTextures.empty ()) { backgroundTextures.clear (); } backgroundLoaded = false; return; } else { if (!backgroundLoaded) updateScreenBackground (); backgroundLoaded = true; } if (backgroundTextures.empty ()) { streamingBuffer->begin (GL_TRIANGLES); n = nBox; while (n--) { vertexData[0] = pBox->x1; vertexData[1] = pBox->y1; vertexData[2] = 0.0f; vertexData[3] = pBox->x1; vertexData[4] = pBox->y2; vertexData[5] = 0.0f; vertexData[6] = pBox->x2; vertexData[7] = pBox->y1; vertexData[8] = 0.0f; vertexData[9] = pBox->x1; vertexData[10] = pBox->y2; vertexData[11] = 0.0f; vertexData[12] = pBox->x2; vertexData[13] = pBox->y2; vertexData[14] = 0.0f; vertexData[15] = pBox->x2; vertexData[16] = pBox->y1; vertexData[17] = 0.0f; streamingBuffer->addVertices (6, vertexData); pBox++; } colorData[0] = colorData[1] = colorData[2] = 0; colorData[3] = std::numeric_limits <unsigned short>::max (); streamingBuffer->addColors (1, colorData); streamingBuffer->end (); streamingBuffer->render (transform); } else { n = nBox; for (unsigned int i = 0; i < backgroundTextures.size (); i++) { GLfloat textureData[12]; GLTexture *bg = backgroundTextures[i]; CompRegion r = region & *bg; pBox = const_cast <Region> (r.handle ())->rects; nBox = const_cast <Region> (r.handle ())->numRects; n = nBox; streamingBuffer->begin (GL_TRIANGLES); while (n--) { GLfloat tx1 = COMP_TEX_COORD_X (bg->matrix (), pBox->x1); GLfloat tx2 = COMP_TEX_COORD_X (bg->matrix (), pBox->x2); GLfloat ty1 = COMP_TEX_COORD_Y (bg->matrix (), pBox->y1); GLfloat ty2 = COMP_TEX_COORD_Y (bg->matrix (), pBox->y2); vertexData[0] = pBox->x1; vertexData[1] = pBox->y1; vertexData[2] = 0.0f; vertexData[3] = pBox->x1; vertexData[4] = pBox->y2; vertexData[5] = 0.0f; vertexData[6] = pBox->x2; vertexData[7] = pBox->y1; vertexData[8] = 0.0f; vertexData[9] = pBox->x1; vertexData[10] = pBox->y2; vertexData[11] = 0.0f; vertexData[12] = pBox->x2; vertexData[13] = pBox->y2; vertexData[14] = 0.0f; vertexData[15] = pBox->x2; vertexData[16] = pBox->y1; vertexData[17] = 0.0f; textureData[0] = tx1; textureData[1] = ty1; textureData[2] = tx1; textureData[3] = ty2; textureData[4] = tx2; textureData[5] = ty1; textureData[6] = tx1; textureData[7] = ty2; textureData[8] = tx2; textureData[9] = ty2; textureData[10] = tx2; textureData[11] = ty1; streamingBuffer->addVertices (6, vertexData); streamingBuffer->addTexCoords (0, 6, textureData); pBox++; } streamingBuffer->end (); if (bg->name ()) { if (transformed) bg->enable (GLTexture::Good); else bg->enable (GLTexture::Fast); streamingBuffer->render (transform); bg->disable (); } } } }
void GLScreen::glPaintCompositedOutput (const CompRegion ®ion, GLFramebufferObject *fbo, unsigned int mask) { WRAPABLE_HND_FUNCTN (glPaintCompositedOutput, region, fbo, mask) GLMatrix sTransform; const GLTexture::Matrix & texmatrix = fbo->tex ()->matrix (); GLVertexBuffer *streamingBuffer = GLVertexBuffer::streamingBuffer (); streamingBuffer->begin (GL_TRIANGLES); if (mask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK) { GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, 0.0f); GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, screen->width ()); GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, 0.0f); GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, screen->height ()); const GLfloat vertexData[] = { 0.0f, 0.0f, 0.0f, 0.0f, (float)screen->height (), 0.0f, (float)screen->width (), 0.0f, 0.0f, 0.0f, (float)screen->height (), 0.0f, (float)screen->width (), (float)screen->height (), 0.0f, (float)screen->width (), 0.0f, 0.0f, }; const GLfloat textureData[] = { tx1, ty1, tx1, ty2, tx2, ty1, tx1, ty2, tx2, ty2, tx2, ty1, }; streamingBuffer->addVertices (6, &vertexData[0]); streamingBuffer->addTexCoords (0, 6, &textureData[0]); } else { BoxPtr pBox = const_cast <Region> (region.handle ())->rects; int nBox = const_cast <Region> (region.handle ())->numRects; while (nBox--) { GLfloat tx1 = COMP_TEX_COORD_X (texmatrix, pBox->x1); GLfloat tx2 = COMP_TEX_COORD_X (texmatrix, pBox->x2); GLfloat ty1 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y1); GLfloat ty2 = 1.0 - COMP_TEX_COORD_Y (texmatrix, pBox->y2); const GLfloat vertexData[] = { (float)pBox->x1, (float)pBox->y1, 0.0f, (float)pBox->x1, (float)pBox->y2, 0.0f, (float)pBox->x2, (float)pBox->y1, 0.0f, (float)pBox->x1, (float)pBox->y2, 0.0f, (float)pBox->x2, (float)pBox->y2, 0.0f, (float)pBox->x2, (float)pBox->y1, 0.0f, }; const GLfloat textureData[] = { tx1, ty1, tx1, ty2, tx2, ty1, tx1, ty2, tx2, ty2, tx2, ty1, }; streamingBuffer->addVertices (6, &vertexData[0]); streamingBuffer->addTexCoords (0, 6, &textureData[0]); pBox++; } } streamingBuffer->end (); fbo->tex ()->enable (GLTexture::Fast); sTransform.toScreenSpace (&screen->fullscreenOutput (), -DEFAULT_Z_CAMERA); streamingBuffer->render (sTransform); fbo->tex ()->disable (); }
void GridAnim::addGeometry (const GLTexture::MatrixList &matrix, const CompRegion ®ion, const CompRegion &clip, unsigned int maxGridWidth, unsigned int maxGridHeight) { if (region.isEmpty ()) // nothing to do return; GLfloat *v, *vMax; bool notUsing3dCoords = !using3D (); CompRect outRect (mAWindow->savedRectsValid () ? mAWindow->savedOutRect () : mWindow->outputRect ()); CompWindowExtents outExtents (mAWindow->savedRectsValid () ? mAWindow->savedOutExtents () : mWindow->output ()); // window output (contents + decorations + shadows) coordinates and size int ox = outRect.x (); int oy = outRect.y (); int owidth = outRect.width (); int oheight = outRect.height (); // to be used if event is shade/unshade float winContentsY = oy + outExtents.top; float winContentsHeight = oheight - outExtents.top - outExtents.bottom; GLWindow *gWindow = GLWindow::get (mWindow); GLVertexBuffer *vertexBuffer = gWindow->vertexBuffer (); int vSize = vertexBuffer->getVertexStride (); // Indentation kept to provide a clean diff with the old code, for now... { int y1 = outRect.y1 (); int x2 = outRect.x2 (); int y2 = outRect.y2 (); float gridW = (float)owidth / (mGridWidth - 1); float gridH; if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part gridH = mDecorTopHeight; else if (y2 > winContentsY + winContentsHeight) // if at bottom gridH = mDecorBottomHeight; else // in window contents (only in Y coords) { float winContentsHeight = oheight - (mDecorTopHeight + mDecorBottomHeight); gridH = winContentsHeight / (mGridHeight - 3); } } else gridH = (float)oheight / (mGridHeight - 1); int oldCount = vertexBuffer->countVertices (); gWindow->glAddGeometry (matrix, region, clip, gridW, gridH); int newCount = vertexBuffer->countVertices (); v = vertexBuffer->getVertices () + (oldCount * vSize); vMax = vertexBuffer->getVertices () + (newCount * vSize); float x, y, topiyFloat; // For each vertex for (; v < vMax; v += vSize) { x = v[0]; y = v[1]; if (y > y2) y = y2; if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part { topiyFloat = (y - oy) / mDecorTopHeight; topiyFloat = MIN (topiyFloat, 0.999); // avoid 1.0 } else if (y2 > winContentsY + winContentsHeight) // if at bottom topiyFloat = (mGridHeight - 2) + (mDecorBottomHeight ? (y - winContentsY - winContentsHeight) / mDecorBottomHeight : 0); else // in window contents (only in Y coords) topiyFloat = (mGridHeight - 3) * (y - winContentsY) / winContentsHeight + 1; } else topiyFloat = (mGridHeight - 1) * (y - oy) / oheight; // topiy should be at most (mGridHeight - 2) int topiy = (int)(topiyFloat + 1e-4); if (topiy == mGridHeight - 1) --topiy; int bottomiy = topiy + 1; float iny = topiyFloat - topiy; float inyRest = 1 - iny; // End of calculations for y // Indentation kept to provide a clean diff with the old code... { if (x > x2) x = x2; // find containing grid cell (leftix rightix) x (topiy bottomiy) float leftixFloat = (mGridWidth - 1) * (x - ox) / owidth; int leftix = (int)(leftixFloat + 1e-4); if (leftix == mGridWidth - 1) --leftix; int rightix = leftix + 1; // GridModel::GridObjects that are at top, bottom, left, right corners of quad GridModel::GridObject *objToTopLeft = &(mModel->mObjects[topiy * mGridWidth + leftix]); GridModel::GridObject *objToTopRight = &(mModel->mObjects[topiy * mGridWidth + rightix]); GridModel::GridObject *objToBottomLeft = &(mModel->mObjects[bottomiy * mGridWidth + leftix]); GridModel::GridObject *objToBottomRight = &(mModel->mObjects[bottomiy * mGridWidth + rightix]); Point3d &objToTopLeftPos = objToTopLeft->mPosition; Point3d &objToTopRightPos = objToTopRight->mPosition; Point3d &objToBottomLeftPos = objToBottomLeft->mPosition; Point3d &objToBottomRightPos = objToBottomRight->mPosition; // find position in cell by taking remainder of flooring float inx = leftixFloat - leftix; float inxRest = 1 - inx; // Interpolate to find deformed coordinates float hor1x = (inxRest * objToTopLeftPos.x () + inx * objToTopRightPos.x ()); float hor1y = (inxRest * objToTopLeftPos.y () + inx * objToTopRightPos.y ()); float hor1z = (notUsing3dCoords ? 0 : inxRest * objToTopLeftPos.z () + inx * objToTopRightPos.z ()); float hor2x = (inxRest * objToBottomLeftPos.x () + inx * objToBottomRightPos.x ()); float hor2y = (inxRest * objToBottomLeftPos.y () + inx * objToBottomRightPos.y ()); float hor2z = (notUsing3dCoords ? 0 : inxRest * objToBottomLeftPos.z () + inx * objToBottomRightPos.z ()); float deformedX = inyRest * hor1x + iny * hor2x; float deformedY = inyRest * hor1y + iny * hor2y; float deformedZ = inyRest * hor1z + iny * hor2z; v[0] = deformedX; v[1] = deformedY; v[2] = deformedZ; } } } }
bool ShowrepaintScreen::glPaintOutput (const GLScreenPaintAttrib &attrib, const GLMatrix &transform, const CompRegion ®ion, CompOutput *output, unsigned int mask) { bool status; GLMatrix sTransform; // initially identity matrix unsigned short color[4]; status = gScreen->glPaintOutput (attrib, transform, region, output, mask); tmpRegion = region.intersected (*output); if (tmpRegion.isEmpty ()) return status; sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA); color[3] = optionGetIntensity () * 0xffff / 100; color[0] = (rand () & 7) * color[3] / 8; color[1] = (rand () & 7) * color[3] / 8; color[2] = (rand () & 7) * color[3] / 8; GLboolean glBlendEnabled = glIsEnabled (GL_BLEND); if (!glBlendEnabled) glEnable (GL_BLEND); std::vector<GLfloat> vertices; /* for each rectangle, use two triangles to display it */ foreach (const CompRect &box, tmpRegion.rects ()) { //first triangle vertices.push_back (box.x1 ()); vertices.push_back (box.y1 ()); vertices.push_back (0.0f); vertices.push_back (box.x1 ()); vertices.push_back (box.y2 ()); vertices.push_back (0.0f); vertices.push_back (box.x2 ()); vertices.push_back (box.y2 ()); vertices.push_back (0.0f); //second triangle vertices.push_back (box.x2 ()); vertices.push_back (box.y2 ()); vertices.push_back (0.0f); vertices.push_back (box.x2 ()); vertices.push_back (box.y1 ()); vertices.push_back (0.0f); vertices.push_back (box.x1 ()); vertices.push_back (box.y1 ()); vertices.push_back (0.0f); } GLVertexBuffer *stream = GLVertexBuffer::streamingBuffer (); stream->begin (GL_TRIANGLES); stream->color4f ((float)color[0] / 65535.0f, (float)color[1] / 65535.0f, (float)color[2] / 65535.0f, (float)color[3] / 65535.0f); stream->addVertices (vertices.size () / 3, &vertices[0]); if (stream->end ()) stream->render (sTransform); stream->colorDefault (); /* only disable blending if it was disabled before */ if (!glBlendEnabled) glDisable (GL_BLEND); return status; }
void GridAnim::addGeometry (const GLTexture::MatrixList &matrix, const CompRegion ®ion, const CompRegion &clip, unsigned int maxGridWidth, unsigned int maxGridHeight) { unsigned int nMatrix = matrix.size (); int nVertices, nIndices; GLushort *i; GLfloat *v; int x1, y1, x2, y2; float winContentsY, winContentsHeight; float deformedX, deformedY; float deformedZ = 0; int nVertX, nVertY; int vSize; float gridW, gridH; bool rect = true; bool notUsing3dCoords = !using3D (); if (region.isEmpty ()) // nothing to do return; GLWindow::Geometry &geometry = GLWindow::get (mWindow)->geometry (); for (unsigned int it = 0; it < nMatrix; it++) { if (matrix[it].xy != 0.0f || matrix[it].yx != 0.0f) { rect = false; break; } } CompRect outRect (mAWindow->savedRectsValid () ? mAWindow->savedOutRect () : mWindow->outputRect ()); CompWindowExtents outExtents (mAWindow->savedRectsValid () ? mAWindow->savedOutExtents () : mWindow->output ()); // window output (contents + decorations + shadows) coordinates and size int ox = outRect.x (); int oy = outRect.y (); int owidth = outRect.width (); int oheight = outRect.height (); // to be used if event is shade/unshade winContentsY = oy + outExtents.top; winContentsHeight = oheight - outExtents.top - outExtents.bottom; geometry.texUnits = (int)nMatrix; if (geometry.vCount == 0) { // reset geometry.indexCount = 0; geometry.texCoordSize = 4; } geometry.vertexStride = 3 + geometry.texUnits * geometry.texCoordSize; vSize = geometry.vertexStride; nVertices = geometry.vCount; nIndices = geometry.indexCount; v = geometry.vertices + (nVertices * vSize); i = geometry.indices + nIndices; // For each clip passed to this function foreach (const CompRect &pClip, region.rects ()) { x1 = pClip.x1 (); y1 = pClip.y1 (); x2 = pClip.x2 (); y2 = pClip.y2 (); gridW = (float)owidth / (mGridWidth - 1); if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part { gridH = mDecorTopHeight; } else if (y2 > winContentsY + winContentsHeight) // if at bottom { gridH = mDecorBottomHeight; } else // in window contents (only in Y coords) { float winContentsHeight = oheight - (mDecorTopHeight + mDecorBottomHeight); gridH = winContentsHeight / (mGridHeight - 3); } } else gridH = (float)oheight / (mGridHeight - 1); // nVertX, nVertY: number of vertices for this clip in x and y dimensions // + 2 to avoid running short of vertices in some cases nVertX = ceil ((x2 - x1) / gridW) + 2; nVertY = (gridH ? ceil ((y2 - y1) / gridH) : 0) + 2; // Allocate 4 indices for each quad int newIndexSize = nIndices + ((nVertX - 1) * (nVertY - 1) * 4); if (newIndexSize > geometry.indexSize) { if (!geometry.moreIndices (newIndexSize)) return; i = geometry.indices + nIndices; } // Assign quad vertices to indices for (int jy = 0; jy < nVertY - 1; jy++) { for (int jx = 0; jx < nVertX - 1; jx++) { *i++ = nVertices + nVertX * (2 * jy + 1) + jx; *i++ = nVertices + nVertX * (2 * jy + 1) + jx + 1; *i++ = nVertices + nVertX * 2 * jy + jx + 1; *i++ = nVertices + nVertX * 2 * jy + jx; nIndices += 4; } } // Allocate vertices int newVertexSize = (nVertices + nVertX * (2 * nVertY - 2)) * vSize; if (newVertexSize > geometry.vertexSize) { if (!geometry.moreVertices (newVertexSize)) return; v = geometry.vertices + (nVertices * vSize); } float rowTexCoordQ = 1; float prevRowCellWidth = 0; // this initial value won't be used float rowCellWidth = 0; int clipRowSize = nVertX * vSize; // For each vertex float y = y1; for (int jy = 0; jy < nVertY; jy++) { float topiyFloat; bool applyOffsets = true; if (y > y2) y = y2; // Do calculations for y here to avoid repeating // them unnecessarily in the x loop if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { if (y1 < winContentsY) // if at top part { topiyFloat = (y - oy) / mDecorTopHeight; topiyFloat = MIN (topiyFloat, 0.999); // avoid 1.0 applyOffsets = false; } else if (y2 > winContentsY + winContentsHeight) // if at bottom { topiyFloat = (mGridHeight - 2) + (mDecorBottomHeight ? (y - winContentsY - winContentsHeight) / mDecorBottomHeight : 0); applyOffsets = false; } else // in window contents (only in Y coords) { topiyFloat = (mGridHeight - 3) * (y - winContentsY) / winContentsHeight + 1; } } else { topiyFloat = (mGridHeight - 1) * (y - oy) / oheight; } // topiy should be at most (mGridHeight - 2) int topiy = (int)(topiyFloat + 1e-4); if (topiy == mGridHeight - 1) topiy--; int bottomiy = topiy + 1; float iny = topiyFloat - topiy; float inyRest = 1 - iny; // End of calculations for y float x = x1; for (int jx = 0; jx < nVertX; jx++) { if (x > x2) x = x2; // find containing grid cell (leftix rightix) x (topiy bottomiy) float leftixFloat = (mGridWidth - 1) * (x - ox) / owidth; int leftix = (int)(leftixFloat + 1e-4); if (leftix == mGridWidth - 1) leftix--; int rightix = leftix + 1; // GridModel::GridObjects that are at top, bottom, left, right corners of quad GridModel::GridObject *objToTopLeft = &(mModel->mObjects[topiy * mGridWidth + leftix]); GridModel::GridObject *objToTopRight = &(mModel->mObjects[topiy * mGridWidth + rightix]); GridModel::GridObject *objToBottomLeft = &(mModel->mObjects[bottomiy * mGridWidth + leftix]); GridModel::GridObject *objToBottomRight = &(mModel->mObjects[bottomiy * mGridWidth + rightix]); Point3d &objToTopLeftPos = objToTopLeft->mPosition; Point3d &objToTopRightPos = objToTopRight->mPosition; Point3d &objToBottomLeftPos = objToBottomLeft->mPosition; Point3d &objToBottomRightPos = objToBottomRight->mPosition; // find position in cell by taking remainder of flooring float inx = leftixFloat - leftix; float inxRest = 1 - inx; // Interpolate to find deformed coordinates float hor1x = (inxRest * objToTopLeftPos.x () + inx * objToTopRightPos.x ()); float hor1y = (inxRest * objToTopLeftPos.y () + inx * objToTopRightPos.y ()); float hor1z = (notUsing3dCoords ? 0 : inxRest * objToTopLeftPos.z () + inx * objToTopRightPos.z ()); float hor2x = (inxRest * objToBottomLeftPos.x () + inx * objToBottomRightPos.x ()); float hor2y = (inxRest * objToBottomLeftPos.y () + inx * objToBottomRightPos.y ()); float hor2z = (notUsing3dCoords ? 0 : inxRest * objToBottomLeftPos.z () + inx * objToBottomRightPos.z ()); deformedX = inyRest * hor1x + iny * hor2x; deformedY = inyRest * hor1y + iny * hor2y; deformedZ = inyRest * hor1z + iny * hor2z; // Texture coordinates (s, t, r, q) if (mUseQTexCoord) { if (jx == 1) rowCellWidth = deformedX - v[-3]; // do only once per row for all rows except row 0 if (jy > 0 && jx == 1) { rowTexCoordQ = (rowCellWidth / prevRowCellWidth); for (unsigned int it = 0; it < nMatrix; it++, v += 4) { // update first column // (since we didn't know rowTexCoordQ before) v[-vSize] *= rowTexCoordQ; // multiply s & t by q v[-vSize + 1] *= rowTexCoordQ; v[-vSize + 3] = rowTexCoordQ; // copy q } v -= nMatrix * 4; } } // Loop for each texture element // (4 texture coordinates for each one) for (unsigned int it = 0; it < nMatrix; it++, v += 4) { float offsetY = 0; if (rect) { if (applyOffsets && y < y2) offsetY = objToTopLeft->mOffsetTexCoordForQuadAfter.y (); v[0] = COMP_TEX_COORD_X (matrix[it], x); // s v[1] = COMP_TEX_COORD_Y (matrix[it], y + offsetY); // t } else { if (applyOffsets && y < y2) // FIXME: // The correct y offset below produces wrong // texture coordinates for some reason. offsetY = 0; // offsetY = objToTopLeft->offsetTexCoordForQuadAfter.y; v[0] = COMP_TEX_COORD_XY (matrix[it], x, y + offsetY); // s v[1] = COMP_TEX_COORD_YX (matrix[it], x, y + offsetY); // t } v[2] = 0; // r if (0 < jy && jy < nVertY - 1) { // copy s, t, r to duplicate row memcpy (v + clipRowSize, v, 3 * sizeof (GLfloat)); v[3 + clipRowSize] = 1; // q } if (applyOffsets && objToTopLeft->mOffsetTexCoordForQuadBefore.y () != 0) { // After copying to next row, update texture y coord // by following object's offset offsetY = objToTopLeft->mOffsetTexCoordForQuadBefore.y (); if (rect) { v[1] = COMP_TEX_COORD_Y (matrix[it], y + offsetY); } else { v[0] = COMP_TEX_COORD_XY (matrix[it], x, y + offsetY); v[1] = COMP_TEX_COORD_YX (matrix[it], x, y + offsetY); } } if (mUseQTexCoord) { v[3] = rowTexCoordQ; // q if (jx > 0) // since column 0 is updated when jx == 1 { // multiply s & t by q v[0] *= rowTexCoordQ; v[1] *= rowTexCoordQ; } } else { v[3] = 1; // q } } v[0] = deformedX; v[1] = deformedY; v[2] = deformedZ; // Copy vertex coordinates to duplicate row if (0 < jy && jy < nVertY - 1) memcpy (v + clipRowSize, v, 3 * sizeof (GLfloat)); nVertices++; // increment x properly (so that coordinates fall on grid intersections) x = rightix * gridW + ox; v += 3; // move on to next vertex } if (mUseQTexCoord) prevRowCellWidth = rowCellWidth; if (0 < jy && jy < nVertY - 1) { v += clipRowSize; // skip the duplicate row nVertices += nVertX; } // increment y properly (so that coordinates fall on grid intersections) if (mCurWindowEvent == WindowEventShade || mCurWindowEvent == WindowEventUnshade) { y += gridH; } else { y = bottomiy * gridH + oy; } } } geometry.vCount = nVertices; geometry.indexCount = nIndices; }
bool CompRegion::operator== (const CompRegion &c) const { return XEqualRegion (handle (), c.handle ()); }