####一、下载bullet
由于我访问不了githubt,所以使用的是国内gitee的,
git clone https://gitee.com/hejuncheng1/bullet3.git
####二、android引入
使用android studio创建native c++程序
将下载的bullet的目录里的src和下面的BulletCollision、BulletDynamics、BulletSoftBody、clew、LinearMath目录,以及btBulletCollisionCommon.h和btBulletDynamicsCommon.h文件复制到cpp目录下
这里没有用bullet3和opencl保留了最基本的bullet功能
修改最外层CMakeLists.txt的内容,将bullet的内容编译进anative共享库
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.8)
# Declares and names the project.
project("anative")
file(GLOB_RECURSE SRC_DIR_LIST "./*.cxx" "./*.c" "./*.cpp")
#自动查找头文件路径函数(没有去重)
macro(FIND_INCLUDE_DIR result curdir) #定义函数,2个参数:存放结果result;指定路径curdir;
file(GLOB_RECURSE children "${curdir}/*.hpp" "${curdir}/*.h" ) #遍历获取{curdir}中*.hpp和*.h文件列表
message(STATUS "children= ${children}") #打印*.hpp和*.h的文件列表
set(dirlist "") #定义dirlist中间变量,并初始化
foreach(child ${children}) #for循环
string(REGEX REPLACE "(.*)/.*" "\\1" LIB_NAME ${child}) #字符串替换,用/前的字符替换/*h
if(IS_DIRECTORY ${LIB_NAME}) #判断是否为路径
LIST(APPEND dirlist ${LIB_NAME}) #将合法的路径加入dirlist变量中
endif() #结束判断
endforeach() #结束for循环
set(${result} ${dirlist}) #dirlist结果放入result变量中
endmacro()
#查找include目录下的所有*.hpp,*.h头文件,并路径列表保存到 INCLUDE_DIR_LIST 变量中
FIND_INCLUDE_DIR(INCLUDE_DIR_LIST ${PROJECT_SOURCE_DIR})
#将INCLUDE_DIR_LIST中路径列表加入工程
include_directories( #INCLUDE_DIR_LIST路径列表加入工程
${INCLUDE_DIR_LIST}
)
ADD_LIBRARY(anative SHARED ${SRC_DIR_LIST})
# Searches for a specified prebuilt library and stores the path as a
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
target_link_libraries( # Specifies the target library.
anative
# Links the target library to the log library
# included in the NDK.
${log-lib})
修改native-lib.cpp的内容,添加bullet的helloworld程序
#include
#include
#include
#include
#include "src/btBulletDynamicsCommon.h"
#define LOG_TAG "test"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
void test();
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_anative_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
test();
LOGE("dongtai=");
return env->NewStringUTF(hello.c_str());
}
///-----includes_start-----
void test(){
///-----includes_end-----
///-----initialization_start-----
// 创建碰撞配置对象以及碰撞调度器对象,使我们可以再各个阶段尝试不同的算法组合,目的是使用不同的算法和测试相同的碰撞
// 碰撞配置
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
// 碰撞调度
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
// btDbvtBroadphase用来执行快速碰撞检测 目的是尽量的剔除没有相互作用的对象对
///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
// 实际上的物理模拟器
// 创建解算器,用于求解约束方程。得到物体在重力等作用下的最终位置的
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
// 独立场景动态世界
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(
dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0, -10, 0)); // 设置重力加速度 Y向下
///-----initialization_end-----
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
btAlignedObjectArray<btCollisionShape*> collisionShapes;
///create a few basic rigid bodies
//创建一个地面,并加入到场景世界中
//the ground is a cube of side 100 at position y = -56.
//the sphere will hit it at y = -6, with center at -5
{
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.), btScalar(50.), btScalar(50.))); // 长方体
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0, -56, 0)); // 设置原点位置
btScalar mass(0.); // 质量
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0, 0, 0); // 惯性
if (isDynamic)
groundShape->calculateLocalInertia(mass, localInertia); //通过质量,这个函数计算出运动物体的惯性
// 运动状态
//using motionstate is optional, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
// 刚体构造信息
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, groundShape, localInertia);
// 刚体
btRigidBody* body = new btRigidBody(rbInfo);
// 将刚体添加至动态世界中
//add the body to the dynamics world
dynamicsWorld->addRigidBody(body);
}
{
//创建一个球体,并加入到场景世界中
//create a dynamic rigidbody
//btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
btCollisionShape* colShape = new btSphereShape(btScalar(1.)); // 球体 半径为1
collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
startTransform.setOrigin(btVector3(2, 10, 0));
btScalar mass(1.f); // 质量
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0, 0, 0); // 惯性
if (isDynamic)
colShape->calculateLocalInertia(mass, localInertia); //通过质量,这个函数计算出运动物体的惯性
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, colShape, localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
dynamicsWorld->addRigidBody(body);
}
/// Do some simulation
int i = 0;
// 步进模拟
///-----stepsimulation_start-----
for (i = 0; i < 150; i++)
{
dynamicsWorld->stepSimulation(1.f / 5.f, 10); // 模拟运动 每次进行物理模拟运算的时间间隔 每次能响应的最大step数
//print positions of all objects
for (int j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
btTransform trans;
if (body && body->getMotionState())
{
body->getMotionState()->getWorldTransform(trans);
}
else
{
trans = obj->getWorldTransform();
}
printf("world pos object %d = %f,%f,%f\n", j,
float(trans.getOrigin().getX()), float(trans.getOrigin().getY()), float(trans.getOrigin().getZ()));
LOGE("world pos object %d = %f,%f,%f\n", j,
float(trans.getOrigin().getX()), float(trans.getOrigin().getY()), float(trans.getOrigin().getZ()));
}
printf(" \n");
}
///-----stepsimulation_end-----
//cleanup in the reverse order of creation/initialization
///-----cleanup_start-----
//清理动态世界里的刚体
//remove the rigidbodies from the dynamics world and delete them
for (i = dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
dynamicsWorld->removeCollisionObject(obj);
delete obj;
}
//清理碰撞形状
//delete collision shapes
for (int j = 0; j < collisionShapes.size(); j++)
{
btCollisionShape* shape = collisionShapes[j];
collisionShapes[j] = 0;
delete shape;
}
//清理动态世界
//delete dynamics world
delete dynamicsWorld;
//清理求解器
//delete solver
delete solver;
//清理粗测阶段
//delete broadphase
delete overlappingPairCache;
//清理调度
//delete dispatcher
delete dispatcher;
delete collisionConfiguration;
//next line is optional: it will be cleared by the destructor when the array goes out of scope
collisionShapes.clear();
}
添加TriangleRenderJNI类实现了GLSurfaceView.Renderer接口
package com.example.anative;
import android.content.Context;
import android.content.res.AssetManager;
import android.opengl.GLSurfaceView;
import android.util.Log;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class TriangleRenderJNI implements GLSurfaceView.Renderer {
static {
System.loadLibrary("anative");
}
public TriangleRenderJNI(Context context){
mAssetMgr = context.getAssets();
if (null == mAssetMgr){
Log.e("TAG", "TriangleRenderJNI: " + "getAssets return null !");
}
}
private AssetManager mAssetMgr = null;
public native void glesInit();
public native void glesRender();
public native void glesResize(int width,int height);
public native void readShaderFile(AssetManager assetManager);
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
readShaderFile(mAssetMgr);
glesInit();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
glesResize(width,height);
}
@Override
public void onDrawFrame(GL10 gl) {
glesRender();
}
}
四个本地方法需要实现
创建一个RenderJNI.cpp,实现这四个本地方法,在里面创建bullet,并用opengles绘制。这里将bullet的HelloWorld程序的一些参数进行修改,改变了物体的大小和碰撞反弹系数
//
// Created by JinTao Liu on 2022/2/4.
//
#include "RenderJNI.h"
#include
#include
#include
#include
#include
#include "btBulletDynamicsCommon.h"
#include
#include
#include
#define LOG_TAG "ndk-build"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#include
GLint g_programObject;
jint g_width;
jint g_height;
jint circle_x = 600;
jint circle_y = 600;
AAssetManager* g_pAssetManager = NULL;
void drawCircle(GLfloat vVertices[],float radius,int n,float x,float y);
void drawBox(GLfloat vVertices[],int pos,float x1,float y1,float x2,float y2);
void drawBoxAndSphere(float radius,float circleX,float circleY,float boxX1,float boxY1,float boxX2,float boxY2);
GLuint LoadShader(GLenum type,const char * shaderSrc)
{
GLuint shader;
GLint compiled;
//Create the shader object
shader = glCreateShader(type);
if ( shader == 0)
{
return 0;
}
glShaderSource(shader,1,&shaderSrc,NULL);
glCompileShader(shader);
glGetShaderiv(shader,GL_COMPILE_STATUS,&compiled);
if(!compiled)
{
GLint infoLen = 0;
glGetShaderiv(shader,GL_INFO_LOG_LENGTH,&infoLen);
if(infoLen > 1)
{
char *infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader,infoLen,NULL,infoLog);
LOGE("Error compiling shader:[%s]",infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
btDiscreteDynamicsWorld* dynamicsWorld;
void createBullet(){
///-----includes_end-----
int i;
///-----initialization_start-----
///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
//冲突配置包含内存的默认设置,冲突设置。高级用户可以创建自己的配置
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep.
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0, -10, 0));
///-----initialization_end-----
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
btAlignedObjectArray<btCollisionShape*> collisionShapes;
///create a few basic rigid bodies
//the ground is a cube of side 100 at position y = -56.
//the sphere will hit it at y = -6, with center at -5
{
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(200.), btScalar(200.), btScalar(50.)));
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0, -300, 0));
btScalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0, 0, 0);
if (isDynamic)
groundShape->calculateLocalInertia(mass, localInertia);
//using motionstate is optional, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, groundShape, localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
//设置碰撞反弹系数
body->setRestitution(btScalar(1.2));
//add the body to the dynamics world
dynamicsWorld->addRigidBody(body);
}
{
//create a dynamic rigidbody
//btCollisionShape* colShape = new btBoxShape(btVector3(1,1,1));
btCollisionShape* colShape = new btSphereShape(btScalar(100));
collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(6.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0, 0, 0);
if (isDynamic)
colShape->calculateLocalInertia(mass, localInertia);
startTransform.setOrigin(btVector3(0, 600, 0));
//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, colShape, localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
//设置碰撞反弹系数
body->setRestitution(btScalar(1.2));
dynamicsWorld->addRigidBody(body);
}
}
void drawStep(){
dynamicsWorld->stepSimulation(1.f / 30.f, 10);
float radius,circleX,circleY;
float boxX1,boxY1,boxX2,boxY2;
//print positions of all objects
for (int j = dynamicsWorld->getNumCollisionObjects() - 1; j >= 0; j--)
{
btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[j];
btRigidBody* body = btRigidBody::upcast(obj);
btTransform trans;
if (body && body->getMotionState())
{
body->getMotionState()->getWorldTransform(trans);
}
else
{
trans = obj->getWorldTransform();
}
btCollisionShape* shape = body->getCollisionShape();
glm::mat4 model = glm::mat4(1.0f);
trans.getOpenGLMatrix(glm::value_ptr(model));
// __android_log_print(ANDROID_LOG_ERROR,shape->getName() ," shape");
// shape->getUserPointer();
int shaeType = shape->getShapeType();
// __android_log_print(ANDROID_LOG_ERROR,shape->getName() ," shapeName");
//box
btVector3 tempVector = shape->get();
__android_log_print(ANDROID_LOG_ERROR,"------------" + tempVector.getX(),"--------------\n");
// __android_log_print(ANDROID_LOG_ERROR,"TAG","world scale object %d = %f,%f,%f\n", j, float(tempVector.getX()), float(tempVector.getY()), float(tempVector.getZ()));
if (shaeType == 0){
btBoxShape* tempShape = static_cast<btBoxShape* >(shape);
btVector3 tempVector = tempShape->getImplicitShapeDimensions();
boxX1 = trans.getOrigin().getX() - tempVector.getX();
boxY1 = trans.getOrigin().getY() - tempVector.getY();
boxX2 = trans.getOrigin().getX() + tempVector.getX();
boxY2 = trans.getOrigin().getY() + tempVector.getY();
}else if (shaeType == 8){
btSphereShape* tempShape = static_cast<btSphereShape* >(shape);
radius = tempShape->getRadius();
circleX = trans.getOrigin().getX();
circleY = trans.getOrigin().getY();
}
// for (int l = 0;l < glm::mat4::length(); ++l) {
//
//
// __android_log_print(ANDROID_LOG_ERROR,glm::to_string(model[l]).c_str() + l,"Need to print");
// }
// __android_log_print(ANDROID_LOG_ERROR,glm::to_string(model).c_str(),"Need to print");
// __android_log_print(ANDROID_LOG_ERROR,"world pos object ","Need to print :");
// __android_log_print(ANDROID_LOG_ERROR,"TAG","world pos object %d = %f,%f,%f\n", j, float(trans.getOrigin().getX()), float(trans.getOrigin().getY()), float(trans.getOrigin().getZ()));
// __android_log_print(ANDROID_LOG_ERROR,"------------","-\n");
}
drawBoxAndSphere(radius,circleX,circleY,boxX1,boxY1,boxX2,boxY2);
// __android_log_print(ANDROID_LOG_ERROR,"------------","--------------\n");
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_anative_TriangleRenderJNI_glesInit(JNIEnv *env, jobject thiz) {
// TODO: implement glesInit()
// TODO: implement glesInit()
char vShaderStr[] =
"#version 300 es \n"
"layout(location = 0) in vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
char fShaderStr[] =
"#version 300 es \n"
"precision mediump float; \n"
"out vec4 fragColor; \n"
"void main() \n"
"{ \n"
" fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 ); \n"
"} \n";
// char *pVertextShader = readShaderSrcFile("shader/vs.glsl",g_pAssetManager);
// char *pFragmentShader = readShaderSrcFile("shader/fs.glsl",g_pAssetManager);
char *pVertextShader = vShaderStr;
char *pFragmentShader = fShaderStr;
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
//load the vertext/fragment shaders
//vertexShader = LoadShader (GL_VERTEX_SHADER,vShaderStr);
//fragmentShader = LoadShader();
vertexShader = LoadShader(GL_VERTEX_SHADER,pVertextShader);
fragmentShader = LoadShader(GL_FRAGMENT_SHADER,pFragmentShader);
//Create the program object
programObject = glCreateProgram();
if (programObject == 0)
{
return;
}
glAttachShader(programObject,vertexShader);
glAttachShader(programObject,fragmentShader);
//Link the program
glLinkProgram(programObject);
//Check the link status
glGetProgramiv(programObject,GL_LINK_STATUS,&linked);
if (!linked)
{
GLint infoLen = 0;
glGetProgramiv(programObject,GL_INFO_LOG_LENGTH,&infoLen);
if (infoLen > 1)
{
char *infoLog = (char *)malloc(sizeof (char )* infoLen);
glGetProgramInfoLog(programObject,infoLen,NULL,infoLog);
LOGE("Error linking program:[%s]",infoLog);
free(infoLog);
}
glDeleteProgram(programObject);
return;
}
// Store the progrom object
g_programObject = programObject;
glClearColor(1.0f,1.0f,1.0f,0.0f);
createBullet();
}
void drawCircle(GLfloat vVertices[],float radius,int n,float x,float y){
int pos = 0;
float angDegSpan=360.0f/n;
for(float i=0;i<360;i+=angDegSpan){
vVertices[pos++] = x / g_width;
vVertices[pos++] = y / g_height;
vVertices[pos++] = 0;
vVertices[pos++] = (float) ((x + radius*sin(i*M_PI/180.0f)) / g_width);
vVertices[pos++] = (float)((y + radius*cos(i*M_PI/180.0f)) / g_height);
vVertices[pos++] = 0;
vVertices[pos++] = (float) ((x + radius*sin((i+angDegSpan)*M_PI/180.0f)) / g_width);
vVertices[pos++] = (float)((y + radius*cos((i+angDegSpan)*M_PI/180.0f)) / g_height);
vVertices[pos++] = 0;
}
}
void drawBox(GLfloat vVertices[],int pos,float x1,float y1,float x2,float y2){
//左上角
vVertices[pos++] = x1 / g_width;
vVertices[pos++] = y1 / g_height;
vVertices[pos++] = 0;
//左下角
vVertices[pos++] = x1 / g_width;
vVertices[pos++] = y2 / g_height;
vVertices[pos++] = 0;
//右下角
vVertices[pos++] = x2 / g_width;
vVertices[pos++] = y2 / g_height;
vVertices[pos++] = 0;
//左上角
vVertices[pos++] = x1 / g_width;
vVertices[pos++] = y1 / g_height;
vVertices[pos++] = 0;
//右上角
vVertices[pos++] = x2 / g_width;
vVertices[pos++] = y1 / g_height;
vVertices[pos++] = 0;
//右下角
vVertices[pos++] = x2 / g_width;
vVertices[pos++] = y2 / g_height;
vVertices[pos++] = 0;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_anative_TriangleRenderJNI_glesRender(JNIEnv *env, jobject thiz) {
// TODO: implement glesRender()
// glDrawArrays(GL_TRIANGLES,0,6);
// GLfloat vVertices[(180)*9 + 6*3];
// drawCircle(vVertices,180,180,circle_x++,circle_y++);
// drawBox(vVertices,180*9,-300,400,300,-400);
//
// // Set the viewport
// glViewport(0,0,g_width,g_height);
//
//
// //Clear the color buffer
// glClear(GL_COLOR_BUFFER_BIT);
//
// //Use the program object
// glUseProgram(g_programObject);
//
// //Load the vertex data
// glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,vVertices);
// glEnableVertexAttribArray(0);
//
// glDrawArrays(GL_TRIANGLES,0,(180)*3 + 6);
drawStep();
}
void drawBoxAndSphere(float radius,float circleX,float circleY,float boxX1,float boxY1,float boxX2,float boxY2){
glDrawArrays(GL_TRIANGLES,0,6);
GLfloat vVertices[(180)*9 + 6*3];
drawCircle(vVertices,radius,180,circleX,circleY);
drawBox(vVertices,180*9,boxX1,boxY1,boxX2,boxY2);
// Set the viewport
glViewport(0,0,g_width,g_height);
//Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
//Use the program object
glUseProgram(g_programObject);
//Load the vertex data
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,vVertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES,0,(180)*3 + 6);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_anative_TriangleRenderJNI_glesResize(JNIEnv *env, jobject thiz, jint width,
jint height) {
// TODO: implement glesResize()
g_width = width;
g_height = height;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_anative_TriangleRenderJNI_readShaderFile(JNIEnv *env, jobject thiz,
jobject asset_manager) {
// TODO: implement readShaderFile()
if (asset_manager && env){
g_pAssetManager = AAssetManager_fromJava(env,asset_manager);
if (NULL == g_pAssetManager)
{
LOGE("AAssetManager_fromJava() return null !");
}
} else{
LOGE("assetManager is null !");
}
}
修改CMakeLists.txt
##加入
##官方标准配置
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions -Wall")
##ANDROID_PLATFORM_LEVEL=18
add_definitions("-DDYNAMIC_ES3")
set(OPENGL_LIB GLESv2)
# Declares and names the project.
#修改,添加引用库${OPENGL_LIB} android EGL m
target_link_libraries( # Specifies the target library.
anative
# Links the target library to the log library
# included in the NDK.
${log-lib}
${OPENGL_LIB}
android
EGL
m)
修改MainActivity
package com.example.anative;
import androidx.appcompat.app.AppCompatActivity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.widget.TextView;
import com.example.anative.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
// Used to load the 'anative' library on application startup.
static {
System.loadLibrary("anative");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// binding = ActivityMainBinding.inflate(getLayoutInflater());
// setContentView(R.layout.activity_main);
//
// // Example of a call to a native method
// TextView tv = findViewById(R.id.sample_text);
// tv.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// stringFromJNI();
// }
// });
setupViews();
}
private void setupViews() {
GLSurfaceView mGlSurfaceView = new GLSurfaceView(this);
setContentView(mGlSurfaceView);
//设置版本
mGlSurfaceView.setEGLContextClientVersion(2);
GLSurfaceView.Renderer renderer = new TriangleRenderJNI(MainActivity.this);
mGlSurfaceView.setRenderer(renderer);
//只有在绘制数据改变时才会绘制View,可以防止GLSurfaceView帧重绘
//该种模式下当需要重绘时需要我们手动调用glSurfaceView.requestRender();
mGlSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
/**
* A native method that is implemented by the 'bulletopengles' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
最后效果
之前参考了一个opengles 绘制三角形的,链接找不到了。
代码:https://gitee.com/aaaa_sss/native.git