3D图形Texture(纹理贴图)

“`
package com.example.tyxiong.myapplication;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.view.View;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/*OpenGL与3D开发.

*2句概述:
* OpenGL是跨平台,跨语言的开放图形库接口. 主要是用于3D图形开发.
* Android系统内置了OpenGL ES支持. OpenGL ES是OpenGL的子集.–只支持绘制三角形
* 对于2D(平面)的三角形而言,由三个点构成,每个点的坐标由(x,y)值构成.三个顶处理同一平面上.只需要提供每个顶点的坐标值即可
* 对于3D(立体)的三棱锥而言,由4个顶点构成,每个顶点的坐标由(x,y,x)值构成,各顶点不在同一平面,需要提供2方面数据:1 3D图形每个顶点的坐标值. 2 3D图形每个平面由哪些顶点组成.
*
* 三维坐标系:与数学里坐标系相同(屏幕中心点为坐标原点)
*
* Android5.0支持OpenGL ES3.1 android有opengl包, 3工具类:GLSurfaceView GLU GLUtils 功能强大.
*
* OpenGL ES绘制2D图形:
* GLSurfaceView组件用于显示3D图形,其中GLSurfaceView.Renderer来完成绘制SurfaceView中的3D图形. 使用分3步:
* 1 创建GLSurfaceView组件,并用Activity显示.
* 2 创建GLSurfaceView.Renderer接口的子类实例–实现3个方法(方法中有GL10参数 表示画笔)
* 2-1 onSurfaceCreate()–Surface被创建时回调,方法内常进行初始化GL10参数.
* 2-2 onSurfaceChanged()–Surface被改变回调,常进行3D场景的设置.
* 2-3 onDrawFrame()–代表绘制的当前帧,绘制3D图形.
* 3 调用GLSurfaceView的setRenderer()方法来指定Renderer对象.
*
* 调用GL10绘制2D(平面)图形的步骤 6步: 只需要提供所有顶点的坐标值.glDrawArrays(mode,first,count)
* 1 glEnableClientState(GL10.GL_VERTEX_ARRAY)启用顶点数组.
* 2 glEnableClientState(GL10.GL_COLOR_ARRAY)启动顶点颜色数组
* 3 glVertexPointer(size,type,stride,pointer)设置顶点坐标值. 每个顶点的值组成元素个数3 值类型int/fix float 步幅0 坐标值数据(一维形如x1,y1,z1)
* 4 glColorPointer(size,type,stride,pointer) 设置顶点颜色值.(rgbn)4
* 5 glDrawArrays(mode,first,count)绘制2D图形(平面) GL10.GL_TRIANGLES三角形/GL10.GL_TRIANGLE_STRIP多三角形. 开始顶点 顶点总数.
* 6 glFinish()结束绘制,glDisableClientState(int)停用顶点坐标和颜色数据.
*
*
* 绘制3D图形,(立方体)用到方法 glDrawElements(mode,count,type,indices) indices包装了一个长度为3N(N为三角形数 3个顶点指定一个三角形)的数组
*
* 前面说了需要提供2方面数据:1 所有顶点的坐标值(x,y,z). 2 需要指定3D图形的每个平面由哪三个顶点组成.
* 1 所有顶点的坐标值.
* 2 需要建 indices数组来指定每个三角形由哪三个顶点组成.
* glDrawElements(mode,count,type,indices)//绘制3D图形,多个三角形 顶点总数(3*三角形数) 顶点indices里的元素类型 buffer
*
* 其它相同的操作..
* 下面用的三棱锥例子,比较简单,无须考虑顶点的排列方式(四面形,由多个三个角形组成顶点排列方式 当然可以用3Dmax软件自动生成 顶点坐标, 平面顶点组成)
*
*
* 为3D图形表面加上皮肤呢(纹理贴图)
* 1 在onSurfaceCreated方法中,加上gl.glEnable(GL10.GL_TEXTURE_2D)//启用2在纹理贴图
* 2 选择资源图片生成纹理.loadTexture()方法实现过程.
* 3 onDrawFrame()方法中启用贴图坐标数组数据 glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
* 设置贴图坐标数据 glTextCoordPointer()//这个弹性很大,可以用3dmax来实现纹理坐标.
* 执行纹理贴图 glBindTexture();
*
*
*
*
* */

public class MainActivity extends Activity {

GLSurfaceView surfaceView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    surfaceView = new GLSurfaceView(this);
    final MyRenderer myRenderer = new MyRenderer(this);

    surfaceView.setRenderer(myRenderer);
    surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);//绘制静图,无须刷新需要重绘时requestRenderer()节省cpu
    setContentView(surfaceView);
    surfaceView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            surfaceView.requestRender();//请求执行onDrawFrame()
        }
    });

}

}

class MyRenderer implements GLSurfaceView.Renderer {
private Context context;
private int texture;
private FloatBuffer pointerTexure;

public MyRenderer(Context context) {
    this.context = context;
}

float[] rectData = new float[]//三棱锥,4面(4个三角形 )4个顶点 上\左\右\里
        {
                0f, 1f, 0f,
                -1f, -1f, 0f,
                1f, -1f, 0f,
                0f, 0f, -1f

        };
int[] rectColor = new int[]//rgbn顶点的颜色值(3*4顶点颜色值重复了不必要)
        {
                65535, 0, 0, 0,
                0, 65535, 0, 0,
                0, 0, 65535, 0,
                0, 65535, 65535, 0

        };
float[] rectTexture=new float[]//图片左上角为(0f,0f)
        {
                0f,0f,
                0f,1f,
                1f,1f,
                1f,0f,

        };


byte[] indices = new byte[]//4个三角形的3*4顶点
        {

                0, 1, 2,
                0, 1, 3,
                0, 2, 3,
                1, 2, 3
        };

private float angle = 0f;

public FloatBuffer floatUtils(float[] floatArr) {//绘制方法要求数据为Buffer类型   float[]-->FloatBuffer[]
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(floatArr.length * 4);//要求用allocateDirect()方法,只有ByteBuffer有该方法,so
    byteBuffer.order(ByteOrder.nativeOrder());          //要求nativeOrder  Java 是大端字节序(BigEdian),
    // 而 OpenGL 所需要的数据是小端字节序(LittleEdian)
    FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
    floatBuffer.put(floatArr);
    floatBuffer.flip();
    return floatBuffer;
}

public IntBuffer intUtils(int[] intArr) {

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(intArr.length * 4);
    byteBuffer.order(ByteOrder.nativeOrder());
    IntBuffer intBuffer = byteBuffer.asIntBuffer();
    intBuffer.put(intArr);
    intBuffer.flip();
    return intBuffer;
}


@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {//对GL设置参数 关闭抗抖动 设置透视修正模式
    // 清屏黑色 平滑 开启深度测试 深度测试类型. 启用2D纹理贴图
    gl.glEnable(GL10.GL_TEXTURE_2D);//1
    gl.glDisable(GL10.GL_DITHER);
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
    gl.glClearColor(0, 0, 0, 0);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glDepthFunc(GL10.GL_LEQUAL);
    loadTexture(gl);//4
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {//3D视窗场景 视窗大小位置 投影矩阵
    // 重置绘制坐标原点 透视视窗宽高比 透视视窗空间大小
    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);//距离越远,小  映射坐标系设置为"投影矩阵"
    gl.glLoadIdentity();
    float ratio = (float) width / height;
    gl.glFrustumf(-ratio, ratio, -1f, 1f, 1f, 10f);//三维坐标系的值不是直接取屏幕像素,是根据该方法
    // 设置空间大小范围内可见最后2个参数为绝对值.
}

@Override
public void onDrawFrame(GL10 gl) {//绘制当图形 清除屏幕缓存深度缓存 开启顶点数据 顶点颜色 设置顶点数据
    // 颜色数据 绘制2D图形 绘制完成 关闭顶点&&颜色数据
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glMatrixMode(GL10.GL_MODELVIEW);//需要绘图时设置为"模型视图"
    gl.glLoadIdentity();
    gl.glTranslatef(0f, 0f, -2f);//改变绘图坐标原点
    gl.glRotatef(angle++, 0f, 0.5f, 0f);//y轴旋转
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    FloatBuffer pointerData = floatUtils(rectData);
    IntBuffer pointColor = intUtils(rectColor);
    pointerTexure = floatUtils(rectTexture);

    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, pointerData);
    gl.glColorPointer(4, GL10.GL_FIXED, 0, pointColor);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, pointerTexure);//5
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);

    gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 12, GL10.GL_UNSIGNED_BYTE, ByteBuffer.wrap(indices));//Byte[]类型可直接包装成Buffer
    //  gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glFinish();
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_COLOR_ARRAY);


}

public void loadTexture(GL10 gl) {//3 图片资源生成纹理贴图... 生成1个纹理存放textures数组中,0元素开始存放纹理代号
    //将纹理绑定到目标中,设置纹理放大/缩小 滤波方式 平铺 加载位图生成纹理.
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon6);
    int[] textures = new int[1];
    texture = textures[0];
    gl.glGenTextures(1, textures, 0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture);
    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);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

}

}

源图

纹理贴图效果

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Open3D是一个用于处理三维数据的库,它可以加载和显示OBJ文件,但是目前Open3D不支持OBJ纹理贴图。不过,你可以使用其他的库来加载和显示带有纹理贴图的OBJ文件,例如Assimp和OpenGL。 具体步骤如下: 1. 使用Assimp库来加载OBJ文件及其相关的纹理贴图。Assimp是一个用C++编写的开源库,可以处理多种三维模型格式,并支持加载纹理贴图。 2. 在OpenGL中创建纹理对象并将纹理贴图映射到OBJ模型上。OpenGL是一个强大的图形库,可以用来显示三维模型并进行纹理贴图。你可以使用OpenGL中的glTexImage2D函数创建纹理对象,并使用glTexCoordPointer函数将纹理坐标映射到OBJ模型的顶点上。 3. 在程序中添加代码,将纹理贴图应用到OBJ模型上。你可以使用OpenGL中的glBindTexture函数将纹理对象绑定到模型上,并使用glEnable函数启用纹理映射。 下面是一个简单的示例代码,使用Assimp和OpenGL实现OBJ纹理贴图: ```cpp #include <iostream> #include <GL/glut.h> #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> GLuint textureId; void loadTexture(const char* filename) { // Load image using SOIL library int width, height; unsigned char* image = SOIL_load_image(filename, &width, &height, 0, SOIL_LOAD_RGB); // Generate texture object glGenTextures(1, &textureId); // Bind texture object glBindTexture(GL_TEXTURE_2D, textureId); // Set texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Load texture data glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); // Free image data SOIL_free_image_data(image); } void drawModel(const char* filename) { // Load model using Assimp library Assimp::Importer importer; const aiScene* scene = importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs); if (!scene) { std::cerr << "Error loading model: " << importer.GetErrorString() << std::endl; return; } // Load texture loadTexture("texture.jpg"); // Enable texture mapping glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, textureId); // Draw model glPushMatrix(); glTranslatef(0.0f, -1.5f, 0.0f); glRotatef(90.0f, 1.0f, 0.0f, 0.0f); glColor3f(1.0f, 1.0f, 1.0f); for (unsigned int i = 0; i < scene->mNumMeshes; ++i) { const aiMesh* mesh = scene->mMeshes[i]; glBegin(GL_TRIANGLES); for (unsigned int j = 0; j < mesh->mNumFaces; ++j) { const aiFace& face = mesh->mFaces[j]; for (unsigned int k = 0; k < face.mNumIndices; ++k) { unsigned int index = face.mIndices[k]; glTexCoord2f(mesh->mTextureCoords[0][index].x, mesh->mTextureCoords[0][index].y); glVertex3f(mesh->mVertices[index].x, mesh->mVertices[index].y, mesh->mVertices[index].z); } } glEnd(); } glPopMatrix(); // Disable texture mapping glDisable(GL_TEXTURE_2D); } void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(0.0f, 0.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); drawModel("model.obj"); glutSwapBuffers(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800, 600); glutCreateWindow("OBJ Texture Mapping"); glutDisplayFunc(display); glEnable(GL_DEPTH_TEST); glutMainLoop(); return 0; } ``` 在这个示例代码中,我们使用Assimp库加载OBJ模型及其关联的纹理贴图,并使用OpenGL将纹理贴图映射到模型上。在drawModel函数中,我们首先调用loadTexture函数加载纹理贴图,然后使用glEnable函数启用纹理映射,并将纹理对象绑定到模型上。在绘制模型时,我们通过glTexCoord2f函数将纹理坐标映射到模型的顶点上。 需要注意的是,Assimp库和SOIL库需要安装并配置好环境。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋葵好吃吗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值