4.29 How to render a textured sphere with Axis, Eye, and Light Positioner in OpenGL?

As you know, in OpenGL, you can easily map a texture to a solid sphere by using gluSphere and gluQuadricTexture APIs in OpenGL GLU library.
In this example, we have used the following classes.
  AxisPositioner

  EyePositioner

  LightPositioner

  OpenGLTexturedSphere

The following TexturedSphereWithAxisEyeLightPositioner is a simple example to render and rotate a textured sphere by dynamically changing an axis position, an eye position, and light position respectively.

In this example, we have used Venus map 'ven0aaa2.jpg' Caltech/JPL/USGS in JPL NASA SOLAR SYSTEM SIMULATOR .





We have also used the following Lunar Orbiter's 'Lunar_LO_UVVISv2_Hybrid_Mosaic_Global_1024.jpg' in Astrogeology Science Center.





Furthermore, we have used the following Voyager Galileo IO 'jup1vss2.jpg' in the page JPL NASA SOLAR SYSTEM SIMULATOR




/*
 * TexturedSphereWithAxisEyeLightPositioner.cpp 
 * Copyright (c) 2017 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


//2017/11/23 
//W have used the following venus image file 'ven0aaa2.jpg' create by Caltech/JPL/USGS:
//
//  https://maps.jpl.nasa.gov/venus.html

#include <sol/Stdio.h>
#include <sol/Vector3.h>
#include <sol/LabeledTrackBar.h>

#include <sol/AxisPositioner.h>
#include <sol/EyePositioner.h>
#include <sol/LightPositioner.h>
#include <sol/FileDialog.h>

#include <sol/opengl/OpenGLMainView.h>
#include <sol/opengl/OpenGLView.h>
#include <sol/opengl/OpenGLGC.h>
#include <sol/opengl/OpenGLLight.h>
#include <sol/opengl/OpenGLMaterial.h>

#include <sol/opengl/Vertex3.h>
#include <sol/opengl/OpenGLLight.h>
#include <sol/opengl/OpenGLMaterial.h>
#include <sol/opengl/OpenGLTexturedSphere.h>

#include "Resource.h"

namespace SOL {

class MainView :public OpenGLMainView {

private:
  ///////////////////////////////////////////////////////////
  //Inner class starts
  class SimpleView: public OpenGLView {
  private:
    SmartPtr<OpenGLGC>          gc;
    SmartPtr<OpenGLTexturedSphere> texture;
    float                       angle;
    
    Vertex3                     axis;
    Vector3                     veye;
    Vector3                     vlight;
    
  public:
    virtual void display()
    {
      if (gc && texture) {
        gc->loadIdentity();
        gc->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        gc->loadIdentity();

        gc->clearColor(0.0, 0.0, 0.0, 1.0);
        gc->enable(GL_LIGHTING);

        gc->enable(GL_DEPTH_TEST);
        gc->color(1.0f, 1.0f, 1.0f);
        gc->lookAt(veye.x, veye.y, veye.z, 0.0, 0.0, 0.0, 0.0, 6.0, 0.0);

        gc->translate(0.0f, 0.0f, 0.0f);

        gc->rotate(angle, axis.x, axis.y, axis.z);

        OpenGLLight light(GL_LIGHT0);
        light.position(vlight.x, vlight.y, vlight.z, 0.0f);
    
        GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f};
        GLfloat blue[]  = {0.0f, 0.0f, 1.0f, 1.0f};
        GLfloat shininess[] = {100.0};
        OpenGLMaterial material(GL_FRONT);
        material.diffuse(blue);
        material.specular(white);
        material.shininess(shininess);
            
        texture -> draw(gc);
      }
    }
  
    virtual void resize(int w, int h)
    {
      if (w == 0 || h == 0) {
        return;
      }
      if (gc) {
        const float r = (float) w / (float) h;

        gc -> matrixMode(GL_PROJECTION);
        gc -> loadIdentity();
        gc -> frustum(r, -r, -1.0, 1.0, 2.0, 30.0);
        gc -> matrixMode(GL_MODELVIEW);
        gc -> loadIdentity() ;
      }
    }

    void createTexture(const char* filename)
    {
      try {
        texture = NULL;
        texture = new OpenGLTexturedSphere(filename, 2.5f, 40, 40);
      } catch (Exception& ex) {
        caught(ex);
      }
    }
    
    virtual void initialize()
    {
      gc = new OpenGLGC();
      gc -> enable(GL_DEPTH_TEST);
      gc -> enable(GL_TEXTURE_2D);
      try {
        //https://maps.jpl.nasa.gov/venus.html
        const char* filename = "./images/ven0aaa2.jpg";
        //const char* filename = "./images/Lunar_Clementine_UVVIS_750nm_Global_Mosaic_1024.jpg";
        
        MainView* parent= (MainView*)getParent();
        parent->openFile(filename); 
      } catch (Exception& ex) {
        caught(ex);
      }
    }

  public:
    SimpleView(View* parent, const char* name, Args& args)
    :OpenGLView(parent, name, args),
    angle(120.0f)
    {
    } 

    ~SimpleView()
    {
    }

    void setAngle(int value)
    {
      angle =value;
      postRenderRequest();
    }
    
    void setAxisPosition(int x, int y, int z)
    {
      axis.x = (float)x;
      axis.y = (float)y;
      axis.z = (float)z;
      postRenderRequest();
    }

    void setEyePosition(int x, int y, int z)
    {
      veye.x = (float)x;
      veye.y = (float)y;
      veye.z= (float)z;
      postRenderRequest();
    }

    void setLightPosition(int x, int y, int z)
    {
      vlight.x = (float)x;
      vlight.y = (float)y;
      vlight.z = (float)z;
      postRenderRequest();
    }
  };
  //Inner class ends.
  ///////////////////////////////////////////////////////////
  
private:
  SmartPtr<SimpleView>      view;
  SmartPtr<LabeledTrackBar> rotator;
  
  SmartPtr<AxisPositioner>  axisPositioner;
  SmartPtr<EyePositioner>   eyePositioner;
  SmartPtr<LightPositioner> lightPositioner;
  FileDialog                filedlg;
  
  long size(Event& event)
  {
    int w, h;
    event.getSize(w, h);
    if (view && rotator && eyePositioner && lightPositioner) {
      int posw = eyePositioner->getDefaultWidth();
      int posh = eyePositioner->getDefaultHeight();
      int rth  = rotator->getDefaultHeight();
      
      view -> reshape(0, 0, w-posw-4, h);
      view -> postResizeRequest(w-posw-4, h);
      rotator->reshape(w-posw-2, 2, posw, rth);
      int posy = rth + 4;
      axisPositioner->reshape(w-posw-2, posy, posw, posh);
      eyePositioner->reshape(w-posw-2,  posy+posh+2, posw, posh);
      lightPositioner->reshape(w-posw-2,posy+(posh+2)*2, posw, posh);
    }
    return 1L;
  }

  virtual void angleChanged(Action& action)
  {
    if (view && rotator) {
      int angle = rotator->getPosition();
      view -> setAngle(angle);
    }
  }
  
  
  virtual long axisPositionChanged(Event& event)
  {   
    if (view && axisPositioner) {
      view -> setAxisPosition(axisPositioner->getX(), 
                           axisPositioner->getY(),
                           axisPositioner->getZ());
    }
    return 0;
  }

  virtual long eyePositionChanged(Event& event)
  {   
    if (view && eyePositioner) {
      view -> setEyePosition(eyePositioner->getX(), 
                           eyePositioner->getY(),
                           eyePositioner->getZ());
    }
    return 0;
  }
  
  virtual long lightPositionChanged(Event& event)
  {
    if (view && lightPositioner) {
      view -> setLightPosition(lightPositioner->getX(),
                             lightPositioner->getY(),
                             lightPositioner->getZ());
    }
    return 0;
  }

public:
  MainView(Application& applet, const char* name, Args& args)
  :OpenGLMainView(applet, name, args.set(XmNstyle, WS_CLIPCHILDREN|WS_CLIPSIBLINGS))
  {
    Args ar;
    view = new SimpleView(this, "", ar);

    ar.reset();
    ar.set(XmNminimum, -180);
    ar.set(XmNmaximum,  180);
    ar.set(XmNheight,    60);
    ar.set(XmNposition, 127);
    ar.set(XmNlabelString, "Rotator");
    rotator = new LabeledTrackBar(this, "", ar);
    rotator->addCallback(XmNtrackBarScrollCallback, this,
      (Callback)&MainView::angleChanged, NULL);
 
    ar.reset();
    ar.set(XmNminimum, -100);
    ar.set(XmNmaximum,  100);
    ar.set(XmNlabelString, "AxisPositioner [-100, 100]");
    axisPositioner = new AxisPositioner(this, "", ar);
    int axisX = -10;//  7;
    int axisY = -50; //-68;
    int axisZ =  80; //85;
 
    axisPositioner->setThumbPosition(axisX, axisY, axisZ);
    view ->setAxisPosition(axisX, axisY, axisZ);

    ar.reset();
    ar.set(XmNminimum, -200);
    ar.set(XmNmaximum,  200);
    ar.set(XmNlabelString, "EyePositioner [-200, 200]");    
    eyePositioner = new EyePositioner(this, "", ar);
    int eyeX =  0;
    int eyeY =  6;
    int eyeZ =  2;
    eyePositioner->setThumbPosition(eyeX, eyeY, eyeZ);
    view -> setEyePosition(eyeX, eyeY, eyeZ);

    ar.reset();
    ar.set(XmNminimum, -200);
    ar.set(XmNmaximum,  200);
    ar.set(XmNlabelString, "LightPositioner [-200, 200]");
    lightPositioner = new LightPositioner(this, "", ar);
    int lightX =  21;
    int lightY = -10;
    int lightZ =   2;
    lightPositioner->setThumbPosition(lightX, lightY, lightZ);
    view -> setLightPosition(lightX, lightY, lightZ);

    addEventHandler(axisPositioner->getPositionChangedMessage(), this, 
      (Handler)&MainView::axisPositionChanged, NULL);

    addEventHandler(eyePositioner->getPositionChangedMessage(), this, 
      (Handler)&MainView::eyePositionChanged, NULL);

    addEventHandler(lightPositioner->getPositionChangedMessage(), this, 
      (Handler)&MainView::lightPositionChanged, NULL);
    view -> postRenderRequest();

    
    ar.reset();
    ar.set(XmNfilter, FileDialog::getImageFilesFilter());
    filedlg.create(this, "OpenFile", ar);  
  }

  ~MainView()
  {
  }
  
  void openFile(const char* filename)
  {
    try {
      view -> createTexture(filename);
      view -> postRenderRequest();

      ModuleFileName module;
      const char* appName = module.getAppName();
      const char* name = filename;
      const char* slash = strrchr(filename, '\\');
      if (slash) {
        name = ++slash;
      }
      
      char title[MAX_PATH];
      sprintf_s(title, CountOf(title), "%s - %s", name,  appName);
      setText(title);        
    } catch (Exception& ex) {
      caught(ex);
    }
  }

  virtual void open(Action& action)
  {
    Args ar;    
    char dir[MAX_PATH] = { 0 };
    if (restoreFileFolder(dir, CountOf(dir))) {
      ar.set(XmNdirectory, dir);
      filedlg.setValues(ar);
    }

    try {    
      if(filedlg.open()) {
        const char* filename = filedlg.getFileName();
        saveFileFolder(filename);

        openFile(filename);
      }
    } catch (Exception& ex) {
      caught(ex);
    }
  }
};
}

//
void Main(int argc, char** argv) 
{
  try {    
    const char*  name = appName(argv[0]);
    Application applet(name, argc, argv);

    Args args;
    args.set(XmNwidth,  840);
    args.set(XmNheight, 490);
    
    MainView view(applet, name, args);
    view.realize();

    applet.run();
    
  } catch (Exception& ex) {
    caught(ex);
  }
}


Last modified: 24 Nov. 2017

Copyright (c) 2017 Antillia.com ALL RIGHTS RESERVED.