title: How to locate texture on sphere in jME3?
body: <p>I would like to place JPEG texture map on sphere. It works for me, but I want to rotate texture by 180 degrees. I.e I want image to start not from zero UV coordinates, but earlier.</p>
  
  <p><img src="https://i.stack.imgur.com/M962i.jpg" alt="enter image description here"></p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I have tried to reassign texture coordinates of a sphere. Texture coordinates are float, and I was hoping they are not constrained to the range of [0..1]. Otherwise it should placed my image into the region of [0..1 x 0..1].</p>
  
  <p>It did something like latter, but not precise:</p>
  
  <p><img src="https://i.stack.imgur.com/QDQ10.jpg" alt="enter image description here"></p>
  
  <p>I.e. entire image was put into small region of a sphere. But, this exact region, where it is located, corresponds with negative values of <code>U</code>, i.e. at the same longitude, where image margin was in previous experiment (top sphere).</p>
  
  <p>Why?</p>
  
  <p>Image is here: <a href="https://en.wikipedia.org/wiki/File:Equirectangular_projection_SW.jpg" rel="nofollow noreferrer">https://en.wikipedia.org/wiki/File:Equirectangular_projection_SW.jpg</a></p>
  
  <p>The code is follows:</p>
  
  <pre><code>package tests.com.jme3;
  
  import java.nio.FloatBuffer;
  
  import com.jme3.app.SimpleApplication;
  import com.jme3.font.BitmapText;
  import com.jme3.light.DirectionalLight;
  import com.jme3.material.Material;
  import com.jme3.math.ColorRGBA;
  import com.jme3.math.Quaternion;
  import com.jme3.math.Vector2f;
  import com.jme3.math.Vector3f;
  import com.jme3.scene.Geometry;
  import com.jme3.scene.VertexBuffer;
  import com.jme3.scene.VertexBuffer.Type;
  import com.jme3.scene.VertexBuffer.Usage;
  import com.jme3.scene.shape.Sphere;
  import com.jme3.util.BufferUtils;
  
  public class Try_TextureTransform  extends SimpleApplication {
  
      public static void main(String[] args) {
          Try_TextureTransform app = new Try_TextureTransform();
          app.setShowSettings(false);
          app.start(); // start the game
      }
  
      final float speed = 0.01f;
  
      BitmapText hudText;
      Sphere sphere1Mesh, sphere2Mesh;
      Material sphere1Mat, sphere2Mat;
      Geometry sphere1Geo, sphere2Geo;
      Quaternion orientation;
      DirectionalLight sun;
  
      @Override
      public void simpleInitApp() {
  
          flyCam.setEnabled(false);
          setDisplayStatView(false); 
          setDisplayFps(false);
  
  
          hudText = new BitmapText(guiFont, false);          
          hudText.setSize(guiFont.getCharSet().getRenderedSize());      // font size
          hudText.setColor(ColorRGBA.Blue);                             // font color
          hudText.setText("");             // the text
          hudText.setLocalTranslation(300, hudText.getLineHeight()*2, 0); // position
          guiNode.attachChild(hudText);
  
          sphere1Mesh = new Sphere(50, 50, 2);
          sphere1Mesh.setTextureMode(Sphere.TextureMode.Projected); // matrc
  
          sphere1Mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
          sphere1Mat.setTexture("ColorMap", assetManager.loadTexture("textures/Equirectangular_projection_SW.jpg"));
  
          sphere1Geo = new Geometry("Sphere2", sphere1Mesh);
          sphere1Geo.setMaterial(sphere1Mat); 
          sphere1Geo.setLocalTranslation(0, 0, 2);
  
          sphere2Mesh = new Sphere(50, 50, 2);
  
          VertexBuffer vb = sphere2Mesh.getBuffer(Type.Position);
          FloatBuffer fb = (FloatBuffer) vb.getData();
          float[] vertexCoordinates = BufferUtils.getFloatArray(fb);
  
          VertexBuffer vb2 = sphere2Mesh.getBuffer(Type.TexCoord);
          FloatBuffer fb2 = (FloatBuffer) vb2.getData();
          float[] uvCoordinates = BufferUtils.getFloatArray(fb2);
  
          double rho;
          for (int i = 0; i &lt; vertexCoordinates.length/3; ++i) {
  
              uvCoordinates[i*2] = (float) Math.atan2(vertexCoordinates[i*3+1], vertexCoordinates[i*3]);
              rho = Math.sqrt(Math.pow( vertexCoordinates[i*3], 2) + Math.pow( vertexCoordinates[i*3+1], 2));
              uvCoordinates[i*2+1] = (float) Math.atan2(vertexCoordinates[i*3+2], rho);
          }
        //apply new texture coordinates
          VertexBuffer uvCoordsBuffer = new VertexBuffer(Type.TexCoord);
          uvCoordsBuffer.setupData(Usage.Static, 2, com.jme3.scene.VertexBuffer.Format.Float, BufferUtils.createFloatBuffer(uvCoordinates));
          sphere2Mesh.clearBuffer(Type.TexCoord);
          sphere2Mesh.setBuffer(uvCoordsBuffer);
  
  
          //sphere2Mesh.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres
  
          sphere2Mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
          sphere2Mat.setTexture("ColorMap", assetManager.loadTexture("textures/Equirectangular_projection_SW.jpg"));
  
          sphere2Geo = new Geometry("Sphere2", sphere2Mesh);
          sphere2Geo.setMaterial(sphere2Mat); 
          sphere2Geo.setLocalTranslation(0, 0, -2);
  
          cam.setLocation(new Vector3f(-10, 0, 0));
          cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Z);
  
          rootNode.attachChild(sphere1Geo);
          rootNode.attachChild(sphere2Geo); 
  
      }
  
      @Override
      public void simpleUpdate(float tpf) {
  
  
          Vector2f cursorPosition = inputManager.getCursorPosition();
          Vector3f cursorPositionWorld = cam.getWorldCoordinates(cursorPosition, 1);
  
          orientation = new Quaternion().fromAngleAxis(cursorPositionWorld.z*speed, Vector3f.UNIT_Y);
          orientation.multLocal(new Quaternion().fromAngleAxis(-cursorPositionWorld.y*speed, Vector3f.UNIT_Z));
  
          rootNode.setLocalRotation(orientation);
  
  
  
      }
  
  }
  </code></pre>