diff --git a/Cassiopee/CPlot/CPlot/Display/renderDLUIsoSolidZone.cpp b/Cassiopee/CPlot/CPlot/Display/renderDLUIsoSolidZone.cpp index f51707e93..0762c4bb5 100644 --- a/Cassiopee/CPlot/CPlot/Display/renderDLUIsoSolidZone.cpp +++ b/Cassiopee/CPlot/CPlot/Display/renderDLUIsoSolidZone.cpp @@ -28,27 +28,16 @@ //============================================================================= void DataDL::renderUIsoSolidZone(UnstructZone* zonep, E_Int zonet, E_Int nofield) { - E_Int i, n1, n2; float offb; double blend; - E_Int ret1, ret2; - - E_Int ne = zonep->ne; + ZoneImplDL* zoneImpl = static_cast(zonep->ptr_impl); // Blending blend = 1.; #include "selection2.h" - double* x = zonep->x; double* y = zonep->y; double* z = zonep->z; E_Int eltType0 = zonep->eltType[0]; - E_Int* connect = zonep->connect[0]; - double fmin, fmax; - fmax = maxf[nofield]; fmin = minf[nofield]; - double deltai = MAX(fmax-fmin, ISOCUTOFF); - float r; - deltai = 1./deltai; - double* f = zonep->f[nofield]; #ifdef __SHADERS__ int curr = _shaders.currentShader(); diff --git a/Cassiopee/CPlot/CPlot/PyTree.py b/Cassiopee/CPlot/CPlot/PyTree.py index 6dd88fac8..5012185a2 100644 --- a/Cassiopee/CPlot/CPlot/PyTree.py +++ b/Cassiopee/CPlot/CPlot/PyTree.py @@ -1150,7 +1150,8 @@ def display360(t, **kwargs): # resolution for the 6 view images locRez = exportRez.split('x')[1] locRez = int(locRez)//2 - locRez = max(locRez, 100) + locRez = max(locRez, 100) # minimum 100 pixels + locRez = min(locRez, 8192) # maximum 8192 pixels, generally the max texture size locRez = "%dx%d"%(locRez, locRez) # display 6 views @@ -1159,12 +1160,13 @@ def display360(t, **kwargs): # Create the 360 image from cube images import Converter.Mpi as Cmpi if Cmpi.rank == 0: - if offscreen == 7: foffscreen = 1 - else: foffscreen = offscreen - a = C.newPyTree(['Base']) - display(a, panorama=1, - offscreen=foffscreen, export=export, exportResolution=exportRez) - finalizeExport(foffscreen) + #if offscreen == 7: foffscreen = 1 + #else: foffscreen = offscreen + #a = C.newPyTree(['Base']) + #display(a, panorama=1, + # offscreen=foffscreen, export=export, exportResolution=exportRez) + #finalizeExport(foffscreen) + panorama(export, exportRez) Cmpi.barrier() # wait for completion if stereo == 1: # left eye @@ -1182,20 +1184,20 @@ def display360(t, **kwargs): display360__(t, posCam, posEye, dirCam, offscreen, locRez, kwargs) if Cmpi.rank == 0: - if offscreen == 7: foffscreen = 1 - else: foffscreen = offscreen - a = C.newPyTree(['Base']) - display(a, panorama=1, - offscreen=foffscreen, export=export2, exportResolution=exportRez) - finalizeExport(foffscreen) + #if offscreen == 7: foffscreen = 1 + #else: foffscreen = offscreen + #a = C.newPyTree(['Base']) + #display(a, panorama=1, + # offscreen=foffscreen, export=export2, exportResolution=exportRez) + #finalizeExport(foffscreen) + panorama(export, exportRez) # assemble images a1 = C.convertFile2PyTree(export) a2 = C.convertFile2PyTree(export2) a1 = Internal.getZones(a1)[0] a2 = Internal.getZones(a2)[0] - a1[0] = "right" - a2[0] = "left" + a1[0] = "right"; a2[0] = "left" locRez = exportRez.split('x') ni = int(locRez[0]); nj = int(locRez[1]) a = G.cart((0,0,0), (1,1,1), (ni,2*nj,1)) @@ -1209,3 +1211,27 @@ def display360(t, **kwargs): C.convertPyTree2File(a, export) # finale Cmpi.barrier() # wait for completion return None + +def panorama(export, exportResolution): + res = exportResolution.split('x') + resx = int(res[0]); resy = int(res[1]) + import Generator.PyTree as G + import CPlot.cplot + a1 = C.convertFile2PyTree('cube_left.png') + a1 = C.getFields('nodes', a1, api=3)[0] + a2 = C.convertFile2PyTree('cube_right.png') + a2 = C.getFields('nodes', a2, api=3)[0] + a3 = C.convertFile2PyTree('cube_bottom.png') + a3 = C.getFields('nodes', a3, api=3)[0] + a4 = C.convertFile2PyTree('cube_top.png') + a4 = C.getFields('nodes', a4, api=3)[0] + a5 = C.convertFile2PyTree('cube_back.png') + a5 = C.getFields('nodes', a5, api=3)[0] + a6 = C.convertFile2PyTree('cube_front.png') + a6 = C.getFields('nodes', a6, api=3)[0] + a7 = G.cart((0,0,0), (1,1,1), (resx, resy,1)) + C._addVars(a7, ['r','g','b','a']) + a7f = C.getFields('nodes', a7, api=3)[0] + CPlot.cplot.panorama(a1, a2, a3, a4, a5, a6, a7f) + C.convertPyTree2File(a7, export) + return a7 \ No newline at end of file diff --git a/Cassiopee/CPlot/CPlot/cplot.cpp b/Cassiopee/CPlot/CPlot/cplot.cpp index f26904e49..66b76b67a 100644 --- a/Cassiopee/CPlot/CPlot/cplot.cpp +++ b/Cassiopee/CPlot/CPlot/cplot.cpp @@ -68,6 +68,7 @@ static PyMethodDef Pycplot [] = {"show", K_CPLOT::show, METH_VARARGS}, {"display1D", K_CPLOT::display1D, METH_VARARGS}, {"configure", K_CPLOT::configure, METH_VARARGS}, + {"panorama", K_CPLOT::panorama, METH_VARARGS}, {NULL, NULL} }; diff --git a/Cassiopee/CPlot/CPlot/cplot.h b/Cassiopee/CPlot/CPlot/cplot.h index 3e0190f72..ae70ee26a 100644 --- a/Cassiopee/CPlot/CPlot/cplot.h +++ b/Cassiopee/CPlot/CPlot/cplot.h @@ -75,6 +75,7 @@ PyObject* hide(PyObject* self, PyObject* args); PyObject* show(PyObject* self, PyObject* args); PyObject* display1D(PyObject* self, PyObject* args); PyObject* configure(PyObject* self, PyObject* args); +PyObject* panorama(PyObject* self, PyObject* args); } E_Int getMode(PyObject* modeObject); diff --git a/Cassiopee/CPlot/CPlot/panorama.cpp b/Cassiopee/CPlot/CPlot/panorama.cpp new file mode 100644 index 000000000..c44e3a2a7 --- /dev/null +++ b/Cassiopee/CPlot/CPlot/panorama.cpp @@ -0,0 +1,275 @@ +/* + Copyright 2013-2024 Onera. + + This file is part of Cassiopee. + + Cassiopee is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Cassiopee is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Cassiopee. If not, see . +*/ +#include "cplot.h" +#include "Data.h" + +void interp(E_Int ind, + E_Float* final1, E_Float* final2, E_Float* final3, E_Float* final4, + E_Float* im1, E_Float* im2, E_Float* im3, E_Float* im4, + E_Float px, E_Float py, E_Int ni1, E_Int nj1) +{ + E_Int i1 = E_Int(px*ni1); + E_Int i1p1 = std::min(i1+1, ni1); + E_Int j1 = E_Int(py*nj1); + E_Int j1p1 = std::min(j1+1, nj1); + E_Int ind1 = i1+j1*(ni1+1); + E_Int ind2 = i1p1+j1*(ni1+1); + E_Int ind3 = i1+j1p1*(ni1+1); + E_Int ind4 = i1p1+j1p1*(ni1+1); + E_Float ax = px*ni1-i1; + E_Float bx = 1.-ax; + E_Float ay = py*nj1-j1; + E_Float by = 1.-ay; + //printf("%g %g // %g %d\n", ax, ay, py, nj1); + final1[ind] = bx*by*im1[ind1]+ax*by*im1[ind2]+bx*ay*im1[ind3]+ax*ay*im1[ind4]; + //printf("ind=%d %g\n", ind, final1[ind]); + final2[ind] = bx*by*im2[ind1]+ax*by*im2[ind2]+bx*ay*im2[ind3]+ax*ay*im2[ind4]; + final3[ind] = bx*by*im3[ind1]+ax*by*im3[ind2]+bx*ay*im3[ind3]+ax*ay*im3[ind4]; + final4[ind] = bx*by*im4[ind1]+ax*by*im4[ind2]+bx*ay*im4[ind3]+ax*ay*im4[ind4]; +} + +// perform the stitching (identical to panorama.frag but on the cpu) +// it doesnt have the texture size limit +PyObject* K_CPLOT::panorama(PyObject* self, PyObject* args) +{ + // Get the 4 arrays of cube images (left, right, bottom, top, back, front) + PyObject* leftArray; PyObject* rightArray; + PyObject* bottomArray; PyObject* topArray; + PyObject* backArray; PyObject* frontArray; + PyObject* finalArray; + if (!PyArg_ParseTuple(args, "OOOOOOO", &leftArray, &rightArray, + &bottomArray, &topArray, &backArray, &frontArray, &finalArray)) + { + return NULL; + } + char* varString; + E_Int ni, nj, nk, res; + FldArrayF* left; FldArrayI* cn; char* eltType; + res = K_ARRAY::getFromArray3(leftArray, varString, left, + ni, nj, nk, cn, eltType); + if (res != 1) + { + PyErr_SetString(PyExc_TypeError, + "panorama: requires a structured array (left)."); + return NULL; + } + + FldArrayF* right; + res = K_ARRAY::getFromArray3(rightArray, varString, right, + ni, nj, nk, cn, eltType); + if (res != 1) + { + PyErr_SetString(PyExc_TypeError, + "panorama: requires a structured array (right)."); + return NULL; + } + + FldArrayF* bottom; + res = K_ARRAY::getFromArray3(bottomArray, varString, bottom, + ni, nj, nk, cn, eltType); + if (res != 1) + { + PyErr_SetString(PyExc_TypeError, + "panorama: requires a structured array (bottom)."); + return NULL; + } + + FldArrayF* top; + res = K_ARRAY::getFromArray3(topArray, varString, top, + ni, nj, nk, cn, eltType); + if (res != 1) + { + PyErr_SetString(PyExc_TypeError, + "panorama: requires a structured array (top)."); + return NULL; + } + + FldArrayF* back; + res = K_ARRAY::getFromArray3(backArray, varString, back, + ni, nj, nk, cn, eltType); + if (res != 1) + { + PyErr_SetString(PyExc_TypeError, + "panorama: requires a structured array (back)."); + return NULL; + } + + FldArrayF* front; + res = K_ARRAY::getFromArray3(frontArray, varString, front, + ni, nj, nk, cn, eltType); + if (res != 1) + { + PyErr_SetString(PyExc_TypeError, + "panorama: requires a structured array (front)."); + return NULL; + } + + FldArrayF* final; + E_Int nil, njl, nkl; + res = K_ARRAY::getFromArray3(finalArray, varString, final, + nil, njl, nkl, cn, eltType); + printf("varstring final=%s\n", varString); + if (res != 1) + { + PyErr_SetString(PyExc_TypeError, + "panorama: requires a structured array (final)."); + return NULL; + } + + // code +#define M_PI 3.1415926535897932384626433832795 + + E_Int nijl = nil*njl; + printf("nijl=%d\n", nijl); + E_Int nil1 = nil-1; + E_Int njl1 = njl-1; + E_Int ni1 = ni-1; + E_Int nj1 = nj-1; + + E_Float* left1 = left->begin(4); // r,g,b,a + E_Float* left2 = left->begin(5); + E_Float* left3 = left->begin(6); + E_Float* left4 = left->begin(7); + + E_Float* right1 = right->begin(4); // r,g,b,a + E_Float* right2 = right->begin(5); + E_Float* right3 = right->begin(6); + E_Float* right4 = right->begin(7); + + E_Float* bottom1 = bottom->begin(4); // r,g,b,a + E_Float* bottom2 = bottom->begin(5); + E_Float* bottom3 = bottom->begin(6); + E_Float* bottom4 = bottom->begin(7); + + E_Float* top1 = top->begin(4); // r,g,b,a + E_Float* top2 = top->begin(5); + E_Float* top3 = top->begin(6); + E_Float* top4 = top->begin(7); + + E_Float* back1 = back->begin(4); // r,g,b,a + E_Float* back2 = back->begin(5); + E_Float* back3 = back->begin(6); + E_Float* back4 = back->begin(7); + + E_Float* front1 = front->begin(4); // r,g,b,a + E_Float* front2 = front->begin(5); + E_Float* front3 = front->begin(6); + E_Float* front4 = front->begin(7); + + E_Float* final1 = final->begin(4); // r,g,b,a + E_Float* final2 = final->begin(5); + E_Float* final3 = final->begin(6); + E_Float* final4 = final->begin(7); + + #pragma omp parallel + { + E_Int ii, jj; + E_Float tx, ty, px, py; + E_Float theta, phi, x, y, z; + E_Float scale; + # pragma omp for + for (E_Int ind = 0; ind < nijl; ind++) + { + jj = E_Int(ind/nil); + ii = ind - jj*nil; + tx = (1.*ii) / nil1; + ty = (1.*jj) / njl1; + + theta = -M_PI + tx * 2. * M_PI; // between -pi and pi + phi = -M_PI/2. + ty * M_PI; // between -pi/2 and pi/2 + + x = cos(phi) * sin(theta); + y = sin(phi); + z = cos(phi) * cos(theta); + //printf("%d %d -tx=%g %g %g %g %g\n", ii,jj,tx,ty,x,y,z); + + if (std::abs(x) >= std::abs(y) && std::abs(x) >= std::abs(z)) + { + if (x < 0.0) + { + scale = -1.0 / x; + px = ( z*scale + 1.0) / 2.0; + py = ( y*scale + 1.0) / 2.0; + //printf("1px=%g %g\n", px, py); + interp(ind, final1, final2, final3, final4, + left1, left2, left3, left4, + px, py, ni1, nj1); + } + else + { + scale = 1.0 / x; + px = (-z*scale + 1.0) / 2.0; + py = ( y*scale + 1.0) / 2.0; + //printf("2px=%g %g\n", px, py); + interp(ind, final1, final2, final3, final4, + right1, right2, right3, right4, + px, py, ni1, nj1); + } + } + else if (std::abs(y) >= std::abs(z)) + { + if (y > 0.0) + { + scale = -1.0 / y; + px = (-x*scale + 1.0) / 2.0; // a shifter a droite + py = ( z*scale + 1.0) / 2.0; + //printf("3px=%g %g\n", px, py); + interp(ind, final1, final2, final3, final4, + bottom1, bottom2, bottom3, bottom4, + px, py, ni1, nj1); + } + else + { + scale = 1.0 / y; + px = (-x*scale + 1.0) / 2.0; + py = (-z*scale + 1.0) / 2.0; + //printf("4px=%g %g\n", px, py); + interp(ind, final1, final2, final3, final4, + top1, top2, top3, top4, + px, py, ni1, nj1); + } + } + else + { + if (z < 0.0) + { + scale = -1.0 / z; + px = (-x*scale + 1.0) / 2.0; + py = ( y*scale + 1.0) / 2.0; + //printf("5px=%g %g\n", px, py); + interp(ind, final1, final2, final3, final4, + back1, back2, back3, back4, + px, py, ni1, nj1); + } + else + { + scale = 1.0 / z; + px = ( x*scale + 1.0) / 2.0; + py = ( y*scale + 1.0) / 2.0; + //printf("6px=%g %g\n", px, py); + interp(ind, final1, final2, final3, final4, + front1, front2, front3, front4, + px, py, ni1, nj1); + } + } + } + } + return Py_None; +} + diff --git a/Cassiopee/CPlot/srcs.py b/Cassiopee/CPlot/srcs.py index 726527fff..3f1f5b590 100644 --- a/Cassiopee/CPlot/srcs.py +++ b/Cassiopee/CPlot/srcs.py @@ -23,6 +23,7 @@ 'CPlot/DataInstance.cpp', 'CPlot/DataDL.cpp', 'CPlot/fitView.cpp', + 'CPlot/panorama.cpp', 'CPlot/getStringsFromPyObj.cpp', 'CPlot/pressKey.cpp', 'CPlot/getAllVars.cpp', diff --git a/Cassiopee/Envs/env_Cassiopee_local b/Cassiopee/Envs/env_Cassiopee_local index 9bc3e6fe6..3e4bd22ff 100644 --- a/Cassiopee/Envs/env_Cassiopee_local +++ b/Cassiopee/Envs/env_Cassiopee_local @@ -654,7 +654,7 @@ else if ($MAC == "juno_gcc") then setenv PRODMODE 1 setenv PIP_DISABLE_PIP_VERSION_CHECK 1 unsetenv SLURM* - setenv OMP_PLACES cores + unsetenv OMP_PLACES else if ($MAC == "juno_coda") then #------------------------------- juno -------------------------------------- diff --git a/Cassiopee/Envs/sh_Cassiopee_local b/Cassiopee/Envs/sh_Cassiopee_local index 54859e9da..ad0fb3932 100644 --- a/Cassiopee/Envs/sh_Cassiopee_local +++ b/Cassiopee/Envs/sh_Cassiopee_local @@ -547,7 +547,7 @@ elif [ "$MAC" = "juno_gcc" ]; then export PRODMODE=1 export PIP_DISABLE_PIP_VERSION_CHECK=1 unset $(env | grep SLURM | cut -d'=' -f 1) - #export OMP_PLACES=cores + unset OMP_PLACES elif [ "$MAC" = "juno_coda" ]; then #----------------------------- juno -----------------------------------------