void doCompute(TTile &tile, double frame, const TRenderSettings &info) { bool isWarped = m_warped.isConnected(); if (!isWarped) return; if (fabs(m_intensity->getValue(frame)) < 0.01) { m_warped->compute(tile, frame, info); return; } int shrink = (info.m_shrinkX + info.m_shrinkY) / 2; double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); params.m_shrink = shrink; double period = m_period->getValue(frame) / info.m_shrinkX; double count = m_count->getValue(frame); double cycle = m_cycle->getValue(frame) / info.m_shrinkX; double scaleX = m_scaleX->getValue(frame) / 100.0; double scaleY = m_scaleY->getValue(frame) / 100.0; double angle = -m_angle->getValue(frame); TPointD center = m_center->getValue(frame) * (1.0 / info.m_shrinkX); // The warper is calculated on a standard reference, with fixed dpi. This // makes sure // that the lattice created for the warp does not depend on camera // transforms and resolution. TRenderSettings warperInfo(info); double warperScaleFactor = 1.0 / params.m_warperScale; warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine; // Retrieve tile's geometry TRectD tileRect; { TRasterP tileRas = tile.getRaster(); tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy())); } // Build the compute rect TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params); if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return; if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0) return; TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect); double warperEnlargement = getWarperEnlargement(params); warperComputeRect = warperComputeRect.enlarge(warperEnlargement); warperComputeRect.x0 = tfloor(warperComputeRect.x0); warperComputeRect.y0 = tfloor(warperComputeRect.y0); warperComputeRect.x1 = tceil(warperComputeRect.x1); warperComputeRect.y1 = tceil(warperComputeRect.y1); // Compute the warped tile TTile tileIn; m_warped->allocateAndCompute( tileIn, warpedComputeRect.getP00(), TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()), tile.getRaster(), frame, info); TRasterP rasIn = tileIn.getRaster(); // Compute the warper tile TSpectrum::ColorKey colors[] = {TSpectrum::ColorKey(0, TPixel32::White), TSpectrum::ColorKey(0.5, TPixel32::Black), TSpectrum::ColorKey(1, TPixel32::White)}; TSpectrumParamP ripplecolors = TSpectrumParamP(tArrayCount(colors), colors); // Build the multiradial warperInfo.m_affine = warperInfo.m_affine * TTranslation(center) * TRotation(angle) * TScale(scaleX, scaleY); TAffine aff = warperInfo.m_affine.inv(); TPointD posTrasf = aff * (warperComputeRect.getP00()); TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy()); multiRadial(rasWarper, posTrasf, ripplecolors, period, count, cycle, aff, frame); // TImageWriter::save(TFilePath("C:\\ripple.tif"), rasWarper); // Warp TPointD db; TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db)); TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI); TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00()); TPointD warperPos( (TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00()); warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params); }
void subCompute(TRasterFxPort &m_input, TTile &tile, double frame, const TRenderSettings &ri, TPointD p00, TPointD p01, TPointD p11, TPointD p10, int details, bool wireframe, TDimension m_offScreenSize, bool isCast) { TPixel32 bgColor; TRectD outBBox, inBBox; outBBox = inBBox = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); m_input->getBBox(frame, inBBox, ri); if (inBBox == TConsts::infiniteRectD) // e' uno zerario inBBox = outBBox; int inBBoxLx = (int)inBBox.getLx() / ri.m_shrinkX; int inBBoxLy = (int)inBBox.getLy() / ri.m_shrinkY; if (inBBox.isEmpty()) return; if (p00 == p01 && p00 == p10 && p00 == p11 && !isCast) // significa che non c'e' deformazione { m_input->compute(tile, frame, ri); return; } TRaster32P rasIn; TPointD rasInPos; if (!wireframe) { if (ri.m_bpp == 64 || ri.m_bpp == 48) { TRaster64P aux = TRaster64P(inBBoxLx, inBBoxLy); rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(aux, rasInPos); m_input->compute(tmp, frame, ri); rasIn = TRaster32P(inBBoxLx, inBBoxLy); TRop::convert(rasIn, aux); } else { rasInPos = TPointD(inBBox.x0 / ri.m_shrinkX, inBBox.y0 / ri.m_shrinkY); TTile tmp(TRaster32P(inBBoxLx, inBBoxLy), rasInPos); m_input->allocateAndCompute(tmp, rasInPos, TDimension(inBBoxLx, inBBoxLy), TRaster32P(), frame, ri); rasIn = tmp.getRaster(); } } unsigned int texWidth = 2; unsigned int texHeight = 2; while (texWidth < (unsigned int)inBBoxLx) texWidth = texWidth << 1; while (texHeight < (unsigned int)inBBoxLy) texHeight = texHeight << 1; while (texWidth > 1024 || texHeight > 1024) // avevo usato la costante // GL_MAX_TEXTURE_SIZE invece di // 1024, ma non funzionava! { inBBoxLx = inBBoxLx >> 1; inBBoxLy = inBBoxLy >> 1; texWidth = texWidth >> 1; texHeight = texHeight >> 1; } if (rasIn->getLx() != inBBoxLx || rasIn->getLy() != inBBoxLy) { TRaster32P rasOut = TRaster32P(inBBoxLx, inBBoxLy); TRop::resample(rasOut, rasIn, TScale((double)rasOut->getLx() / rasIn->getLx(), (double)rasOut->getLy() / rasIn->getLy())); rasIn = rasOut; } int rasterWidth = tile.getRaster()->getLx() + 2; int rasterHeight = tile.getRaster()->getLy() + 2; assert(rasterWidth > 0); assert(rasterHeight > 0); TRectD clippingRect = TRectD(tile.m_pos, TDimensionD(tile.getRaster()->getLx(), tile.getRaster()->getLy())); #ifdef CREATE_GL_CONTEXT_ONE_TIME int ret = wglMakeCurrent(m_offScreenGL.m_offDC, m_offScreenGL.m_hglRC); assert(ret == TRUE); #else TOfflineGL offScreenRendering(TDimension(rasterWidth, rasterHeight)); //#ifdef _WIN32 offScreenRendering.makeCurrent(); //#else //#if defined(LINUX) || defined(MACOSX) // offScreenRendering.m_offlineGL->makeCurrent(); //#endif #endif checkErrorsByGL // disabilito quello che non mi serve per le texture glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); glDisable(GL_DITHER); glDisable(GL_DEPTH_TEST); glCullFace(GL_FRONT); glDisable(GL_STENCIL_TEST); glDisable(GL_LOGIC_OP); // creo la texture in base all'immagine originale glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); checkErrorsByGL #ifndef CREATE_GL_CONTEXT_ONE_TIME TRaster32P rasaux; if (!wireframe) { TRaster32P texture(texWidth, texHeight); texture->clear(); rasaux = texture; rasaux->lock(); texture->copy(rasIn); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, 4, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->getRawData()); } #else unsigned int texWidth = 1024; unsigned int texHeight = 1024; rasaux = rasIn; rasaux->lock(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasIn->getLx(), rasIn->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, rasIn->getRawData()); #endif checkErrorsByGL glEnable(GL_TEXTURE_2D); // cfr. help: OpenGL/Programming tip/OpenGL Correctness Tips glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-rasterWidth * 0.5, rasterWidth * 0.5, -rasterHeight * 0.5, rasterHeight * 0.5, -1, 1); glViewport(0, 0, rasterWidth, rasterHeight); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); // do OpenGL draw double lwTex = (double)(inBBoxLx - 1) / (double)(texWidth - 1); double lhTex = (double)(inBBoxLy - 1) / (double)(texHeight - 1); TPointD tex00 = TPointD(0.0, 0.0); TPointD tex10 = TPointD(lwTex, 0.0); TPointD tex11 = TPointD(lwTex, lhTex); TPointD tex01 = TPointD(0.0, lhTex); GLenum polygonStyle; if (wireframe) { polygonStyle = GL_LINE; glDisable(GL_TEXTURE_2D); } else polygonStyle = GL_FILL; checkErrorsByGL p00.x /= ri.m_shrinkX; p00.y /= ri.m_shrinkY; p10.x /= ri.m_shrinkX; p10.y /= ri.m_shrinkY; p11.x /= ri.m_shrinkX; p11.y /= ri.m_shrinkY; p01.x /= ri.m_shrinkX; p01.y /= ri.m_shrinkY; TPointD translate = TPointD(tile.m_pos.x + tile.getRaster()->getLx() * 0.5, tile.m_pos.y + tile.getRaster()->getLy() * 0.5); glTranslated(-translate.x, -translate.y, 0.0); // disegno il poligono double dist_p00_p01 = tdistance2(p00, p01); double dist_p10_p11 = tdistance2(p10, p11); double dist_p01_p11 = tdistance2(p01, p11); double dist_p00_p10 = tdistance2(p00, p10); bool vertical = (dist_p00_p01 == dist_p10_p11); bool horizontal = (dist_p00_p10 == dist_p01_p11); if (vertical && horizontal) details = 1; glPolygonMode(GL_FRONT_AND_BACK, polygonStyle); subdivision(p00, p10, p11, p01, tex00, tex10, tex11, tex01, clippingRect, details); if (!wireframe) { // abilito l'antialiasing delle linee glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // disegno il bordo del poligono glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glBegin(GL_QUADS); glTexCoord2d(tex00.x, tex00.y); tglVertex(p00); glTexCoord2d(tex10.x, tex10.y); tglVertex(p10); glTexCoord2d(tex11.x, tex11.y); tglVertex(p11); glTexCoord2d(tex01.x, tex01.y); tglVertex(p01); glEnd(); // disabilito l'antialiasing per le linee glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisable(GL_TEXTURE_2D); } // force to finish glFlush(); // rimetto il disegno dei poligoni a GL_FILL glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // metto il frame buffer nel raster del tile glPixelStorei(GL_UNPACK_ROW_LENGTH, rasterWidth); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); TRaster32P newRas(tile.getRaster()->getLx(), tile.getRaster()->getLy()); newRas->lock(); glReadPixels(1, 1, newRas->getLx(), newRas->getLy(), GL_RGBA, GL_UNSIGNED_BYTE, (void *)newRas->getRawData()); newRas->unlock(); checkErrorsByGL rasaux->unlock(); tile.getRaster()->copy(newRas); }
QScriptValue Transform::scale(double sx, double sy) { return create(engine(), new Transform(TScale(sx, sy) * m_affine)); }
void doCompute(TTile &tile, double frame, const TRenderSettings &info) { bool isWarped = m_warped.isConnected(); if (!isWarped) return; if (fabs(m_intensity->getValue(frame)) < 0.01) { m_warped->compute(tile, frame, info); return; } int shrink = (info.m_shrinkX + info.m_shrinkY) / 2; double scale = sqrt(fabs(info.m_affine.det())); double gridStep = 1.5 * m_gridStep->getValue(frame); WarpParams params; params.m_intensity = m_intensity->getValue(frame) / gridStep; params.m_warperScale = scale * gridStep; params.m_sharpen = m_sharpen->getValue(); params.m_shrink = shrink; double evolution = m_evol->getValue(frame); double size = 100.0 / info.m_shrinkX; TPointD pos(m_posx->getValue(frame), m_posy->getValue(frame)); //The warper is calculated on a standard reference, with fixed dpi. This makes sure //that the lattice created for the warp does not depend on camera transforms and resolution. TRenderSettings warperInfo(info); double warperScaleFactor = 1.0 / params.m_warperScale; warperInfo.m_affine = TScale(warperScaleFactor) * info.m_affine; //Retrieve tile's geometry TRectD tileRect; { TRasterP tileRas = tile.getRaster(); tileRect = TRectD(tile.m_pos, TDimensionD(tileRas->getLx(), tileRas->getLy())); } //Build the compute rect TRectD warpedBox, warpedComputeRect, tileComputeRect; m_warped->getBBox(frame, warpedBox, info); getWarpComputeRects(tileComputeRect, warpedComputeRect, warpedBox, tileRect, params); if (tileComputeRect.getLx() <= 0 || tileComputeRect.getLy() <= 0) return; if (warpedComputeRect.getLx() <= 0 || warpedComputeRect.getLy() <= 0) return; TRectD warperComputeRect(TScale(warperScaleFactor) * tileComputeRect); double warperEnlargement = getWarperEnlargement(params); warperComputeRect = warperComputeRect.enlarge(warperEnlargement); warperComputeRect.x0 = tfloor(warperComputeRect.x0); warperComputeRect.y0 = tfloor(warperComputeRect.y0); warperComputeRect.x1 = tceil(warperComputeRect.x1); warperComputeRect.y1 = tceil(warperComputeRect.y1); //Compute the warped tile TTile tileIn; m_warped->allocateAndCompute(tileIn, warpedComputeRect.getP00(), TDimension(warpedComputeRect.getLx(), warpedComputeRect.getLy()), tile.getRaster(), frame, info); TRasterP rasIn = tileIn.getRaster(); //Compute the warper tile TSpectrum::ColorKey colors[] = { TSpectrum::ColorKey(0, TPixel32::White), TSpectrum::ColorKey(1, TPixel32::Black)}; TSpectrumParamP cloudscolors = TSpectrumParamP(tArrayCount(colors), colors); //Build the warper warperInfo.m_affine = warperInfo.m_affine; TAffine aff = warperInfo.m_affine.inv(); TTile warperTile; TRasterP rasWarper = rasIn->create(warperComputeRect.getLx(), warperComputeRect.getLy()); warperTile.m_pos = warperComputeRect.getP00(); warperTile.setRaster(rasWarper); { TRenderSettings info2(warperInfo); //Now, separate the part of the affine the Fx can handle from the rest. TAffine fxHandledAffine = handledAffine(warperInfo, frame); info2.m_affine = fxHandledAffine; TAffine aff = warperInfo.m_affine * fxHandledAffine.inv(); aff.a13 /= warperInfo.m_shrinkX; aff.a23 /= warperInfo.m_shrinkY; TRectD rectIn = aff.inv() * warperComputeRect; //rectIn = rectIn.enlarge(getResampleFilterRadius(info)); //Needed to counter the resample filter TRect rectInI(tfloor(rectIn.x0), tfloor(rectIn.y0), tceil(rectIn.x1) - 1, tceil(rectIn.y1) - 1); // rasIn e' un raster dello stesso tipo di tile.getRaster() TTile auxtile(warperTile.getRaster()->create(rectInI.getLx(), rectInI.getLy()), convert(rectInI.getP00())); TPointD mypos(auxtile.m_pos - pos); double scale2 = sqrt(fabs(info2.m_affine.det())); doClouds(auxtile.getRaster(), cloudscolors, mypos, evolution, size, 0.0, 1.0, PNOISE_CLOUDS, scale2, frame); info2.m_affine = aff; TRasterFx::applyAffine(warperTile, auxtile, info2); } //Warp TPointD db; TRect rasComputeRectI(convert(tileComputeRect - tileRect.getP00(), db)); TRasterP tileRas = tile.getRaster()->extract(rasComputeRectI); TPointD rasInPos(warpedComputeRect.getP00() - tileComputeRect.getP00()); TPointD warperPos((TScale(params.m_warperScale) * warperComputeRect.getP00()) - tileComputeRect.getP00()); warp(tileRas, rasIn, rasWarper, rasInPos, warperPos, params); }
void tglDraw(const TMeshImage &meshImage, const DrawableTextureData &texData, const TAffine &meshToTexAff, const PlasticDeformerDataGroup &group) { typedef MeshTexturizer::TextureData::TileData TileData; // Prepare OpenGL glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_HINT_BIT); // Preserve original status bits glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glLineWidth(1.0f); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Prepare variables const std::vector<TTextureMeshP> &meshes = meshImage.meshes(); const TTextureMesh *mesh; typedef std::vector<std::pair<int, int>> SortedFacesVector; const SortedFacesVector &sortedFaces = group.m_sortedFaces; const MeshTexturizer::TextureData *td = texData.m_textureData; int t, tCount = td->m_tileDatas.size(); GLuint texId = -1; int m = -1; const double *dstCoords; int v0, v1, v2; int e1ovi, e2ovi; // Edge X's Other Vertex Index (see below) // Prepare each tile's affine std::vector<TAffine> tileAff(tCount); for (t = 0; t != tCount; ++t) { const TileData &tileData = td->m_tileDatas[t]; const TRectD &tileRect = tileData.m_tileGeometry; tileAff[t] = TScale(1.0 / (tileRect.x1 - tileRect.x0), 1.0 / (tileRect.y1 - tileRect.y0)) * TTranslation(-tileRect.x0, -tileRect.y0) * meshToTexAff; } // Draw each face individually, according to the group's sorted faces list. // Change tile and mesh data only if they change - improves performance SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end()); for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) { int f = sft->first, m_ = sft->second; if (m != m_) { // Change mesh if different from current m = m_; mesh = meshes[m].getPointer(); dstCoords = group.m_datas[m].m_output.get(); } // Draw each face const TTextureMesh::face_type &fc = mesh->face(f); const TTextureMesh::edge_type &ed0 = mesh->edge(fc.edge(0)), &ed1 = mesh->edge(fc.edge(1)), &ed2 = mesh->edge(fc.edge(2)); { v0 = ed0.vertex(0); v1 = ed0.vertex(1); v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1)); e1ovi = (ed1.vertex(0) == v1) | (ed1.vertex(1) == v1); // ed1 and ed2 will refer to vertexes e2ovi = 1 - e1ovi; // with index 2 and these. } const TPointD &p0 = mesh->vertex(v0).P(), &p1 = mesh->vertex(v1).P(), &p2 = mesh->vertex(v2).P(); for (t = 0; t != tCount; ++t) { // Draw face against tile const TileData &tileData = td->m_tileDatas[t]; // Map each face vertex to tile coordinates TPointD s[3] = {tileAff[t] * p0, tileAff[t] * p1, tileAff[t] * p2}; // Test the face bbox - tile intersection if (std::min({s[0].x, s[1].x, s[2].x}) > 1.0 || std::min({s[0].y, s[1].y, s[2].y}) > 1.0 || std::max({s[0].x, s[1].x, s[2].x}) < 0.0 || std::max({s[0].y, s[1].y, s[2].y}) < 0.0) continue; // If the tile has changed, interrupt the glBegin/glEnd block and bind the // OpenGL texture corresponding to the new tile if (tileData.m_textureId != texId) { texId = tileData.m_textureId; glBindTexture( GL_TEXTURE_2D, tileData .m_textureId); // This must be OUTSIDE a glBegin/glEnd block } const double *d[3] = {dstCoords + (v0 << 1), dstCoords + (v1 << 1), dstCoords + (v2 << 1)}; /* Now, draw primitives. A note about pixel arithmetic, here. Since line antialiasing in OpenGL just manipulates output fragments' alpha components, we must require that the input texture is NONPREMULTIPLIED. Furthermore, this function does not rely on the assumption that the output alpha component is discarded (as it happens when drawing on screen). This means that just using a simple glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) is not an option, since this way THE INPUT SRC ALPHA GETS MULTIPLIED BY ITSELF - see glBlendFunc's docs - and that shows. The solution is to separate the rendering of RGB and M components - the formers use GL_SRC_ALPHA, while the latter uses GL_ONE. The result is a PREMULTIPLIED image. */ // First, draw antialiased face edges on the mesh border. bool drawEd0 = (ed0.facesCount() < 2), drawEd1 = (ed1.facesCount() < 2), drawEd2 = (ed2.facesCount() < 2); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glBegin(GL_LINES); { if (drawEd0) { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); } if (drawEd1) { glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } if (drawEd2) { glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } } glEnd(); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); glBegin(GL_LINES); { if (drawEd0) { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); } if (drawEd1) { glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } if (drawEd2) { glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } } glEnd(); // Finally, draw the face glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glBegin(GL_TRIANGLES); { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } glEnd(); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); glBegin(GL_TRIANGLES); { glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1)); glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1)); glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1)); } glEnd(); } } glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture glPopAttrib(); }
bool addFrame(ToonzScene &scene, int row, bool isLast) { assert(m_status == 3); if (!m_started) start(scene); TDimension cameraRes = scene.getCurrentCamera()->getRes(); TDimensionD cameraSize = scene.getCurrentCamera()->getSize(); TPointD center(0.5 * cameraSize.lx, 0.5 * cameraSize.ly); double sx = (double)m_offlineGlContext.getLx() / (double)cameraRes.lx; double sy = (double)m_offlineGlContext.getLy() / (double)cameraRes.ly; double sc = std::min(sx, sy); // TAffine cameraAff = // scene.getXsheet()->getPlacement(TStageObjectId::CameraId(0), row); TAffine cameraAff = scene.getXsheet()->getCameraAff(row); double dpiScale = (1.0 / Stage::inch) * (double)cameraRes.lx / cameraSize.lx; // TAffine viewAff = TScale(dpiScale*sc) * TTranslation(center)* // cameraAff.inv(); TAffine viewAff = TTranslation(0.5 * cameraRes.lx, 0.5 * cameraRes.ly) * TScale(dpiScale * sc) * cameraAff.inv(); TRect clipRect(m_offlineGlContext.getBounds()); TPixel32 bgColor = scene.getProperties()->getBgColor(); m_offlineGlContext.makeCurrent(); TPixel32 bgClearColor = m_bgColor; if (m_alphaEnabled && m_alphaNeeded) { const double maxValue = 255.0; double alpha = (double)bgClearColor.m / maxValue; bgClearColor.r *= alpha; bgClearColor.g *= alpha; bgClearColor.b *= alpha; } m_offlineGlContext.clear(bgClearColor); Stage::VisitArgs args; args.m_scene = &scene; args.m_xsh = scene.getXsheet(); args.m_row = row; args.m_col = m_columnIndex; args.m_osm = &m_osMask; ImagePainter::VisualSettings vs; Stage::OpenGlPainter painter(viewAff, clipRect, vs, false, true); Stage::visit(painter, args); /* painter, &scene, scene.getXsheet(), row, m_columnIndex, m_osMask, false,0); */ TImageWriterP writer = m_lw->getFrameWriter(m_frameIndex++); if (!writer) return false; #ifdef MACOSX glFinish(); // per fissare il bieco baco su Mac/G3 #endif TRaster32P raster = m_offlineGlContext.getRaster(); #ifdef MACOSX if (m_alphaEnabled && m_alphaNeeded) checkAndCorrectPremultipliedImage(raster); #endif if (Preferences::instance()->isSceneNumberingEnabled()) TRasterImageUtils::addSceneNumbering(TRasterImageP(raster), m_frameIndex - 1, scene.getSceneName(), row + 1); TRasterImageP img(raster); writer->save(img); return true; }
void TglTessellator::tessellate(const TColorFunction *cf, const bool antiAliasing, TRegionOutline &outline, TRaster32P texture) { //QMutexLocker sl(m_mutex); checkErrorsByGL; glEnable(GL_TEXTURE_2D); glColor4d(1, 1, 1, 1); checkErrorsByGL; TextureInfoForGL texInfo; int pow2Lx = tcg::numeric_ops::GE_2Power((unsigned int)texture->getLx()); int pow2Ly = tcg::numeric_ops::GE_2Power((unsigned int)texture->getLy()); TAffine aff; if (texture->getLx() != pow2Lx || texture->getLy() != pow2Ly) { TRaster32P r(pow2Lx, pow2Ly); aff = TScale((double)pow2Lx / texture->getLx(), (double)pow2Ly / texture->getLy()); TRop::resample(r, texture, aff.place(texture->getCenterD(), r->getCenterD())); texture = r; glPushMatrix(); tglMultMatrix(aff.inv()); } // If GL_BRGA isn't present make a proper texture to use (... obsolete?) texture->lock(); TRasterP texImage = prepareTexture(texture, texInfo); checkErrorsByGL; if (texImage != texture) texImage->lock(); assert(texImage->getLx() == texImage->getWrap()); GLuint texId; glGenTextures(1, &texId); // Generate a texture name checkErrorsByGL; glBindTexture(GL_TEXTURE_2D, texId); // Bind it 'active' checkErrorsByGL; glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // These must be invoked glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // on a bound texture glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // checkErrorsByGL; glTexEnvf(GL_TEXTURE_ENV, // This too ? GL_TEXTURE_ENV_MODE, // Better here anyway GL_MODULATE); // checkErrorsByGL; glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); checkErrorsByGL; glTexImage2D(GL_TEXTURE_2D, 0, // one level only texInfo.internalformat, // pixel channels count texInfo.width, // width texInfo.height, // height 0, // border size texInfo.type, // pixel format // crappy names texInfo.format, // pixel data type // oh, SO much texImage->getRawData()); checkErrorsByGL; texture->unlock(); if (texImage != texture) texImage->unlock(); TglTessellator::GLTess glTess; gluTessCallback(glTess.m_tess, GLU_TESS_VERTEX, (GluCallback)tessellateTexture); checkErrorsByGL; //------------------------// if (aff != TAffine()) doTessellate(glTess, cf, antiAliasing, outline, aff); // Tessellate & render else doTessellate(glTess, cf, antiAliasing, outline); // Tessellate & render checkErrorsByGL; //------------------------// if (aff != TAffine()) glPopMatrix(); glDeleteTextures(1, &texId); // Delete & unbind texture checkErrorsByGL; glDisable(GL_TEXTURE_2D); checkErrorsByGL; }