我正在尝试绘制相互连接的线条。让我们说他们正在创造一个 长方形。在每个角落我也有积分。当我在我的测试中测试代码 三星Galaxy Note 4经过几次旋转后,使用触控,所有矩形都结束了 在中心有一个点。我无法弄清楚为什么会这样。 代码在模拟器中工作正常。另外,我将行和点数据存储为数组列表 在我的代码中。这些数组列表用于创建行和点对象类 渲染。
public class GLRender implements GLSurfaceView.Renderer {
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private float[] mRotationMatrix = new float[16];
private float[] mVRMatrix = new float[16];
private static ArrayList<Line> DrLine = new ArrayList<Line>();
private static ArrayList<Point> DrPoint = new ArrayList<Point>();
private float ratio;
private float Joint1;
private float Joint2;
private float x1, y1, z1, x2, y2, z2;
private float px, py, pz, ps;
private float[] nearN = new float[4];
private static ArrayList<ArrayList<String>> LineArray = new ArrayList<ArrayList<String>>();
private ArrayList<String> L = new ArrayList<String>();
private ArrayList<String> P = new ArrayList<String>();
private static ArrayList<ArrayList<String>> PointArray = new ArrayList<ArrayList<String>>();
private static ArrayList<String> EmptyLine = new ArrayList<String>();
private static ArrayList<String> EmptyPoint = new ArrayList<String>();
private static ArrayList<ArrayList<ArrayList<String>>> UndoL = new ArrayList<ArrayList<ArrayList<String>>>();
private static ArrayList<ArrayList<ArrayList<String>>> UndoP = new ArrayList<ArrayList<ArrayList<String>>>();
public GLRender(Activity activity) {
}
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
//GLES20.glClearColor(0.53f, 0.53f, 0.53f, 1.0f);
GLES20.glClearColor(0.474f, 0.537f, 0.078f, 1.0f);
}
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
Drawer();
Line XLine = new Line();
XLine.SetVerts(0.0f, 0.0f, 0.0f, 1.0f / 10, 0.0f, 0.0f);
XLine.SetColor(1.0f, 0.0f, 0.0f, 1.0f);
Line YLine = new Line();
YLine.SetVerts(0.0f, 0.0f, 0.0f, 0.0f, 1.0f / 10, 0.0f);
YLine.SetColor(0.0f, 1.0f, 0.0f, 1.0f);
Line ZLine = new Line();
ZLine.SetVerts(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f / 10);
ZLine.SetColor(0.0f, 0.0f, 1.0f, 1.0f);
Matrix.setIdentityM(mViewMatrix, 0);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 1.0f , 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.setIdentityM(mRotationMatrix, 0);
Matrix.rotateM(mRotationMatrix, 0, mXAngle, 0, 1f, 0);
Matrix.rotateM(mRotationMatrix, 0, mYAngle, 1f, 0, 0);
Matrix.setIdentityM(mVRMatrix, 0);
Matrix.multiplyMM(mVRMatrix, 0, mViewMatrix, 0, mRotationMatrix, 0);
Matrix.setIdentityM(mMVPMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mVRMatrix, 0);
Matrix.scaleM(mMVPMatrix,0,mScale,mScale,mScale);
if (DrLine.size() > 0) {
for (Line LineX : DrLine) {
LineX.draw(mMVPMatrix);
}
}
if (DrPoint.size() > 0) {
for (Point PointX : DrPoint) {
PointX.draw(mMVPMatrix);
}
}
XLine.draw(mMVPMatrix);
YLine.draw(mMVPMatrix);
ZLine.draw(mMVPMatrix);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
ratio = (float) width / height;
//Matrix.frustumM(mProjectionMatrix, 0, -ratio*10, ratio*10, -10, 10, 1, 9);
Matrix.orthoM(mProjectionMatrix, 0, -ratio, ratio, -1.0f, 1.0f, -5.0f, 5.0f);
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
private Float TempMaxPointHolder = 0.0f;
private Float MaxPointHolder = 0.0f;
public Float Scaler(){
Float TempScaler = 1.0f;
Iterator<ArrayList<String>> MaxPointFinder = PointArray.iterator();
while (MaxPointFinder.hasNext()){
ArrayList<String> MaxPoint = MaxPointFinder.next();
TempMaxPointHolder = Math.abs(Math.max(Math.max(Float.parseFloat(MaxPoint.get(1)),Float.parseFloat(MaxPoint.get(2))),Float.parseFloat(MaxPoint.get(3))));
if (TempMaxPointHolder > MaxPointHolder){
MaxPointHolder = TempMaxPointHolder;
}
}
TempScaler = 0.9f / MaxPointHolder;
return TempScaler;
}
public void Drawer(){
Float Scaler = Scaler();
Integer Lindex = 0;
ArrayList<Point> TempDrPoint = new ArrayList<Point>();
ArrayList<Line> TempDrLine = new ArrayList<Line>();
Iterator<ArrayList<String>> Litr = LineArray.iterator();
while (Litr.hasNext()) {
L = Litr.next();
Joint1 = Float.parseFloat(L.get(1));
Joint2 = Float.parseFloat(L.get(2));
Iterator<ArrayList<String>> PitrL = PointArray.iterator();
while (PitrL.hasNext()){
P = PitrL.next();
if (Float.parseFloat(P.get(0)) == Joint1) {
x1 = Float.parseFloat(P.get(1)) * Scaler;
y1 = Float.parseFloat(P.get(2)) * Scaler;
z1 = Float.parseFloat(P.get(3)) * Scaler;
}
if (Float.parseFloat(P.get(0)) == Joint2) {
x2 = Float.parseFloat(P.get(1)) * Scaler;
y2 = Float.parseFloat(P.get(2)) * Scaler;
z2 = Float.parseFloat(P.get(3)) * Scaler;
}
}
Line TempLine = new Line();
TempLine.SetVerts(x1, y1, z1, x2, y2, z2);
if (L.get(3) == "0") {
TempLine.SetColor(0.0f, 0.0f, 0.0f, 1.0f);
}
else if (L.get(3) == "1"){
TempLine.SetColor(0.66f, 0.73f, 0.21f, 1.0f);
}
TempDrLine.add(TempLine);
Lindex = Lindex + 1;
}
setDrLine(TempDrLine);
Integer Pindex = 0;
Iterator<ArrayList<String>> Pitr = PointArray.iterator();
while (Pitr.hasNext()){
P = Pitr.next();
px = Float.parseFloat(P.get(1)) * Scaler;
py = Float.parseFloat(P.get(2)) * Scaler;
pz = Float.parseFloat(P.get(3)) * Scaler;
ps = Float.parseFloat(P.get(4));
Point TempPoint = new Point();
TempPoint.SetPointVerts(px, py, pz);
if (ps == 0.0f) {
TempPoint.SetPointColor(0.65f, 0.37f, 0.11f, 1.0f);
}
else if (ps == 1.0f) {
TempPoint.SetPointColor(0.68f, 0.07f, 0.32f, 1.0f);
}
TempDrPoint.add(TempPoint);
Pindex = Pindex + 1;
}
setDrPoint(TempDrPoint);
}
public volatile float mXAngle;
public volatile float mYAngle;
public ArrayList<Line> getDrLine() {
return DrLine;
}
public ArrayList<Point> getDrPoint(){
return DrPoint;
}
public void setDrLine(ArrayList<Line> XDrLine) {
DrLine = XDrLine;
}
public void setDrPoint(ArrayList<Point> XDrPoint) {
DrPoint = XDrPoint;
}
public float getXAngle() {
return mXAngle;
}
public float getYAngle(){
return mYAngle;
}
public void setAngleX(float Xangle) {
mXAngle = Xangle;
}
public void setAngleY(float Yangle) {
mYAngle = Yangle;
}
public volatile float mScale = 1;
public volatile float mXFocus;
public volatile float mYFocus;
public void setZoom(float scale){
mScale = scale;
}
public void setFocus(float XFocus, float YFocus){
mXFocus = XFocus;
mYFocus = YFocus;
}
public float getmScale(){
return mScale;
}
public float getmXFocus(){
return mXFocus;
}
public float getmYFocus(){
return mYFocus;
}
public void setLineArray(ArrayList<ArrayList<String>> XLine){
LineArray = XLine;
}
public ArrayList<ArrayList<String>> getLineArray(){
return LineArray;
}
public void setUndoL(ArrayList<ArrayList<String>> UndoLine){
this.UndoL.add(new ArrayList<ArrayList<String>>(UndoLine));
}
public ArrayList<ArrayList<ArrayList<String>>> getUndoL() {
return UndoL;
}
public void setUndoP(ArrayList<ArrayList<String>> UndoPoint){
this.UndoP.add(new ArrayList<ArrayList<String>>(UndoPoint));
}
public ArrayList<ArrayList<ArrayList<String>>> getUndoP() {
return UndoP;
}
public void setPointArray(ArrayList<ArrayList<String>> XPoint){
PointArray = XPoint;
}
public ArrayList<ArrayList<String>> getPointArray(){
return PointArray;
}
给出错误contents_sample_state:[agr({[3,38] = 11,[3,7,38] = 28})]
public class Line {
private FloatBuffer VertexBuffer;
private final String VertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String FragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
protected int GlProgram;
protected int PositionHandle;
protected int ColorHandle;
protected int MVPMatrixHandle;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float LineCoords[] = {
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
private final int VertexCount = LineCoords.length / COORDS_PER_VERTEX;
private final int VertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
public Line() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
LineCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
VertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
VertexBuffer.put(LineCoords);
// set the buffer to read the first coordinate
VertexBuffer.position(0);
int vertexShader = GLRender.loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode);
int fragmentShader = GLRender.loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode);
GlProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(GlProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(GlProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(GlProgram); // creates OpenGL ES program executables
}
public void SetVerts(float v0, float v1, float v2, float v3, float v4, float v5) {
LineCoords[0] = v0;
LineCoords[1] = v1;
LineCoords[2] = v2;
LineCoords[3] = v3;
LineCoords[4] = v4;
LineCoords[5] = v5;
VertexBuffer.put(LineCoords);
// set the buffer to read the first coordinate
VertexBuffer.position(0);
}
public void SetColor(float red, float green, float blue, float alpha) {
color[0] = red;
color[1] = green;
color[2] = blue;
color[3] = alpha;
}
public void draw(float[] mvpMatrix) {
// Add program to OpenGL ES environment
GLES20.glUseProgram(GlProgram);
// get handle to vertex shader's vPosition member
PositionHandle = GLES20.glGetAttribLocation(GlProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(PositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(PositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
VertexStride, VertexBuffer);
// get handle to fragment shader's vColor member
ColorHandle = GLES20.glGetUniformLocation(GlProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(ColorHandle, 1, color, 0);
// get handle to shape's transformation matrix
MVPMatrixHandle = GLES20.glGetUniformLocation(GlProgram, "uMVPMatrix");
//GLRender.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(MVPMatrixHandle, 1, false, mvpMatrix, 0);
//GLRender.checkGlError("glUniformMatrix4fv");
GLES20.glLineWidth(5);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_LINES, 0, VertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(PositionHandle);
}
}
public class GLSurface extends GLSurfaceView {
//public static GLRender xRender;
ScaleGestureDetector ScaleDetect;
MainActivity mMain;
OpenGL XOPL = mMain.xOpenGL;
public GLSurface(Context context, AttributeSet attrs){
super(context, attrs);
// Render the view only when there is a change in the drawing data
//setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
ScaleDetect = new ScaleGestureDetector(context, new ScaleDetectorListener());
}
private float mPreviousX;
private float mPreviousY;
float density = this.getResources().getDisplayMetrics().density;
private static final int MAX_CLICK_DURATION = 300;
private long pressStartTime;
@Override
public boolean onTouchEvent(MotionEvent e) {
ScaleDetect.onTouchEvent(e);
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
if(!ScaleDetect.isInProgress()) {
float xMoveRange = x - mPreviousX;
float yMoveRange = y - mPreviousY;
float dx = 0.0f;
float dy = 0.0f;
float w = this.getWidth();
float h = this.getHeight();
if (Math.abs(xMoveRange) > w / 100 && Math.abs(yMoveRange) < h / 100){
dx = xMoveRange / density / 2.0f;
XOPL.xRender.setAngleX(XOPL.xRender.getXAngle() + dx);
}
if (Math.abs(xMoveRange) < w / 100 && Math.abs(yMoveRange) > h / 100){
dy = yMoveRange / density / 2.0f;
XOPL.xRender.setAngleY(XOPL.xRender.getYAngle() + dy);
}
XOPL.myGLView.requestRender();
}
break;
case MotionEvent.ACTION_DOWN:
pressStartTime = System.currentTimeMillis();
break;
case MotionEvent.ACTION_UP:
long pressDuration = System.currentTimeMillis() - pressStartTime;
if (pressDuration < MAX_CLICK_DURATION) {
float Nx = (x - Float.parseFloat(Double.toString(this.getWidth())) * 0.5f) / (Float.parseFloat(Double.toString(this.getWidth())) * 0.5f);
float Ny = (y - Float.parseFloat(Double.toString(this.getHeight())) * 0.5f) / (Float.parseFloat(Double.toString(this.getHeight())) * 0.5f);
float Nz = 1.0f;
XOPL.xRender.setNCoordinate(Nx, Ny, Nz);
XOPL.xRender.Selection();
XOPL.myGLView.requestRender();
}
break;
}
mPreviousX = x;
mPreviousY = y;
return true;
}
private float sizeCoef = 1;
public class ScaleDetectorListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
float scaleFocusX = 0;
float scaleFocusY = 0;
public boolean onScale(ScaleGestureDetector arg0) {
float scale = arg0.getScaleFactor() * sizeCoef;
sizeCoef = scale;
XOPL.xRender.setZoom(sizeCoef);
XOPL.myGLView.requestRender();
return true;
}
public boolean onScaleBegin(ScaleGestureDetector arg0) {
invalidate();
scaleFocusX = arg0.getFocusX();
scaleFocusY = arg0.getFocusY();
XOPL.xRender.setFocus(scaleFocusX,scaleFocusY);
return true;
}
public void onScaleEnd(ScaleGestureDetector arg0) {
scaleFocusX = 0;
scaleFocusY = 0;
XOPL.xRender.setFocus(scaleFocusX,scaleFocusY);
}
}
}
答案 0 :(得分:0)
不确定这是否是问题,但请注意以下事项:
XOPL.xRender.setAngleX(XOPL.xRender.getXAngle()+ dx)
...尤其是在着色器中使用mediump精度时。一般情况下,我建议更改setAngle函数以利用旋转对称性并将值包装起来,这样就可以得到API级别为+ -Pi的绝对范围。
在当前代码中,如果用户继续向一个方向滑动,最终你将运行我们的位,一切都将停止旋转(最好),或者无效或NaN结果失败(最坏的情况下)。 / p>
注意使用&#34; -Pi到+ Pi&#34;最好使用&#34; 0到+ 2Pi&#34;,因为符号位在大多数浮点表示中是空闲的,因此保留了更多的动态精度。
示例代码:
public float wrapRadians(float angle) {
// If angle is negative ensure value is higher than minus pi
if (angle < 0) {
while (angle < -math.PI) {
angle += 2 * math.PI;
}
// Else angle is positive so ensure value is less than pi
} else {
while (angle > math.PI) {
angle -= 2 * math.PI;
}
}
return angle;
}
public float setXAngle(float XAngle) {
mXAngle = wrapRadians(XAngle);
}
public float setYAngle(float YAngle) {
mYAngle = wrapRadians(YAngle);
}