36 TGL5DPainter::TGL5DPainter(TGL5DDataSet *data, TGLPlotCamera *camera, TGLPlotCoordinates *coord)
 
   37          : TGLPlotPainter(data, camera, coord),
 
   43            fNContours(kNContours)
 
   45    if (fData->fV4IsString)
 
   46       fNContours = Int_t(fData->fV4MinMax.second) - Int_t(fData->fV4MinMax.first) + 1;
 
   54 TGL5DPainter::SurfIter_t TGL5DPainter::AddSurface(Double_t v4, Color_t ci,
 
   55                                                   Double_t iso, Double_t sigma,
 
   56                                                   Double_t range, Int_t lownps)
 
   58    fData->SelectPoints(v4, range);
 
   60    if (fData->SelectedSize() < size_type(lownps)) {
 
   61       Warning(
"TGL5DPainter::AddSurface", 
"Too little points: %d", Int_t(fData->SelectedSize()));
 
   64       Info(
"TGL5DPainter::AddSurface", 
"Selected %d points", Int_t(fData->SelectedSize()));
 
   67    fKDE.BuildModel(fData, sigma);
 
   69    Info(
"TGL5DPainter::AddSurface", 
"Building the mesh ...");
 
   71    Rgl::Mc::TGridGeometry<Float_t> geom(fXAxis, fYAxis, fZAxis,
 
   76    fMeshBuilder.SetGeometry(fData);
 
   78    fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, iso);
 
   80    Info(
"TGL5DPainter::AddSurface", 
"Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
 
   82    if (!mesh.fVerts.size())
 
   85    fIsos.push_front(fDummy);
 
   87    fIsos.front().fMesh.Swap(mesh);
 
   88    fIsos.front().f4D = v4;
 
   89    fIsos.front().fRange = range;
 
   90    fIsos.front().fShowCloud = kFALSE;
 
   91    fIsos.front().fHide = kFALSE;
 
   92    fIsos.front().fColor = ci;
 
  102 void TGL5DPainter::AddSurface(Double_t v4)
 
  104    const Rgl::Range_t &v4R = fData->fV4MinMax;
 
  105    const Bool_t isString   = fData->fV4IsString;
 
  106    const Double_t rms  = TMath::RMS(fData->fNP, fData->fV4);  
 
  107    const Double_t d    = isString ? (v4R.second - v4R.first) / (fNContours - 1)
 
  108                                   : 6 * rms / fNContours;
 
  110    const Double_t range = isString ? 1e-3 : fAlpha * d;
 
  112    AddSurface(v4, 1, 0.125, 0.05, range);
 
  118 void TGL5DPainter::RemoveSurface(SurfIter_t surf)
 
  120    if (surf == fIsos.end()) {
 
  121       Error(
"TGL5DPainter::RemoveSurface", 
"Invalid iterator, surface does not exist.");
 
  131 char *TGL5DPainter::GetPlotInfo(Int_t , Int_t )
 
  133    static char mess[] = {
"gl5d"};
 
  143 Bool_t TGL5DPainter::InitGeometry()
 
  148    fCoord->SetCoordType(kGLCartesian);
 
  150    if (!fCoord->SetRanges(fXAxis, fYAxis, fZAxis))
 
  155    fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
 
  156                        fCoord->GetYRangeScaled(),
 
  157                        fCoord->GetZRangeScaled());
 
  159       fCamera->SetViewVolume(fBackBox.Get3DBox());
 
  161    const Rgl::Range_t &v4R = fData->fV4MinMax;
 
  162    const Bool_t isString   = fData->fV4IsString;
 
  165    const Double_t mean = TMath::Mean(fData->fNP, fData->fV4); 
 
  166    const Double_t rms  = TMath::RMS(fData->fNP, fData->fV4);  
 
  167    const Double_t min  = isString ? v4R.first : mean - 3 * rms; 
 
  168    const Double_t d    = isString ? (v4R.second - v4R.first) / (fNContours - 1)
 
  169                                   : 6 * rms / fNContours;
 
  171    const Double_t range = isString ? 1e-3 : fAlpha * d;
 
  173    Info(
"InitGeometry", 
"min = %g, mean = %g, rms = %g, dx = %g", min, mean, rms, d);
 
  175    for (Int_t j = 0; j < fNContours; ++j) {
 
  176       const Double_t isoLevel = min + j * d;
 
  177       Info(
"TGL5DPainter::InitGeometry", 
"Iso-level %g, range is %g ...", isoLevel, range);
 
  178       const Color_t color = j * 6 + 1;
 
  179       AddSurface(isoLevel, color, 0.125, 0.05, range);
 
  185    return fInit = kTRUE;
 
  191 void TGL5DPainter::StartPan(Int_t px, Int_t py)
 
  193    fMousePosition.fX = px;
 
  194    fMousePosition.fY = fCamera->GetHeight() - py;
 
  195    fCamera->StartPan(px, py);
 
  196    fBoxCut.StartMovement(px, fCamera->GetHeight() - py);
 
  202 void TGL5DPainter::Pan(Int_t px, Int_t py)
 
  204    if (fSelectedPart >= fSelectionBase) {
 
  205       SaveModelviewMatrix();
 
  206       SaveProjectionMatrix();
 
  208       fCamera->SetCamera();
 
  209       fCamera->Apply(fPadPhi, fPadTheta);
 
  210       fCamera->Pan(px, py);
 
  212       RestoreProjectionMatrix();
 
  213       RestoreModelviewMatrix();
 
  214    } 
else if (fSelectedPart > 0) {
 
  216       py = fCamera->GetHeight() - py;
 
  218       SaveModelviewMatrix();
 
  219       SaveProjectionMatrix();
 
  221       fCamera->SetCamera();
 
  222       fCamera->Apply(fPadPhi, fPadTheta);
 
  225          if (fBoxCut.IsActive() && (fSelectedPart >= kXAxis && fSelectedPart <= kZAxis)) {
 
  226             fBoxCut.MoveBox(px, py, fSelectedPart);
 
  230       RestoreProjectionMatrix();
 
  231       RestoreModelviewMatrix();
 
  234    fMousePosition.fX = px, fMousePosition.fY = py;
 
  235    fUpdateSelection = kTRUE;
 
  241 void TGL5DPainter::AddOption(
const TString &)
 
  247 void TGL5DPainter::ProcessEvent(Int_t event, Int_t , Int_t py)
 
  250    if (event == kKeyPress) {
 
  251       if (py == kKey_c || py == kKey_C) {
 
  253             Info(
"ProcessEvent", 
"Cut box does not work in high color, please, switch to true color");
 
  256             fUpdateSelection = kTRUE;
 
  259    } 
else if (event == kButton1Double && fBoxCut.IsActive()) {
 
  260       if (fBoxCut.IsActive())
 
  262       if (!gVirtualX->IsCmdThread())
 
  263          gROOT->ProcessLineFast(Form(
"((TGLPlotPainter *)0x%lx)->Paint()", (ULong_t)
this));
 
  272 void TGL5DPainter::SetAlpha(Double_t newVal)
 
  274    if (fAlpha != newVal && !fData->fV4IsString) {
 
  280    if (fData->fV4IsString)
 
  281       Warning(
"SetAlpha", 
"Alpha is not required for string data (your 4-th dimension is string).");
 
  287 void TGL5DPainter::SetNContours(Int_t n)
 
  290       Warning(
"SetNContours", 
"Bad number of contours: %d", n);
 
  306 void TGL5DPainter::ResetGeometryRanges()
 
  308    fCoord->SetRanges(fXAxis, fYAxis, fZAxis);
 
  309    fBackBox.SetPlotBox(fCoord->GetXRangeScaled(),
 
  310                        fCoord->GetYRangeScaled(),
 
  311                        fCoord->GetZRangeScaled());
 
  313       fCamera->SetViewVolume(fBackBox.Get3DBox());
 
  315    for (SurfIter_t surf = fIsos.begin(); surf != fIsos.end(); ++surf) {
 
  316       fData->SelectPoints(surf->f4D, surf->fRange);
 
  317       fKDE.BuildModel(fData, 0.05);
 
  318       Info(
"TGL5DPainter::ResetGeometryRanges", 
"Building the mesh ...");
 
  320       Rgl::Mc::TGridGeometry<Float_t> geom(fXAxis, fYAxis, fZAxis,
 
  323                                            fCoord->GetZScale());
 
  324       fMeshBuilder.SetGeometry(fData);
 
  325       Mesh_t &mesh = surf->fMesh;
 
  331       fMeshBuilder.BuildMesh(&fKDE, geom, &mesh, 0.125);
 
  332       Info(
"TGL5DPainter::AddSurface", 
"Mesh has %d vertices", Int_t(mesh.fVerts.size() / 3));
 
  335    fBoxCut.ResetBoxGeometry();
 
  341 TGL5DPainter::SurfIter_t TGL5DPainter::SurfacesBegin()
 
  343    return fIsos.begin();
 
  349 TGL5DPainter::SurfIter_t TGL5DPainter::SurfacesEnd()
 
  357 void TGL5DPainter::InitGL()
 const 
  359    glEnable(GL_LIGHTING);
 
  361    glEnable(GL_DEPTH_TEST);
 
  362    glDisable(GL_CULL_FACE);
 
  363    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
 
  369 void TGL5DPainter::DeInitGL()
const 
  371    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
 
  372    glDisable(GL_CULL_FACE);
 
  373    glDisable(GL_DEPTH_TEST);
 
  374    glDisable(GL_LIGHT0);
 
  375    glDisable(GL_LIGHTING);
 
  381 void TGL5DPainter::DrawPlot()
 const 
  384    const Rgl::PlotTranslation trGuard(
this);
 
  386    fBackBox.DrawBox(fSelectedPart, fSelectionPass, fZLevels, fHighColor);
 
  392       Bool_t needSecondPass = kFALSE;
 
  393       for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
 
  397          if (it->fAlpha != 100) {
 
  398             needSecondPass = kTRUE;
 
  403          glEnable(GL_POLYGON_OFFSET_FILL);
 
  404          glPolygonOffset(1.f, 1.f);
 
  406          glDisable(GL_POLYGON_OFFSET_FILL);
 
  408          if (!fSelectionPass && it->fHighlight) {
 
  409             const TGLDisableGuard lightGuard(GL_LIGHTING);
 
  410             const TGLEnableGuard  blendGuard(GL_BLEND);
 
  411             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
  412             glColor4d(1., 0.4, 0., 0.5);
 
  417       if (needSecondPass) {
 
  418          const TGLEnableGuard  blendGuard(GL_BLEND);
 
  419          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
  420          glDepthMask(GL_FALSE);
 
  421          for (ConstSurfIter_t it = fIsos.begin(); it != fIsos.end(); ++it) {
 
  423             if (it->fAlpha == 100)
 
  428             glEnable(GL_POLYGON_OFFSET_FILL);
 
  429             glPolygonOffset(1.f, 1.f);
 
  431             glDisable(GL_POLYGON_OFFSET_FILL);
 
  433             if (!fSelectionPass && it->fHighlight) {
 
  434                const TGLDisableGuard lightGuard(GL_LIGHTING);
 
  435                glColor4d(1., 0.4, 0., it->fAlpha / 150.);
 
  439          glDepthMask(GL_TRUE);
 
  443    if (fBoxCut.IsActive())
 
  444       fBoxCut.DrawBox(fSelectionPass, fSelectedPart);
 
  450 void TGL5DPainter::SetSurfaceColor(ConstSurfIter_t it)
const 
  452    Color_t ind = it->fColor;
 
  453    Float_t rgba[] = {0.f, 0.f, 0.f, 
static_cast<Float_t
>(it->fAlpha / 100.)};
 
  454    Rgl::Pad::ExtractRGBA(ind, rgba);
 
  456    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, rgba);
 
  457    const Float_t specColor[] = {1.f, 1.f, 1.f, 1.f};
 
  458    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specColor);
 
  459    glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 20.f);
 
  465 void TGL5DPainter::DrawCloud()
const 
  467    const TGLDisableGuard light(GL_LIGHTING);
 
  468    const TGLDisableGuard depth(GL_DEPTH_TEST);
 
  470    glColor3d(0.4, 0., 1.);
 
  475    const Double_t xs = fCoord->GetXScale();
 
  476    const Double_t ys = fCoord->GetYScale();
 
  477    const Double_t zs = fCoord->GetZScale();
 
  479    for (Int_t i = 0; i < fData->fNP; ++i)
 
  480       glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
 
  490 void TGL5DPainter::DrawSubCloud(Double_t v4, Double_t range, Color_t ci)
const 
  492    const TGLDisableGuard light(GL_LIGHTING);
 
  494    Float_t rgba[4] = {};
 
  495    Rgl::Pad::ExtractRGBA(ci, rgba);
 
  502    const Double_t xs = fCoord->GetXScale();
 
  503    const Double_t ys = fCoord->GetYScale();
 
  504    const Double_t zs = fCoord->GetZScale();
 
  506    for (Int_t i = 0; i < fData->fNP; ++i)
 
  507       if (TMath::Abs(fData->fV4[i] - v4) < range)
 
  508          glVertex3d(fData->fV1[i] * xs, fData->fV2[i] * ys, fData->fV3[i] * zs);
 
  518 void TGL5DPainter::DrawMesh(ConstSurfIter_t surf)
const 
  520    const Mesh_t &m = surf->fMesh;
 
  522    if (!fBoxCut.IsActive()) {
 
  524          Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris);
 
  526          Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
 
  527          Rgl::DrawMesh(m.fVerts, m.fTris);
 
  530       if (!fSelectionPass) {
 
  531          Rgl::DrawMesh(m.fVerts, m.fNorms, m.fTris, fBoxCut);
 
  533          Rgl::ObjectIDToColor(fSelectionBase, fHighColor);
 
  534          Rgl::DrawMesh(m.fVerts, m.fTris, fBoxCut);