4.19 How to render a textured sphere in OpenGL?

In OpenGL, you can map a texture to a solid sphere by using gluSphere and gluQuadricTexture APIs in OpenGL GLU library.
In this example, we have used the OpenGLTexturedSphere.

OpenGLObject

  OpenGLTexture

    OpenGLTexture2D
    
      OpenGLTexturedSphere


The following TexturedSphereRotationByKeyInput is a simple example to draw a textured shpere and rotate it by Left or Rigth keys.

In this example, we have used the world map of 'world.topo.bathy.200412.3x5400x2700.jpg' file in the following page.
NASA VISIBLE EARTH
December, Blue Marble Next Generation w/ Topography and Bathymetry
Credit: Reto Stockli, NASA Earth Observatory

We have used the following world map file based on the 'world.topo.bathy.200412.3x5400x2700.jpg'.







/*
 * TexturedSphereRotationByKeyInput.cpp 
 * Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


//2017/02/28

// We have used 'world.topo.bathy.200412.3x5400x2700.jpg' file in the following page.
//
//http://visibleearth.nasa.gov/view.php?id=73909
//
//December, Blue Marble Next Generation w/ Topography and Bathymetry
//Credit: Reto St?ckli, NASA Earth Observatory


#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/OpenGLTexturedSphere.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;
  public:
    virtual void display()
    {
      if (gc && texture) {
        gc -> loadIdentity();
        gc -> clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        gc -> clearColor(0.1, 0.1, 0.2, 1.0);
        gc -> enable(GL_CULL_FACE); 
        gc -> enable(GL_LIGHTING);

        gc -> enable(GL_DEPTH_TEST);
        gc -> color(1.0f, 1.0f, 1.0f);
        gc -> lookAt(0.0, 6.0, 2, 0.0, 0.0, 0.0, 0.0, 100.0, 0.0);

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

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

        OpenGLLight light(GL_LIGHT0);
        GLfloat lightPosition[] = {10, 20, 0, 1.0}; 
        light.position(lightPosition);
    
        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, 100.0);
        gc -> matrixMode(GL_MODELVIEW);
        gc -> loadIdentity() ;
      }
    }

    virtual void initialize()
    {
      axis.x = 20.0f;
      axis.y = -30.0f;
      axis.z = 40.0f;
      gc = new OpenGLGC();
      gc -> enable(GL_DEPTH_TEST);
      gc -> enable(GL_TEXTURE_2D);
      try {
        // The 'world.topo.bathy.200412.3x860x430.jpg' used here is based on
        // 'world.topo.bathy.200412.3x5400x2700.jpg' in the following page.
        //
        //http://visibleearth.nasa.gov/view.php?id=73909
        //
        //December, Blue Marble Next Generation w/ Topography and Bathymetry
        //Credit: Reto St?ckli, NASA Earth Observatory
        const char* imageFileName = "./images/world.topo.bathy.200412.3x860x430.jpg";

        ModuleFileName module;
        const char* appName = module.getAppName();
        
        texture = new OpenGLTexturedSphere(imageFileName, 2.5f, 40, 40);
        char title[1024];
        sprintf_s(title, CountOf(title), "%s - %s", "world.topo.bathy.200412.3: Reto Stockli, NASA Earth Observatory", 
              appName);
        View* parent=getParent();
        parent->setText(title);
        
      } catch (Exception& ex) {
        caught(ex);
      }
      
    }

   virtual void keyDown(Event& event)
    {
      WPARAM vkey = event.getWParam();
      switch (vkey) {
      case VK_LEFT:
        angle += 2.0;
        postRenderRequest();
        break;
      case VK_RIGHT:
        angle -= 2.0;
        postRenderRequest();
        break;
      default:
        break;
      }
    }
    
  public:
    SimpleView(View* parent, const char* name, Args& args)
    :OpenGLView(parent, name, args),
    angle(120.0f)
    {
    } 

    ~SimpleView()
    {
    }
  };
  //Inner class ends.
  
private:
  SmartPtr<SimpleView>  view;

  long size(Event& event)
  {
    int w, h;
    event.getSize(w, h);
    if (view) {
      view -> reshape(0, 0, w, h);
      view -> postResizeRequest(w, h);
    }
    return 1L;
  }


  virtual long keyDown(Event& event)
  {
    if (view) {
      view -> keyDown(event);
    }
    return 0;
  }
  
public:
  MainView(Application& applet, const char* name, Args& args)
  :OpenGLMainView(applet, name, args)
  {
    addEventHandler(WM_KEYDOWN, this,
              (Handler)&MainView::keyDown, NULL);
    Args ar;
    view = new SimpleView(this, "", ar);
  }

  ~MainView()
  {
  }
};
}

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

    Args args;
    args.set(XmNwidth,  600);
    args.set(XmNheight, 600);

    MainView view(applet, name, args);
    view.realize();

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


Last modified: 25 Feb 2017

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