openGL 关于3D图像的显示区域问题

诸葛非常的亮 2016-05-11 03:31:09
这样的,我做了个蓝牙接收主机发来的3D立体点数据,采用OpenGl进行绘制,但是3D图像只做绘制到一个新的View上,可我想将3D图像绘制到主界面的区域,请问该怎样做呢?


图一是主界面,图二是接收完数据后显示的3D模型界面
现在想实现的效果如下图


主界面代码如下
package com.caresono.hd2_pro;
import android.widget.Toast;//省略掉其他导入

public class MainActivity extends Activity implements OnTouchListener {

private final static int REQUEST_CONNECT_DEVICE = 1; // 宏定义查询设备句柄
private final static String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB"; // SPP服务UUID号

private static final String TAG = "MainActivity";
private static final boolean D = false;

final int IMAGE_NUM_LEN = 2;
final int VOLUME_LEN = 3;
final static int IMAGE_X_LEN = 50;
final static int IMAGE_Y_LEN = 50;
public static byte[][] ImageX = new byte[13][IMAGE_X_LEN];//0:预扫描 ;1-12 :扫描;13:和第一幅相同 送给显示3D
public static byte[][] ImageY = new byte[13][IMAGE_Y_LEN];
static String BladderVolume;
int volume = 0;//只做测试数据库使用
static String ImageNumber;
int IntImageNumber = 0;
// int BMP_LEN = 1078+248*200*2;
// byte[] BmpRecvBuf = new byte[BMP_LEN];

private InputStream is; // 输入流,用来接收蓝牙数据
private OutputStream os; // 输出流,用来发送蓝牙数据


BluetoothDevice _device = null; // 蓝牙设备
BluetoothSocket _socket = null; // 蓝牙通信socket
boolean _discoveryFinished = false;
boolean bRun = true;
boolean bThread = false;
boolean isBTConnect = false;
boolean CurrentBTDataValid = false;
private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter(); // 获取本地蓝牙适配器,即蓝牙设备

private static myView mmyView;// 自己写的myview
GLSurfaceView glView;//3Dview


private static TextView myTextViewCurrentVolume;
private static TextView myTextViewImageNumber;
private static Button myButtonConnect;
private static Button myButtonScan;
private static ImageButton myImageButtonPre;
private static ImageButton myImageButtonNext;

int SW, SH;// Screen Width and Screen High

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // 设置画面为主画面 main.xml

myTextViewCurrentVolume = (TextView) findViewById(R.id.TextViewCurrentVolume); // 得到数据显示句柄
myTextViewImageNumber = (TextView) findViewById(R.id.TextViewImageNumber);
myButtonConnect = (Button) findViewById(R.id.ButtonConnect);// 他的监听在xml里
myButtonScan = (Button) findViewById(R.id.ButtonScan);
myImageButtonPre = (ImageButton) findViewById(R.id.ImageButtonPre);
myImageButtonNext = (ImageButton) findViewById(R.id.ImageButtonNext);

myButtonScan.setOnTouchListener(this);
myImageButtonPre.setOnTouchListener(this);
myImageButtonNext.setOnTouchListener(this);

LinearLayout DrawArea = (LinearLayout) findViewById(R.id.LinearLayoutImage);// 定义一块画布
mmyView = new myView(MainActivity.this);// 定义一个新view
DrawArea.addView(mmyView);// 将新view添加到画布上

glView = new GLSurfaceView(this);



if (_bluetooth == null) {// 如果打开本地蓝牙设备不成功,提示信息,结束程序
Toast.makeText(this, "Unable to open the Bluetooth, make sure the phone has a Bluetooth function!", Toast.LENGTH_LONG).show();
finish();
return;
}

new Thread() {
public void run() {
if (_bluetooth.isEnabled() == false) {
_bluetooth.enable();
}
}
}.start();
}

public void onConnectButtonClicked(View v) {

}

public boolean onTouch(View v, MotionEvent event) {
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {// 接收活动结果,响应startActivityForResult()

}

Thread ReadThread = new Thread() {// 接收数据线程
};

static Handler handler = new Handler() {// 消息处理队列
public void handleMessage(Message msg) {
if (msg.what == 1) {
myTextViewImageNumber.setText("Current Image Number: " + ImageNumber);
mmyView.invalidate();
}
}
};

public class myView extends View {// 定义一个类,继承于view
public myView(Context context) {
super(context);
}

@SuppressLint("DrawAllocation")
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 把整张画布绘制成淡蓝色
// canvas.drawColor(Color.CYAN);
Paint paint = new Paint();
paint.setAntiAlias(true);// 去锯齿
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);

if (IntImageNumber >= 0 && IntImageNumber < 12) {// 防止数据错乱乱
for (int i = 0; i < IMAGE_X_LEN - 2; i++) {// 当j<len时程序会异常
// 因为data[j+1]已经超出了接收数据大小了
canvas.drawLine(SW / 125 * (ImageX[IntImageNumber][i] + 5), SW / 125 * ImageY[IntImageNumber][i] + 50,// 5为调整中线系数
SW / 125 * (ImageX[IntImageNumber][i + 1] + 5), SW / 125 * ImageY[IntImageNumber][i + 1] + 50, paint);
}
canvas.drawLine(SW / 125 * (ImageX[IntImageNumber][IMAGE_X_LEN - 2] + 5), SW / 125 * ImageY[IntImageNumber][IMAGE_Y_LEN - 2] + 50,
SW / 125 * (ImageX[IntImageNumber][0] + 5), SW / 125 * ImageY[IntImageNumber][0] + 50, paint);
}
if(IntImageNumber == 12){
// 创建GLSurfaceView的内容绘制器
MyRenderer myRender = new MyRenderer();
// 为GLSurfaceView设置绘制器
glView.setRenderer(myRender);
setContentView(glView);//这里显示占满了主界面,而我想只显示到mmyview上,不知道该怎样修改?

}
}
}

public void onDestroy() {
super.onDestroy();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}

myRender如下:
package com.caresono.hd2_pro;

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

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

import android.opengl.GLSurfaceView.Renderer;

public class MyRenderer implements Renderer
{
float[] BladderVertices = new float[BLADDER_SECTION*BLADDER_POINT*3];
int[] BladderColors = new int[BLADDER_SECTION*BLADDER_POINT*4];
short[] BladderFacets = new short[(BLADDER_SECTION)*(BLADDER_POINT*2 - 2)*3];

FloatBuffer BladderVerticesBuffer;
ShortBuffer BladderFacetsBuffer;
IntBuffer BladderColorsBuffer;

private float rotate;//控制旋转的角度

public MyRenderer()
{
BladderVerticesBuffer = floatBufferUtil(BladderVertices);
BladderFacetsBuffer = shortBufferUtil(BladderFacets);
BladderColorsBuffer = intBufferUtil( BladderColors);
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// 关闭抗抖动
gl.glDisable(GL10.GL_DITHER);
// 设置系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glClearColor(0.5f, 0.6f, 0.7f, 0f);//清屏RGBa,单位 GLclampf
// 设置阴影平滑模式
gl.glShadeModel(GL10.GL_SMOOTH);//默认没有
gl.glClearDepthf(1.0f);//如果初始值指定为0.5, 那么物体就只有深度小于0.5的那部分才是可见的
// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
// 设置深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
}

@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;//0.5625
// 调用此方法设置透视视窗的空间大小。视景体
gl.glFrustumf(-ratio/*left*/, ratio/*right*/, -1/*bottom*/, 1/*top*/, 1/*near*/, 1000/*far*/);
}

// 绘制图形的方法
@Override
public void onDrawFrame(GL10 gl)
{
// 清除屏幕缓存和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 启用顶点座标数据
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 启用顶点颜色数据
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
// 设置当前矩阵堆栈为模型堆栈,
gl.glMatrixMode(GL10.GL_MODELVIEW);
// --------------------绘制第4个图形---------------------
// 重置当前的模型视图矩阵
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -1.5f);
gl.glRotatef(rotate, 0f, 0.5f, 0f);
// 设置顶点的位置数据
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, BladderVerticesBuffer);//一个点占据的坐标个数

// 按cubeFacetsBuffer指定的面绘制三角形
gl.glColorPointer(4, GL10.GL_FIXED, 0,BladderColorsBuffer);
//由于GL10里面没用GL_UNSIGNED_INT选项,因此将其封装成short类型;
//之前是封装成byte,但byte最多显示256个面,当面大于256时就忽略掉,而short可以显示65536个面;
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP//GL10.GL_LINE_STRIP//显示所有线//GL10.GL_POINTS//显示所有点
, BladderFacetsBuffer.remaining(),
GL10.GL_UNSIGNED_SHORT, BladderFacetsBuffer);

// 绘制结束
gl.glFinish();
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
// 旋转角度增加1
rotate+=1;
}

//自己写一个short封装工具
private ShortBuffer shortBufferUtil(short[] arr)
{
ShortBuffer mBuffer;
//申请内存,初始化ByteBuffer,长度为arr数组的长度*2,因为一个short占2个字节
ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 2);
////设置字节顺序,其中ByteOrder.nativeOrder()是获取本机字节顺序
qbb.order(ByteOrder.nativeOrder());
//转换为short型
mBuffer = qbb.asShortBuffer();
//添加数据
mBuffer.put(arr);
//设置缓冲区起始位置
mBuffer.position(0);
return mBuffer;
}

// 定义一个工具方法,将int[]数组转换为OpenGL ES所需的IntBuffer
private IntBuffer intBufferUtil(int[] arr)
{
IntBuffer mBuffer;
ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
qbb.order(ByteOrder.nativeOrder());
mBuffer = qbb.asIntBuffer();
mBuffer.put(arr);
mBuffer.position(0);
return mBuffer;
}

// 定义一个工具方法,将float[]数组转换为OpenGL ES所需的FloatBuffer
private FloatBuffer floatBufferUtil(float[] arr)
{
FloatBuffer mBuffer;
ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
qbb.order(ByteOrder.nativeOrder());
mBuffer = qbb.asFloatBuffer();
mBuffer.put(arr);
mBuffer.position(0);
return mBuffer;
}
}
...全文
360 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
JPF1024 2016-05-11
  • 打赏
  • 举报
回复
去OpenGL群问问,没搞过这个啊。。。。。。

80,337

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧