`

用OpenGL实现无限循环的coverflow

阅读更多
网上找了很久,都是用Gallery实现的,效果不是很满意,结果发现这个用OpenGL实现的,稍微修改了一下源码,实现了无限循环功能

源码地址:https://github.com/jackfengji/glcoverflow

public class CoverFlowOpenGL extends GLSurfaceView implements
		GLSurfaceView.Renderer {

	private static final int TOUCH_MINIMUM_MOVE = 5;
	private static final int IMAGE_SIZE = 128;
	private static final int MAX_TILES = 48;

	// the visble tiles left and right
	private static final int VISIBLE_TILES = 1;

	private static final float SCALE = 0.7f;
	private static final float SPREAD_IMAGE = 0.14f;
	private static final float FLANK_SPREAD = 0.4f;
	private static final float FRICTION = 10.0f;
	private static final float MAX_SPEED = 6.0f;

	private static final float[] GVertices = new float[] { -1.0f, -1.0f, 0.0f,
			1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, };

	private static final float[] GTextures = new float[] { 0.0f, 1.0f, 1.0f,
			1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };

	private GL10 mGLContext;
	private FloatBuffer mVerticesBuffer;
	private FloatBuffer mTexturesBuffer;
	private float[] mMatrix;

	private int mBgTexture;
	private FloatBuffer mBgVerticesBuffer;
	private FloatBuffer mBgTexturesBuffer;
	private int mBgBitmapId;
	private boolean mInitBackground;

	private float mOffset;
	private int mLastOffset;
	private RectF mTouchRect;

	private int mWidth;
	private boolean mTouchMoved;
	private float mTouchStartPos;
	private float mTouchStartX;
	private float mTouchStartY;

	private float mStartOffset;
	private long mStartTime;

	private float mStartSpeed;
	private float mDuration;
	private Runnable mAnimationRunnable;
	private VelocityTracker mVelocity;

	private CoverFlowListener mListener;
	private DataCache<Integer, CoverFlowRecord> mCache;

	public CoverFlowOpenGL(Context context) {
		super(context);

		setEGLConfigChooser(8, 8, 8, 8, 16, 0);

		setRenderer(this);
		setRenderMode(RENDERMODE_WHEN_DIRTY);

		getHolder().setFormat(PixelFormat.TRANSLUCENT);

		mCache = new DataCache<Integer, CoverFlowRecord>(MAX_TILES);
		mLastOffset = 0;
		mOffset = 0;
		mInitBackground = false;
		mBgBitmapId = 0;
	}

	public void setCoverFlowListener(CoverFlowListener listener) {
		mListener = listener;
	}

	public void setSelection(int position) {
		endAnimation();
		mOffset = position;
		requestRender();
	}

	private int getActuallyPosition(int position) {

		int max = mListener.getCount(this);
		while (position < 0 || position >= max) {
			if (position < 0)
				position += max;
			else if (position >= max)
				position -= max;
		}

		return position;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int action = event.getAction();
		switch (action) {
		case MotionEvent.ACTION_DOWN:
			touchBegan(event);
			return true;
		case MotionEvent.ACTION_MOVE:
			touchMoved(event);
			return true;
		case MotionEvent.ACTION_UP:
			touchEnded(event);
			return true;
		}
		return false;
	}

	private void touchBegan(MotionEvent event) {
		endAnimation();

		float x = event.getX();
		mTouchStartX = x;
		mTouchStartY = event.getY();
		mStartTime = System.currentTimeMillis();
		mStartOffset = mOffset;

		mTouchMoved = false;

		mTouchStartPos = (x / mWidth) * 10 - 5;
		mTouchStartPos /= 2;

		mVelocity = VelocityTracker.obtain();
		mVelocity.addMovement(event);
	}

	private void touchMoved(MotionEvent event) {
		float pos = (event.getX() / mWidth) * 10 - 5;
		pos /= 2;

		if (!mTouchMoved) {
			float dx = Math.abs(event.getX() - mTouchStartX);
			float dy = Math.abs(event.getY() - mTouchStartY);

			if (dx < TOUCH_MINIMUM_MOVE && dy < TOUCH_MINIMUM_MOVE)
				return;

			mTouchMoved = true;
		}

		mOffset = mStartOffset + mTouchStartPos - pos;

		requestRender();
		mVelocity.addMovement(event);
	}

	private void touchEnded(MotionEvent event) {
		float pos = (event.getX() / mWidth) * 10 - 5;
		pos /= 2;

		if (mTouchMoved) {
			mStartOffset += mTouchStartPos - pos;
			mOffset = mStartOffset;

			mVelocity.addMovement(event);

			mVelocity.computeCurrentVelocity(1000);
			double speed = mVelocity.getXVelocity();
			speed = (speed / mWidth) * 10;
			if (speed > MAX_SPEED)
				speed = MAX_SPEED;
			else if (speed < -MAX_SPEED)
				speed = -MAX_SPEED;

			startAnimation(-speed);
		} else {
			if (mTouchRect.contains(event.getX(), event.getY())) {
				mListener.topTileClicked(this,
						getActuallyPosition((int) (mOffset + 0.01)));
			}
		}
	}

	private void startAnimation(double speed) {
		if (mAnimationRunnable != null)
			return;

		double delta = speed * speed / (FRICTION * 2);
		if (speed < 0)
			delta = -delta;

		double nearest = mStartOffset + delta;
		nearest = Math.floor(nearest + 0.5);

		mStartSpeed = (float) Math.sqrt(Math.abs(nearest - mStartOffset)
				* FRICTION * 2);
		if (nearest < mStartOffset)
			mStartSpeed = -mStartSpeed;

		mDuration = Math.abs(mStartSpeed / FRICTION);
		mStartTime = AnimationUtils.currentAnimationTimeMillis();

		mAnimationRunnable = new Runnable() {
			@Override
			public void run() {
				driveAnimation();
			}
		};
		post(mAnimationRunnable);
	}

	private void driveAnimation() {
		float elapsed = (AnimationUtils.currentAnimationTimeMillis() - mStartTime) / 1000.0f;
		if (elapsed >= mDuration)
			endAnimation();
		else {
			updateAnimationAtElapsed(elapsed);
			post(mAnimationRunnable);
		}
	}

	private void endAnimation() {
		if (mAnimationRunnable != null) {
			mOffset = (float) Math.floor(mOffset + 0.5);

			requestRender();

			removeCallbacks(mAnimationRunnable);
			mAnimationRunnable = null;
		}
	}

	private void updateAnimationAtElapsed(float elapsed) {
		if (elapsed > mDuration)
			elapsed = mDuration;

		float delta = Math.abs(mStartSpeed) * elapsed - FRICTION * elapsed
				* elapsed / 2;
		if (mStartSpeed < 0)
			delta = -delta;

		mOffset = mStartOffset + delta;
		requestRender();
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		mCache.clear();

		mGLContext = gl;
		mVerticesBuffer = makeFloatBuffer(GVertices);
		mTexturesBuffer = makeFloatBuffer(GTextures);
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int w, int h) {

		mWidth = w;

		float imagew = w * 0.45f / SCALE / 2.0f;
		float imageh = h * 0.45f / SCALE / 2.0f;
		mTouchRect = new RectF(w / 2 - imagew, h / 2 - imageh, w / 2 + imagew,
				h / 2 + imageh);

		gl.glViewport(0, 0, w, h);

		float ratio = ((float) w) / h;
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glOrthof(-ratio * SCALE, ratio * SCALE, -1 * SCALE, 1 * SCALE, 1, 3);

		float[] vertices = new float[] { -ratio * SCALE, -SCALE, 0,
				ratio * SCALE, -SCALE, 0, -ratio * SCALE, SCALE, 0,
				ratio * SCALE, SCALE, 0 };
		mBgVerticesBuffer = makeFloatBuffer(vertices);
	}

	public void setBackgroundTexture(int res) {
		mBgBitmapId = res;
		mInitBackground = true;
	}

	public void clearTileCache() {
		mCache.clear();
	}

	private void initBg() {
		mInitBackground = false;
		if (mBgBitmapId != 0) {
			Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
					mBgBitmapId);
			mBgBitmapId = 0;

			int tmp = 1;
			int w = bitmap.getWidth();
			int h = bitmap.getHeight();
			while (w > tmp || h > tmp) {
				tmp <<= 1;
			}

			int width = tmp;
			int height = tmp;
			Bitmap bm = Bitmap.createBitmap(width, height,
					Bitmap.Config.RGB_565);
			Canvas cv = new Canvas(bm);

			int left = (width - w) / 2;
			int top = (height - h) / 2;
			cv.drawBitmap(bitmap, left, top, new Paint());

			GL10 gl = mGLContext;

			int[] tex = new int[1];
			gl.glGenTextures(1, tex, 0);
			mBgTexture = tex[0];

			gl.glBindTexture(GL10.GL_TEXTURE_2D, mBgTexture);
			GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bm, 0);
			bitmap.recycle();
			bm.recycle();

			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_CLAMP_TO_EDGE);
			gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
					GL10.GL_CLAMP_TO_EDGE);
			gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
					GL10.GL_REPLACE);

			float[] textcoor = new float[] { (tmp - w) / 2.0f / tmp,
					(tmp - h) / 2.0f / tmp, (tmp + w) / 2.0f / tmp,
					(tmp - h) / 2.0f / tmp, (tmp - w) / 2.0f / tmp,
					(tmp + h) / 2.0f / tmp, (tmp + w) / 2.0f / tmp,
					(tmp + h) / 2.0f / tmp };
			mBgTexturesBuffer = makeFloatBuffer(textcoor);
		}
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glLoadIdentity();
		GLU.gluLookAt(gl, 0, 0, 2, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

		gl.glDisable(GL10.GL_DEPTH_TEST);
		gl.glClearColor(0, 0, 0, 0);
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

		drawBg(gl);
		draw(gl);
	}

	public void drawBg(GL10 gl) {
		if (mInitBackground)
			initBg();

		if (mBgTexture != 0) {
			gl.glPushMatrix();

			gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mBgVerticesBuffer);
			gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mBgTexturesBuffer);
			gl.glEnable(GL10.GL_TEXTURE_2D);

			gl.glBindTexture(GL10.GL_TEXTURE_2D, mBgTexture);
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

			gl.glPopMatrix();
		}
	}

	private void draw(GL10 gl) {
		gl.glPushMatrix();

		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVerticesBuffer);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexturesBuffer);
		gl.glEnable(GL10.GL_TEXTURE_2D);

		gl.glEnable(GL10.GL_BLEND);
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

		final float offset = mOffset;
		int i = 0;
		int mid = (int) Math.floor(offset + 0.5);

		// draw the left tiles
		int iStartPos = mid - VISIBLE_TILES;
		for (i = iStartPos; i < mid; ++i) {
			drawTile(i, i - offset, gl);
		}

		// draw the right tiles
		int iEndPos = mid + VISIBLE_TILES;
		for (i = iEndPos; i >= mid; --i) {
			drawTile(i, i - offset, gl);
		}

		if (mLastOffset != (int) offset) {
			mListener.tileOnTop(this, getActuallyPosition((int) offset));
			mLastOffset = (int) offset;
		}

		gl.glPopMatrix();
	}

	private void drawTile(int position, float off, GL10 gl) {
		final CoverFlowRecord fcr = getTileAtIndex(position, gl);
		if (fcr != null && fcr.mTexture != 0) {
			if (mMatrix == null) {
				mMatrix = new float[16];
				mMatrix[15] = 1;
				mMatrix[10] = 1;
				mMatrix[5] = 1;
				mMatrix[0] = 1;
			}

			float trans = off * SPREAD_IMAGE;
			float f = off * FLANK_SPREAD;
			if (f > FLANK_SPREAD)
				f = FLANK_SPREAD;
			else if (f < -FLANK_SPREAD)
				f = -FLANK_SPREAD;

			mMatrix[3] = -f;
			mMatrix[0] = 1 - Math.abs(f);
			float sc = 0.38f * mMatrix[0];
			trans += f * 1;

			gl.glPushMatrix();
			gl.glBindTexture(GL10.GL_TEXTURE_2D, fcr.mTexture);

			// draw bitmap
			gl.glTranslatef(trans, 0, 0);
			gl.glScalef(sc, sc, 1.0f);
			gl.glMultMatrixf(mMatrix, 0);
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

			// draw the reflection
			gl.glTranslatef(0, -2, 0);
			gl.glScalef(1, -1, 1);
			gl.glColor4f(1f, 1f, 1f, 0.5f);
			gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
			gl.glColor4f(1, 1, 1, 1);

			gl.glPopMatrix();
		}
	}

	private CoverFlowRecord getTileAtIndex(int position, GL10 gl) {
		synchronized (this) {

			position = getActuallyPosition(position);

			CoverFlowRecord fcr = mCache.objectForKey(position);
			if (fcr == null) {

				Bitmap bm = mListener.getImage(this, position);

				if (bm == null)
					return null;

				int texture = imageToTexture(bm, gl);

				fcr = new CoverFlowRecord(texture, gl);
				mCache.putObjectForKey(position, fcr);
			}
			return fcr;
		}
	}

	private static Bitmap createTextureBitmap(Bitmap bitmap) {
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		final Bitmap bm = Bitmap.createBitmap(IMAGE_SIZE, IMAGE_SIZE,
				Bitmap.Config.ARGB_8888);
		Canvas cv = new Canvas(bm);
		if (width > IMAGE_SIZE || height > IMAGE_SIZE) {
			// scale the bitmap, make the width or height to the IMAGE_SIZE
			Rect src = new Rect(0, 0, width, height);

			float scale = 1.0f;
			if (width > height)
				scale = ((float) IMAGE_SIZE) / width;
			else
				scale = ((float) IMAGE_SIZE) / height;
			width = (int) (width * scale);
			height = (int) (height * scale);
			float left = (IMAGE_SIZE - width) / 2.0f;
			float top = (IMAGE_SIZE - height) / 2.0f;
			RectF dst = new RectF(left, top, left + width, top + height);

			cv.drawBitmap(bitmap, src, dst, new Paint());
		} else {
			float left = (IMAGE_SIZE - width) / 2.0f;
			float top = (IMAGE_SIZE - height) / 2.0f;
			cv.drawBitmap(bitmap, left, top, new Paint());
		}

		return bm;
	}

	private int imageToTexture(Bitmap bitmap, GL10 gl) {
		// generate texture
		int[] texture = new int[1];
		gl.glGenTextures(1, texture, 0);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);

		final Bitmap bm = createTextureBitmap(bitmap);
		bitmap.recycle();
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bm, 0); // draw the bitmap in
															// the texture
		bm.recycle();

		// some texture settings
		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_CLAMP_TO_EDGE);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
				GL10.GL_CLAMP_TO_EDGE);
		gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
				GL10.GL_MODULATE);

		return texture[0];
	}

	private static FloatBuffer makeFloatBuffer(final float[] arr) {
		ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4);
		bb.order(ByteOrder.nativeOrder());
		FloatBuffer fb = bb.asFloatBuffer();
		fb.put(arr);
		fb.position(0);
		return fb;
	}

	public static class CoverFlowRecord {
		private int mTexture;
		private GL10 gl;

		public CoverFlowRecord(int texture, GL10 gl) {
			mTexture = texture;
			this.gl = gl;
		}

		@Override
		protected void finalize() throws Throwable {
			if (mTexture != 0) {
				gl.glDeleteTextures(1, new int[] { mTexture }, 0);
			}

			super.finalize();
		}
	}

	public static interface CoverFlowListener {
		public int getCount(CoverFlowOpenGL view);

		public Bitmap getImage(CoverFlowOpenGL anotherCoverFlow, int position);

		public void tileOnTop(CoverFlowOpenGL view, int position);

		public void topTileClicked(CoverFlowOpenGL view, int position);
	}
}


public class DataCache<K, E> {
	private int mCapacity;
	private LinkedHashMap<K, E> mCache;
	private final ReadWriteLock mReadWriteLock = new ReentrantReadWriteLock();

	public DataCache(int capacity) {
		mCapacity = capacity;
		mCache = new LinkedHashMap<K, E>(mCapacity) {
			private static final long serialVersionUID = -9165777183357349715L;

			@Override
			protected boolean removeEldestEntry(Entry<K, E> eldest) {
				if (size() > mCapacity) {
					mReadWriteLock.writeLock().lock();
					remove(eldest.getKey());
					mReadWriteLock.writeLock().unlock();
				}

				return false;
			}
		};
	}

	public E objectForKey(K key) {
		mReadWriteLock.readLock().lock();
		final E result = mCache.get(key);
		mReadWriteLock.readLock().unlock();

		return result;
	}

	public void putObjectForKey(final K key, final E value) {
		if (key != null && value != null) {
			mReadWriteLock.writeLock().lock();
			mCache.put(key, value);
			mReadWriteLock.writeLock().unlock();
		}
	}

	public boolean containsKey(final K key) {
		mReadWriteLock.readLock().lock();
		final boolean result = mCache.containsKey(key);
		mReadWriteLock.readLock().unlock();

		return result;
	}

	public void clear() {
		mReadWriteLock.writeLock().lock();
		mCache.clear();
		mReadWriteLock.writeLock().unlock();
	}

	public void setCapacity(int capacity) {
		mCapacity = capacity;
	}
}

使用时
private static int[] SAMPLE_IMAGES = new int[] {
		R.drawable.gallery_photo_1, R.drawable.gallery_photo_2,
		R.drawable.gallery_photo_3, R.drawable.gallery_photo_4,
		R.drawable.gallery_photo_5, R.drawable.gallery_photo_6,
		R.drawable.gallery_photo_7, R.drawable.gallery_photo_8 };

mCoverFlow = new CoverFlowOpenGL(this);
mCoverFlow.setCoverFlowListener(new CoverFlowOpenGL.CoverFlowListener() {
	@Override
	public int getCount(CoverFlowOpenGL view) {
		return SAMPLE_IMAGES_2.length;
	}

	@Override
	public View getView(CoverFlowOpenGL anotherCoverFlow,
							int position) {
		return BitmapFactory.decodeResource(getResources(),
								SAMPLE_IMAGES_2[position]);
	}

	@Override
	public void tileOnTop(CoverFlowOpenGL view, int position) {
		// you can control what will happen when one image is in
		// middle
	}

	@Override
	public void topTileClicked(CoverFlowOpenGL view,
							int position) {
		// you can control what will happen when the image in
		// middle is clicked
	}
});
分享到:
评论

相关推荐

    Android平台openg es实现的CoverFlow特效源码

    在给定的资源中,“Android平台opengles实现的CoverFlow特效源码”是一个利用OpenGL ES实现的仿苹果Coverflow特效的应用实例。Coverflow效果通常在音乐播放器、应用选择器等场景中看到,它呈现一种卡片翻转流动的...

    CoverFlow.rar

    【标签】"Coverflow Android Coverflo 3d" 强调了这个项目是关于Android平台上的Coverflow实现,可能涉及到3D图形处理和动画效果的编程。Coverflow和Coverflow可能指的是不同的实现版本或者相关的库,而"3d"则表示...

    android coverflow

    Android中的Coverflow效果可以通过自定义View或者使用第三方库来实现。其中,`jackfengji-glcoverflow-a9e2475`这个库就是一个专门用于实现Coverflow效果的开源项目。它基于OpenGL ES,利用硬件加速的优势,提供了...

    Qt+opengl实现分屏效果

    Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl实现分屏效果Qt+opengl...

    Android 3D CoverFlow 3D Gallery

    在"Android 3D CoverFlow 3D Gallery"的实现中,开发者可能使用SurfaceView或者GLSurfaceView来显示OpenGL ES渲染的内容。SurfaceView提供了硬件加速的画布,而GLSurfaceView则专为OpenGL ES设计,提供了一套更方便...

    qt+opengl实现帧缓冲

    qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl实现帧缓冲qt+opengl...

    OpenGL实现3D模型旋转

    本主题主要关注如何使用OpenGL实现3D模型的旋转,特别是通过ArcBall算法来实现平滑、直观的旋转操作。 ArcBall是一种在三维空间中对物体进行旋转的经典方法,它模拟了物理世界中的球体旋转。在OpenGL中,我们通常...

    opengl 实现水波纹

    在这个"opengl 实现水波纹"的项目中,我们关注的是如何利用OpenGL来创建动态的、逼真的水面波动效果。这个程序的核心是模拟水面的物理特性,如波动、反射和折射,以创造出视觉上的水波纹。 在OpenGL中实现水波纹...

    Qt+OpenGL 实现色温、色调、亮度、对比度、饱和度、高光

    Qt+OpenGL 实现色温、色调、亮度、对比度、饱和度、高光Qt+OpenGL 实现色温、色调、亮度、对比度、饱和度、高光Qt+OpenGL 实现色温、色调、亮度、对比度、饱和度、高光Qt+OpenGL 实现色温、色调、亮度、对比度、饱和...

    cover Flow

    在Android平台上,实现Cover Flow效果通常需要利用OpenGL(Open Graphics Library)这一强大的图形处理库。 OpenGL是一种跨语言、跨平台的应用程序编程接口(API),用于渲染2D和3D图像。在Android系统中,我们可以...

    安卓翻页效果相关-android用opengl实现电子书翻书效果代码.rar

    在这个“安卓翻页效果相关-android用opengl实现电子书翻书效果代码”中,开发者可能已经创建了一个利用OpenGL技术模拟真实书籍翻页动画的库或项目。 1. **OpenGL基础知识**:首先,理解OpenGL的基础概念至关重要。...

    Cover flow (iPad) 代码分享

    9. **源代码结构**:一个完整的Cover Flow实现通常包括多个类,如数据模型类(存储和管理显示内容),视图控制器(处理用户交互和业务逻辑),以及自定义视图类(实现Cover Flow的具体效果)。 10. **文档与注释**...

    Qt+opengl实现爆破物体

    Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl实现爆破物体Qt+opengl...

    A coverflow demo

    【标题】"A coverflow demo" 是一个关于Cover Flow效果实现的示例项目,它通常用于展示媒体库、应用图标或其他元素,用户可以像翻阅相册一样在这些元素之间流畅地滚动。Cover Flow最早由Steve Jobs在2006年的苹果...

    仿coverflow的翻页效果,但是没有镜面反射。

    项目需要coverflow的翻页效果,但是网上找到的都是IOS和java的代码。由于不需要那种镜面反射效果,所以不必去管opengl,再说我也不懂。 既然不需要懂opengl,那剩下只是纯逻辑的事了。 代码比较凌乱,勉强可以用。...

    opengl实现图形平移旋转缩放

    华科图形学作业,opengl实现图形平移旋转缩放

    利用OpenGL实现动画效果

    我们会在主程序中设置一个无限循环,不断调用`glClear()`清除屏幕,然后使用`glDrawArrays()`或`glDrawElements()`等函数绘制物体,最后调用`glSwapBuffers()`交换前后缓冲区,显示新绘制的帧,从而达到连续播放的...

    opengl+qt实现鼠标选中模型

    opengl+qt实现鼠标选中模型opengl+qt实现鼠标选中模型opengl+qt实现鼠标选中模型opengl+qt实现鼠标选中模型opengl+qt实现鼠标选中模型opengl+qt实现鼠标选中模型opengl+qt实现鼠标选中模型opengl+qt实现鼠标选中模型...

    使用 C++ 和 OpenGL 实现简单的 3D 赛车游戏

    【作品名称】:使用 C++ 和 OpenGL 实现简单的 3D 赛车游戏 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】: 项目结构...

    Android coverFlow

    在提供的压缩包"android-coverFlow"中,可能包含了一个完整的CoverFlow实现示例,包括源代码、资源文件和相关的示例数据。通过研究这些内容,开发者可以学习如何在自己的项目中集成和定制CoverFlow特效。同时,这也...

Global site tag (gtag.js) - Google Analytics