3d 绘图纹理

http://blog.csdn.net/hmg25/article/details/6740136

(球上纹理)

package com.ct.testmyfirst3d;

import android.app.Activity;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.LinearLayout;
import android.widget.ToggleButton;

public class TextureActivity extends Activity{
    TextureSurface mSurface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSurface = new TextureSurface(this);
        mSurface.requestFocus();
        mSurface.setFocusableInTouchMode(true);
        
        LinearLayout llLayout = (LinearLayout)findViewById(R.id.main_liner);
        llLayout.addView(mSurface);
        ToggleButton tb = (ToggleButton)findViewById(R.id.ToggleButton01);
        tb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // TODO Auto-generated method stub
                mSurface.setSmoothFlag(!mSurface.isSmoothFlag()); 
            }
        });
    }
    
}
package com.ct.testmyfirst3d;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.R.integer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

public class TextureSurface extends GLSurfaceView{

    private final float TOUCH_SCALE_FACTOR = 180.0f/320;
    private SceneRenderer mRenderer;
    private float mPreviousX;
    private float mPreviousY;
    private boolean smoothFlag = true;
    private int lightAngleaGreen;
    private int lightAngleRed;
    int textureId;
    public TextureSurface(Context context) {
        super(context);
        mRenderer = new SceneRenderer();
        setRenderer(mRenderer);
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
        
        // TODO Auto-generated constructor stub
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        float y = event.getY();
        float x = event.getX();
        switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:
            float dy = y - mPreviousY;//计算触控笔Y位移  
            float dx = x - mPreviousX;//计算触控笔Y位移  
            mRenderer.ball.mAngleX += dy * TOUCH_SCALE_FACTOR;//设置沿x轴旋转角度  
            mRenderer.ball.mAngleZ += dx * TOUCH_SCALE_FACTOR;//设置沿z轴旋转角度  
            requestRender();//重绘画面  
            break;

        default:
            break;
        }
        
         mPreviousY = y;//记录触控笔位置  
            mPreviousX = x;//记录触控笔位置  
            return true;  
    }
    
    public void setSmoothFlag(boolean smoothFlag){
        this.smoothFlag = smoothFlag;
    }
    
     public boolean isSmoothFlag() {  
            return smoothFlag;  
        }
     
    
    private class SceneRenderer implements GLSurfaceView.Renderer{
        Ball ball;
        public SceneRenderer(){
            new Thread(){

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    try{
                        Thread.sleep(1000);
                    }catch (Exception e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                    while (true) {
                        lightAngleaGreen+=5;
                        lightAngleRed+=5;
                        requestRender();
                        try {
                            Thread.sleep(50);
                        } catch (Exception e) {
                            // TODO: handle exception
                            e.printStackTrace();
                        }
                        
                    }
                }
                
            }.start();
        }
        @Override
        public void onDrawFrame(GL10 gl) {
            // TODO Auto-generated method stub
            if(smoothFlag){
                //进行平滑着色
                 gl.glShadeModel(GL10.GL_SMOOTH);
            }
            else {
                //相反的 
                gl.glShadeModel(GL10.GL_FLAT);
            }
            //设定绿色光源的位置  
            float lxGreen=(float)(7*Math.cos(Math.toRadians(lightAngleaGreen)));  
            float lzGreen=(float)(7*Math.sin(Math.toRadians(lightAngleaGreen)));  
            float[] positionParamsGreen={lxGreen,0,lzGreen,1};//最后的1表示使用定位光  
            gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, positionParamsGreen,0);   
              
            //设定红色光源的位置  
            float lyRed=(float)(7*Math.cos(Math.toRadians(lightAngleRed)));  
            float lzRed=(float)(7*Math.sin(Math.toRadians(lightAngleRed)));  
            float[] positionParamsRed={0,lyRed,lzRed,1};//最后的1表示使用定位光  
            gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, positionParamsRed,0);
            
          //清除颜色缓存  
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);  
            //设置当前矩阵为模式矩阵  
            gl.glMatrixMode(GL10.GL_MODELVIEW);  
            //设置当前矩阵为单位矩阵  
            gl.glLoadIdentity();       
              
            gl.glTranslatef(0, 0f, -1.8f);    
              
            gl.glPushMatrix();//保护变换矩阵现场  
            ball.drawSelf(gl);//绘制球  
            gl.glPopMatrix();//恢复变换矩阵现场 
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            // TODO Auto-generated method stub
             //设置视窗大小及位置   
            gl.glViewport(0, 0, width, height);  
            //设置当前矩阵为投影矩阵  
            gl.glMatrixMode(GL10.GL_PROJECTION);  
            //设置当前矩阵为单位矩阵  
            gl.glLoadIdentity();  
            //计算透视投影的比例  
            float ratio = (float) width / height;  
            //调用此方法计算产生透视投影矩阵  
            gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);  
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // TODO Auto-generated method stub
              //关闭抗抖动   
            gl.glDisable(GL10.GL_DITHER);  
            //设置特定Hint项目的模式,这里为设置为使用快速模式  
            gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);  
            //设置屏幕背景色黑色RGBA  
            gl.glClearColor(0,0,0,0);  
            //设置着色模型为平滑着色     
            gl.glShadeModel(GL10.GL_SMOOTH);//GL10.GL_SMOOTH  GL10.GL_FLAT  
            //启用深度测试  
            gl.glEnable(GL10.GL_DEPTH_TEST);  
              
            gl.glEnable(GL10.GL_LIGHTING);//允许光照      
              
            initGreenLight(gl);//初始化绿色灯  
            initRedLight(gl);//初始化红色灯  
            initMaterial(gl);//初始化材质  
              
            textureId=initTexture(gl,R.drawable.duke);//初始化纹理  
            ball=new Ball(4,textureId);  
        }  
        
        }
    //初始化绿色灯  
    private void initGreenLight(GL10 gl)  
    {  
        gl.glEnable(GL10.GL_LIGHT0);//打开0号灯    
          
        //环境光设置  
        float[] ambientParams={0.1f,0.1f,0.1f,1.0f};//光参数 RGBA  
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientParams,0);              
          
        //散射光设置  
        float[] diffuseParams={0f,1f,0f,1.0f};//光参数 RGBA  
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, diffuseParams,0);   
          
        //反射光设置  
        float[] specularParams={1f,1f,1f,1.0f};//光参数 RGBA  
        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, specularParams,0);       
    }  
    
    //初始化红色灯  
    private void initRedLight(GL10 gl)  
    {      
        gl.glEnable(GL10.GL_LIGHT1);//打开1号灯    
          
        //环境光设置  
        float[] ambientParams={0.2f,0.2f,0.2f,1.0f};//光参数 RGBA  
        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, ambientParams,0);              
          
        //散射光设置  
        float[] diffuseParams={1f,0f,0f,1.0f};//光参数 RGBA  
        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, diffuseParams,0);   
          
        //反射光设置  
        float[] specularParams={1f,1f,1f,1.0f};//光参数 RGBA  
        gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_SPECULAR, specularParams,0);   
    }  
    
    //初始化材质  
    private void initMaterial(GL10 gl)  
    {//材质为白色时什么颜色的光照在上面就将体现出什么颜色  
        //环境光为白色材质  
        float ambientMaterial[] = {1.0f, 1.0f, 1.0f, 1.0f};  
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, ambientMaterial,0);  
        //散射光为白色材质  
        float diffuseMaterial[] = {1.0f, 1.0f, 1.0f, 1.0f};  
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffuseMaterial,0);  
        //高光材质为白色  
        float specularMaterial[] = {1f, 1f, 1f, 1.0f};  
        gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, specularMaterial,0);  
        gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 100.0f);  
    }  
    public int initTexture(GL10 gl,int textureId)//textureId  
    {  
        int[] textures = new int[1];  
        gl.glGenTextures(1, textures, 0);      
        int currTextureId=textures[0];      
        gl.glBindTexture(GL10.GL_TEXTURE_2D, currTextureId);  
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);  
        gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);  
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,GL10.GL_REPEAT);  
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,GL10.GL_REPEAT);  
          
        InputStream is = this.getResources().openRawResource(textureId);  
        Bitmap bitmapTmp;   
        try   
        {  
            bitmapTmp = BitmapFactory.decodeStream(is);  
        }   
        finally   
        {  
            try   
            {  
                is.close();  
            }   
            catch(IOException e)   
            {  
                e.printStackTrace();  
            }  
        }  
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmapTmp, 0);  
        bitmapTmp.recycle();   
          
        return currTextureId;  
    }  
    
    
    
    
        
    }
    
    
package com.ct.testmyfirst3d;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;

import javax.microedition.khronos.opengles.GL10;

import android.R.integer;

public class Ball {

    private IntBuffer mVertexBuffer;//定点坐标数据缓冲
    private IntBuffer mNormalBuffer;//顶点向量数据缓冲
    
    private FloatBuffer mTextureBuffer;//顶点纹理数据缓冲
    public float mAngleX;
    public float mAngleY;
    public float mAngleZ;
    int vCount=0;//顶点数量  
    int textureId;//纹理ID  
    public Ball(int scale,int textureId){
        this.textureId = textureId;
        final int UNIT_SIZE=10000;  
        //实际顶点坐标数据的初始化================begin============================  
        ArrayList<Integer> alVertix=new ArrayList<Integer>();//存放顶点坐标的ArrayList  
        final int angleSpan=18;//将球进行单位切分的角度  
        for(int vAngle=-90;vAngle<=90;vAngle=vAngle+angleSpan)//垂直方向angleSpan度一份  
        {  
            for(int hAngle=0;hAngle<360;hAngle=hAngle+angleSpan)//水平方向angleSpan度一份  
            {//纵向横向各到一个角度后计算对应的此点在球面上的坐标  
                double xozLength=scale*UNIT_SIZE*Math.cos(Math.toRadians(vAngle));  
                int x=(int)(xozLength*Math.cos(Math.toRadians(hAngle)));  
                int z=(int)(xozLength*Math.sin(Math.toRadians(hAngle)));  
                int y=(int)(scale*UNIT_SIZE*Math.sin(Math.toRadians(vAngle)));  
                //将计算出来的XYZ坐标加入存放顶点坐标的ArrayList  
                alVertix.add(x);alVertix.add(y);alVertix.add(z);  
            }  
        }     
        vCount=alVertix.size()/3;//顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标  
          
        //将alVertix中的坐标值转存到一个int数组中  
        int vertices[] = new int[vCount*3];
            for(int i=0;i<alVertix.size();i++){
                vertices[i] = alVertix.get(i);
            }
            alVertix.clear();
            ArrayList<Float> alTexture = new ArrayList<Float>();
            
             int row=(180/angleSpan)+1;//球面切分的行数  
             int col=360/angleSpan;//球面切分的列数  
             
             for(int i=0;i<row;i++)//对每一行循环  
             {  
                 if(i>0&&i<row-1)  
                 {//中间行  
                     for(int j=-1;j<col;j++)  
                     {//中间行的两个相邻点与下一行的对应点构成三角形  
                         int k=i*col+j;  
                         //第1个三角形顶点                    
                         alVertix.add(vertices[(k+col)*3]);  
                         alVertix.add(vertices[(k+col)*3+1]);  
                         alVertix.add(vertices[(k+col)*3+2]);                      
                         alTexture.add(0.0f);alTexture.add(0.0f);  
                           
                         //第2个三角形顶点        
                         alVertix.add(vertices[(k+1)*3]);  
                         alVertix.add(vertices[(k+1)*3+1]);  
                         alVertix.add(vertices[(k+1)*3+2]);                    
                         alTexture.add(1.0f);alTexture.add(1.0f);  
                           
                         //第3个三角形顶点  
                         alVertix.add(vertices[k*3]);  
                         alVertix.add(vertices[k*3+1]);  
                         alVertix.add(vertices[k*3+2]);    
                         alTexture.add(1.0f);alTexture.add(0.0f);  
                     }  
                     for(int j=0;j<col+1;j++)  
                     {//中间行的两个相邻点与上一行的对应点构成三角形                 
                         int k=i*col+j;  
                           
                         //第1个三角形顶点                    
                         alVertix.add(vertices[(k-col)*3]);  
                         alVertix.add(vertices[(k-col)*3+1]);  
                         alVertix.add(vertices[(k-col)*3+2]);                      
                         alTexture.add(1f);alTexture.add(1f);  
                           
                         //第2个三角形顶点                    
                         alVertix.add(vertices[(k-1)*3]);  
                         alVertix.add(vertices[(k-1)*3+1]);  
                         alVertix.add(vertices[(k-1)*3+2]);                    
                         alTexture.add(0.0f);alTexture.add(0.0f);  
                           
                         //第3个三角形顶点                    
                         alVertix.add(vertices[k*3]);  
                         alVertix.add(vertices[k*3+1]);  
                         alVertix.add(vertices[k*3+2]);                    
                         alTexture.add(0f);alTexture.add(1f);      
                     }  
                 }  
             }  
               
             vCount=alVertix.size()/3;//顶点的数量为坐标值数量的1/3,因为一个顶点有3个坐标  
               
             //将alVertix中的坐标值转存到一个int数组中  
             vertices=new int[vCount*3];  
             for(int i=0;i<alVertix.size();i++)  
             {  
                 vertices[i]=alVertix.get(i);  
             }  
               
             //创建绘制顶点数据缓冲  
             ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);  
             vbb.order(ByteOrder.nativeOrder());//设置字节顺序  
             mVertexBuffer = vbb.asIntBuffer();//转换为int型缓冲  
             mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据  
             mVertexBuffer.position(0);//设置缓冲区起始位置       
               
             //创建顶点法向量数据缓冲  
             ByteBuffer nbb = ByteBuffer.allocateDirect(vertices.length*4);  
             nbb.order(ByteOrder.nativeOrder());//设置字节顺序  
             mNormalBuffer = vbb.asIntBuffer();//转换为int型缓冲  
             mNormalBuffer.put(vertices);//向缓冲区中放入顶点坐标数据  
             mNormalBuffer.position(0);//设置缓冲区起始位置  
               
             //创建纹理坐标缓冲  
             float textureCoors[]=new float[alTexture.size()];//顶点纹理值数组  
             for(int i=0;i<alTexture.size();i++)   
             {  
                 textureCoors[i]=alTexture.get(i);  
             }  
               
             ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4);  
             cbb.order(ByteOrder.nativeOrder());//设置字节顺序  
             mTextureBuffer = cbb.asFloatBuffer();//转换为int型缓冲  
             mTextureBuffer.put(textureCoors);//向缓冲区中放入顶点着色数据  
             mTextureBuffer.position(0);//设置缓冲区起始位置  
               
             //三角形构造顶点、纹理、法向量数据初始化==
            

        
    }
    
    public void drawSelf(GL10 gl){
        gl.glRotatef(mAngleZ, 0, 0, 1);//沿Z轴旋转  
        gl.glRotatef(mAngleX, 1, 0, 0);//沿X轴旋转  
        gl.glRotatef(mAngleY, 0, 1, 0);//沿Y轴旋转  
          
        //允许使用顶点数组  
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  
        //为画笔指定顶点坐标数据  
        gl.glVertexPointer  
        (  
                3,              //每个顶点的坐标数量为3  xyz   
                GL10.GL_FIXED,  //顶点坐标值的类型为 GL_FIXED  
                0,              //连续顶点坐标数据之间的间隔  
                mVertexBuffer   //顶点坐标数据  
        );  
          
        //允许使用法向量数组  
        gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);  
        //为画笔指定顶点法向量数据  
        gl.glNormalPointer(GL10.GL_FIXED, 0, mNormalBuffer);  
          
        //开启纹理  
        gl.glEnable(GL10.GL_TEXTURE_2D);     
        //允许使用纹理ST坐标缓冲  
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  
        //为画笔指定纹理ST坐标缓冲  
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);  
        //绑定当前纹理  
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);  
          
        //绘制图形  
        gl.glDrawArrays  
        (  
                GL10.GL_TRIANGLES,      //以三角形方式填充  
                0,                      //开始点编号  
                vCount                  //顶点数量  
        );
        
    }
}

(在F:\java\TestMyFirst3d)

原文地址:https://www.cnblogs.com/ct732003684/p/2933081.html