Android OpenGLES 360全景图片渲染(球体内部)

news2025/5/10 7:10:57

在这里插入图片描述

概述

    360度全景图是一种虚拟现实技术,它通过对现实场景进行多角度拍摄后,利用计算机软件将这些照片拼接成一个完整的全景图像。这种技术能够让观看者在虚拟环境中以交互的方式查看整个周围环境,就好像他们真的站在那个位置一样。在Android设备上查看360度全景图片,可以使用一些专门的app, 不如Google相册, Google 街景, 第三方的全景图片查看应用。这些应用程序能够识别并以交互方式展示360度全景图像,让用户可以旋转、缩放和平移来探索整个场景。
    360全景图片渲染可以使用openGLES来轻松实现.

实现

在这里插入图片描述
在这里插入图片描述

使用OpenGL 创建一个球体, 并将图片纹理按一定的规则贴到球体的内部. 如上图, 可以考虑将图片等比例铺满球面展开的面积即可, 方法有很多, 可以按经度, 也可以按维度, 不同顺序对结果没影响.

参考代码:

主界面

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import com.android.apitester.SphereView;

public class SphereViewer extends Activity {
    SphereView sphereView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bitmap bm = BitmapFactory.decodeFile("/sdcard/sphere.jpg");
        sphereView = new SphereView(this);
        sphereView.setBitmap(bm);
        setContentView(sphereView);
    }
}

自定义GLSurfaceView

import android.content.Context;
import android.graphics.Bitmap;
import android.hardware.SensorManager;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.View;

import com.ansondroider.acore.Logger;
import com.ansondroider.acore.opengl.EGLHelper;

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

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

public class SphereView  extends GLSurfaceView implements GLSurfaceView.Renderer {
    final String TAG = "SphereView";
    private String vertextShaderSource = "attribute vec4 aPosition;" +
            "precision mediump float;" +
            "uniform mat4 uMatrix;" +
            "attribute vec2 aCoordinate;" +
            "varying vec2 vCoordinate;" +
            "attribute float alpha;" +
            "varying float inAlpha;" +
            "void main(){" +
            "	gl_Position = uMatrix*aPosition;\n" +
            //"	gl_Position = aPosition;" +
            " 	gl_PointSize = 10.0;" +
            "	vCoordinate = aCoordinate;" +
            "	inAlpha = alpha;" +
            "}";
    private String fragmentShaderSource = "#extension GL_OES_EGL_image_external : require\n" +
            "precision mediump float;" +
            "varying vec2 vCoordinate;" +
            "varying float inAlpha;" +
            //"uniform samplerExternalOES uTexture;" +
            "uniform sampler2D uTexture;" +
            "uniform bool isPoint;" +
            "void main() {" +
            "	vec4 color = texture2D(uTexture, vCoordinate);" +
            "	if(isPoint){" +
            " 	   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);" +
            "	}else{" +
            "		gl_FragColor = vec4(color.r, color.g, color.b, inAlpha);" +
            "	}" +
            "}";

    //纹理ID
    private int mTextureId = -1;
    // 定义OpenGL 程序ID
    private int mProgram = -1;
    //矩阵变换接受者(shader中)
    private int mVertexMatrixHandler = -1;
    //顶点坐标接收者
    private int mVertexPosHandler = -1;
    //纹理坐标接受者
    private int mTexturePosHandler = -1;
    //纹理接受者
    private int mTextureHandler = -1;
    //半透明值接受者
    private int mAlphaHandler = -1;
    private int mPointHandler = -1;
    //矩阵
    private float[] mMatrix = new float[16];
    private float[] projectionMatrix = new float[16];
    //透明度
    private float mAlpha = 1f;
    public SphereView(Context context) {
        super(context);
        //A        #16 pc 000000000000d348  [anon:dalvik-classes2.dex extracted in memory from /data/app/~~Kkld4fhSS0RUjHOLDPgB7w==/com.ansondroider.apitester-9-2nRYL85FvddCKlwbFEFw==/base.apk!classes2.dex] (com.ansondroider.apitester.sphere.SphereView.createGLPrg+36)
        //A        #18 pc 000000000000d74a  [anon:dalvik-classes2.dex extracted in memory from /data/app/~~Kkld4fhSS0RUjHOLDPgB7w==/com.ansondroider.apitester-9-2nRYL85FvddCKlwbFEFw==/base.apk!classes2.dex] (com.ansondroider.apitester.sphere.SphereView.onDrawFrame+138)
        setEGLContextClientVersion(2);
        setRenderer(this);
        setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                updateRotate(event);
                return true;
            }
        });
    }

    //if touching, stop sensor rotate.
    boolean touching;
    float dx, dy;
    float angStartX, angStartY;
    float angelTouchX, angelTouchY;
    public void updateRotate(MotionEvent e){
        if(e.getAction() == MotionEvent.ACTION_DOWN){
            touching = true;
            dx = e.getX();
            dy = e.getY();
            //float[] rot = {0, 0, 0};
            //provider.getAngle(rot);
            angStartX = angelTouchY;//rot[0];
            angStartY = angelTouchX;//rot[1];
        }else if(e.getAction() == MotionEvent.ACTION_MOVE){
            angelTouchY = angStartX + 180f * (e.getX() - dx) / getWidth();
            angelTouchX = angStartY + 180f * (e.getY() - dy) / getHeight();
        }else{
            touching = false;
        }
    }

    Bitmap tmpBm = null;
    boolean rebindTexture = false;
    public void setBitmap(Bitmap bm){
        //check mTextureId is -1, save bm to tmpBm;
        if(bm == null || bm.isRecycled())return;
        else tmpBm = bm;

        if(mTextureId >= 0){
            rebindTexture = true;
        }
    }

    float ratio = 1;
    //float frustumSize 	= 2.5f;
    float[] NEAR_FAR 	= {1.7f,	0.5f, 	20f, 	17f};
    float[] EYE_Z 		= {-0.06f, 	-3f, 	3};
    float[] SCALE 		= {5f, 		0.5f, 	10};
    float[] FRUSTUM 	= {1, 		1, 		3};
    float[] RADIUS 		= {2.5f, 	2, 		3};

    /**
     * 初始化矩阵变换,主要是防止视频拉伸变形
     */
    private void initDefMatrix() {
        //Log.d(TAG, "initDefMatrix");
        //设置相机位置
        float[] viewMatrix = new float[16];
        Matrix.setLookAtM(
                viewMatrix, 0,
                0f, 0f, EYE_Z[0],
                0f, 0f, 0,
                0f, 1.0f, 0f
        );

        float[] rotSensor = new float[16];
        Matrix.setIdentityM(rotSensor, 0);
        float[] rotTouch = new float[16];
        Matrix.setIdentityM(rotTouch, 0);
        Matrix.rotateM(rotTouch, 0, -angelTouchX, 1, 0, 0);
        float rotY = -angelTouchY + (vtSphere != null ? vtSphere.getStartRotateY() : 0);
        Matrix.rotateM(rotTouch, 0, rotY, 0, 1, 0);
        Matrix.multiplyMM(viewMatrix, 0, rotSensor, 0, rotTouch, 0);


        // 参数解释:
        //result: 存储乘法结果的矩阵数组。
        //resultOffset: 存储结果矩阵的数组起始偏移量。
        //lhs: 左操作数矩阵(left-hand side)的数组。
        //lhsOffset: 左操作数矩阵的数组起始偏移量。
        //rhs: 右操作数矩阵(right-hand side)的数组。
        //rhsOffset: 右操作数矩阵的数组起始偏移量。
        //Matrix.multiplyMM(mMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

        Matrix.multiplyMM(mMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

        Matrix.scaleM(mMatrix, 0, SCALE[0], SCALE[0], SCALE[0]);

    }

    @Override
    public void setAlpha(float alpha) {
        super.setAlpha(alpha);
        mAlpha = alpha;
    }

    /**
     * 创建并使用opengles程序
     */
    private void createGLPrg() {
        //Logger.d(TAG, "createGLPrg");
        if (mProgram == -1) {
            int vertexShader = EGLHelper.compileVertexShader(vertextShaderSource);
            int fragmentShader = EGLHelper.compileFragmentShader(fragmentShaderSource);
            //创建programe陈谷
            mProgram = GLES20.glCreateProgram();
            //将顶点着色器加入程序
            GLES20.glAttachShader(mProgram, vertexShader);
            //将片元着色器加入程序
            GLES20.glAttachShader(mProgram, fragmentShader);
            GLES20.glLinkProgram(mProgram);
            //从程序中获取句柄
            mVertexMatrixHandler = GLES20.glGetUniformLocation(mProgram, "uMatrix");
            mVertexPosHandler = GLES20.glGetAttribLocation(mProgram, "aPosition");
            mTextureHandler = GLES20.glGetUniformLocation(mProgram, "uTexture");
            mTexturePosHandler = GLES20.glGetAttribLocation(mProgram, "aCoordinate");
            mAlphaHandler = GLES20.glGetAttribLocation(mProgram, "alpha");
            mPointHandler = GLES20.glGetUniformLocation(mProgram, "isPoint");
        }
        //使用opengl程序
        if (mProgram != -1) GLES20.glUseProgram(mProgram);

    }

    @Override
    protected void onDetachedFromWindow() {
        Logger.d(TAG, "onDetachedFromWindow");
        super.onDetachedFromWindow();
        GLES20.glDisableVertexAttribArray(mVertexPosHandler);
        GLES20.glDisableVertexAttribArray(mTexturePosHandler);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        GLES20.glDeleteTextures(1, new int[]{mTextureId}, 0);
        GLES20.glDeleteProgram(mProgram);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        Logger.d(TAG, "onSurfaceCreated");
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        Logger.d(TAG, "onSurfaceChanged");
        GLES20.glViewport(0, 0, width, height);
        ratio = (float) width / height;

        //m: 存储结果矩阵的数组。
        //offset: 存储结果矩阵的数组起始偏移量。
        //left	: 近平面左边界的 X 坐标值。
        //right	: 近平面右边界的 X 坐标值。
        //bottom: 近平面下边界的 Y 坐标值。
        //top	: 近平面上边界的 Y 坐标值。
        //near	: 近平面的 Z 坐标值(必须为正数)。
        //far	: 远平面的 Z 坐标值(必须为正数)。
        Matrix.frustumM(projectionMatrix, 0,
                -ratio*FRUSTUM[0], ratio*FRUSTUM[0],
                -FRUSTUM[0], FRUSTUM[0],
                NEAR_FAR[0], NEAR_FAR[3]);
    }

    void prepareTexture(){
        if((mTextureId < 0 || rebindTexture) && tmpBm != null){
            Logger.d(TAG, "setBitmap bind bitmap to texture " + mTextureId);
            if(mTextureId >= 0) {
                //check texture is bind, unbind.
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
                GLES20.glDeleteTextures(1, new int[]{mTextureId}, 0);
            }
            //create texture and bind bitmap to it
            int[] textures = new int[1];
            GLES20.glGenTextures(1, textures, 0);
            mTextureId = textures[0];
            rebindTexture = false;


            //mTextureId is not -1, then bind Bitmap to mTextureId
            // 将 Bitmap 加载到纹理
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId);
            // 设置纹理参数
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
            GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, tmpBm, 0);
            tmpBm.recycle(); // 释放 Bitmap 资源
        }
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        //Logger.d(TAG, "onDrawFrame");
        GLES20.glClearColor(bgRGBA[0], bgRGBA[1], bgRGBA[2], bgRGBA[3]);
        long ct = SystemClock.uptimeMillis();
        if(ct - last_fps > 1000) {
            last_fps = ct;
            fps = 0;
        }
        fps ++;
        prepareTexture();
        //drawBitmap_initBuffer();
        //清除颜色缓冲和深度缓冲
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        ///GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        if (mTextureId != -1) {
            initDefMatrix();
            //2/创建、编译、启动opengles着色器
            createGLPrg();
            //3.激活并绑定纹理单元
            ///activateTexture();
            //5.开始绘制渲染
            doDraw();
        }
    }

    float[] bgRGBA = {0, 0, 0, 1};
    int fps = 0;
    long last_fps = SystemClock.uptimeMillis();

    /**
     * 开始绘制渲染
     */
    SphereTexture vtSphere;
    public void doDraw() {
        //Logger.d(TAG, "doDraw");
        if(mMatrix == null)return;
        if(vtSphere == null){
            vtSphere = new SphereTexture(RADIUS[0], 32, 32,
                    false);
        }

        // 绑定纹理
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId);
        GLES20.glUniform1i(mTextureHandler, 0);

        GLES20.glUniformMatrix4fv(mVertexMatrixHandler, 1, false, mMatrix, 0);
        GLES20.glVertexAttrib1f(mAlphaHandler, mAlpha);
        GLES20.glUniform1i(mPointHandler, vtSphere.isPoint() ? 1 : 0);
        vtSphere.draw(mVertexPosHandler, mTexturePosHandler);
    }
    
}//Class SphereView end

球面顶点和纹理坐标的生成与渲染

import android.graphics.RectF;
import android.opengl.GLES20;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

public class SphereTexture extends VertexTexture{
    private float mRadius;
    private int mLat, mLong;
    private boolean mIs180;

    private float[] degreeLongitude;
    private float[] degreeLatitude;
    public SphereTexture(float radius, int latitudeBands, int longitudeBands,
                         boolean is180) {
        mRadius = radius;
        mLat = latitudeBands;
        mLong = longitudeBands;
        mIs180 = is180;
        init();
    }

    @Override
    public float getStartRotateY() {
        return 0;//mIs180 ? 180f: -90f;
    }

    @Override
    protected void initVertexTextureCoordinate(){
        if(degreeLongitude == null) {
            degreeLongitude = new float[]{-_PI, 	_PI, 	_PI * 2};
            degreeLatitude 	= new float[]{-0, 		_PI, 	_PI};
        }

        mVertexCoors = new float[(mLat + 1) * (mLong + 1) * 3];
        mTextureCoors = new float[(mLat + 1) * (mLong + 1) * 2];
        mIndices = new short[mLat * mLong * 6];

        int vIndex = 0;
        int tIndex = 0;
        int iIndex = 0;
        for (int lat = 0; lat <= mLat; lat++) {
            float theta = degreeLatitude[0] +  (float) lat / mLat * degreeLatitude[2];
            float sinTheta = (float) Math.sin(theta);
            float cosTheta = (float) Math.cos(theta);

            for (int lon = 0; lon <= mLong; lon++) {
                float phi = degreeLongitude[0] + (float) lon / mLong * degreeLongitude[2];
                //float phi =  (float) lon / longitudeBands * 2 * (MAX_DEGREE_X);
                float sinPhi = (float) Math.sin(phi);
                float cosPhi = (float) Math.cos(phi);

                float x = cosPhi * sinTheta;
                float y = cosTheta;
                float z = sinPhi * sinTheta;

                mVertexCoors[vIndex] = mRadius * x;
                mVertexCoors[vIndex + 1] = mRadius * y;
                mVertexCoors[vIndex + 2] = mRadius * z;

                // 生成纹理坐标

                float u = (float) lon / mLong;
                float v = (float) lat / mLat;
                // 生成纹理坐标
				/*mTextureCoors[tIndex] = u;//x
				mTextureCoors[tIndex + 1] = v;//y*/
                RectF r = getTextureArea();
                mTextureCoors[tIndex] = r.left + r.width() * u;//x
                mTextureCoors[tIndex + 1] = r.top + r.height() * v;//y

                if (lat < mLat && lon < mLong) {
                    int first = lat * (mLong + 1) + lon;
                    int second = first + mLong + 1;

                    mIndices[iIndex++] = (short) first;
                    mIndices[iIndex++] = (short) second;
                    mIndices[iIndex++] = (short) (first + 1);

                    mIndices[iIndex++] = (short) second;
                    mIndices[iIndex++] = (short) (second + 1);
                    mIndices[iIndex++] = (short) (first + 1);


						/*
							first		first + 1		...
								|----------|-------------|
								|		   |			 |
								|		   |			 |
						  second|----------|-------------|
						  		|       second + 1       |
						  		|          |             |
						  		|          |             |
						  		|----------|-------------|
						 */
                }

                vIndex += 3;
                tIndex += 2;
            }
        }
    }

    @Override
    public void updateZ(float z) {
        super.updateZ(z);
        mRadius = z;
        initVertexTextureCoordinate();
    }

    @Override
    public void draw(int mVertexPosHandler, int mTexturePosHandler) {
        // 绑定顶点缓冲区
        GLES20.glEnableVertexAttribArray(mVertexPosHandler);
        mVertexBuffer.position(0);
        GLES20.glVertexAttribPointer(mVertexPosHandler, 3, GLES20.GL_FLOAT, false, 0, mVertexBuffer);


        // 绑定纹理坐标缓冲区
        GLES20.glEnableVertexAttribArray(mTexturePosHandler);
        mTextureBuffer.position(0);
        GLES20.glVertexAttribPointer(mTexturePosHandler, 2, GLES20.GL_FLOAT, false, 0, mTextureBuffer);

        // 绑定纹理
        //if(textureId > -1)GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);

        // 绘制球体
        if(!isPoint()) {
            GLES20.glDrawElements(GLES20.GL_TRIANGLES, getIndexCount(),
                    GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);
        }else
            GLES20.glDrawArrays(GLES20.GL_POINTS, 0, getVertexCount());

        GLES20.glDisableVertexAttribArray(mVertexPosHandler);
        GLES20.glDisableVertexAttribArray(mTexturePosHandler);
    }

}

最终效果:
在这里插入图片描述

参考

  1. Android OpenGLES3绘图:球形视频播放器
  2. Android 使用 OpenGL ES 绘制球面

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2327865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LETTERS(DFS)

【题目描述】 给出一个rowcolrowcol的大写字母矩阵&#xff0c;一开始的位置为左上角&#xff0c;你可以向上下左右四个方向移动&#xff0c;并且不能移向曾经经过的字母。问最多可以经过几个字母。 【输入】 第一行&#xff0c;输入字母矩阵行数RR和列数SS&#xff0c;1≤R,S≤…

NVM 多版本Node.js 管理全指南(Windows系统)

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、全栈领域优质创作者、高级开发工程师、高级信息系统项目管理师、系统架构师&#xff0c;数学与应用数学专业&#xff0c;10年以上多种混合语言开发经验&#xff0c;从事DICOM医学影像开发领域多年&#xff0c;熟悉DICOM协议及…

C,C++语言缓冲区溢出的产生和预防

缓冲区溢出的定义 缓冲区是内存中用于存储数据的一块连续区域&#xff0c;在 C 和 C 里&#xff0c;常使用数组、指针等方式来操作缓冲区。而缓冲区溢出指的是当程序向缓冲区写入的数据量超出了该缓冲区本身能够容纳的最大数据量时&#xff0c;额外的数据就会覆盖相邻的内存区…

《Linux内存管理:实验驱动的深度探索》【附录】【实验环境搭建 2】【vscode搭建调试内核环境】

1. 如何调试我们的内核 1. GDB调试 安装gdb sudo apt-get install gdb-multiarchgdb-multiarch是多架构版本&#xff0c;可以通过set architecture aarch64指定架构 QEMU参数修改添加-s -S #!/usr/bin/shqemu-7.2.0-rc1/build/aarch64-softmmu/qemu-system-aarch64 \-nogr…

Flutter项目之登录注册功能实现

目录&#xff1a; 1、页面效果2、登录两种状态界面3、中间按钮部分4、广告区域5、最新资讯6、登录注册页联调6.1、网络请求工具类6.2、注册页联调6.3、登录问题分析6.4、本地缓存6.5、共享token6.6、登录页联调6.7、退出登录 1、页面效果 import package:flutter/material.dart…

ctfshow VIP题目限免 源码泄露

根据题目提示是源代码泄露&#xff0c;右键查看页面源代码发现了 flag

移动神器RAX3000M路由器变身家庭云之七:增加打印服务,电脑手机无线打印

系列文章目录&#xff1a; 移动神器RAX3000M路由器变身家庭云之一&#xff1a;开通SSH&#xff0c;安装新软件包 移动神器RAX3000M路由器变身家庭云之二&#xff1a;安装vsftpd 移动神器RAX3000M路由器变身家庭云之三&#xff1a;外网访问家庭云 移动神器RAX3000M路由器不刷固…

《函数基础与内存机制深度剖析:从 return 语句到各类经典编程题详解》

一、问答题 &#xff08;1&#xff09;使用函数的好处是什么&#xff1f; 1.提升代码的复用性 2.提升代码的可维护性 3.增强代码的可读性 4.提高代码的灵活性 5.方便进行单元测试 &#xff08;2&#xff09;如何定义一个函数&#xff1f;如何调用一个函数&#xff1f; 在Pytho…

Python | 使用Matplotlib绘制Swarm Plot(蜂群图)

Swarm Plot&#xff08;蜂群图&#xff09;是一种数据可视化图表&#xff0c;它用于展示分类数据的分布情况。这种图表通过将数据点沿着一个或多个分类变量轻微地分散&#xff0c;以避免它们之间的重叠&#xff0c;从而更好地显示数据的分布密度和分布趋势。Swarm Plot特别适用…

新版本Xmind结合DeepSeek快速生成美丽的思维导图

前言 我的上一篇博客&#xff08;https://quickrubber.blog.csdn.net/article/details/146518898&#xff09;中讲到采用Python编程可以实现和Xmind的互动&#xff0c;并让DeepSeek来生成相应的代码从而实现对内容的任意修改。但是&#xff0c;那篇博客中提到的Xmind有版本的限…

set和map封装

目录 set和map区别 set和map的插入 set和map的实现 修改红黑树的模板参数 修改比较时使用的变量 迭代器的实现 迭代器的定义 *解引用重载 ->成员访问重载 自增重载 重载 封装迭代器 RBTree迭代器封装 封装set迭代器 对set迭代器进行修改 封装map迭代器 修改…

【Linux】Orin NX + Ubuntu22.04配置国内源

1、获取源 清华源 arm 系统的源,可以在如下地址获取到 https://mirror.tuna.tsinghua.edu.cn/help/ubuntu-ports/ 选择HTTPS,否则可能报错: 明文签署文件不可用,结果为‘NOSPLIT’(您的网络需要认证吗?)查看Orin NX系统版本 选择jammy的源 2、更新源 1)备份原配…

Open-Sora:开源AI视频生成的新星

一.引言 近年来&#xff0c;AI视频生成技术快速发展&#xff0c;从文本生成图像&#xff08;如Stable Diffusion、DALLE&#xff09;到文本生成视频&#xff08;如Runway、Pika&#xff09;&#xff0c;AI在多媒体创作领域的应用日益广泛。近期&#xff0c;Open-Sora作为一款开…

【堆】《深入剖析优先级队列(堆):数据结构与算法的高效搭档》

文章目录 前言例题一、最后一块石头的重量二、数据流中的第 K 大元素三、前K个高频单词四、数据流的中位数 结语 前言 什么是优先级队列算法呢&#xff1f;它的算法原理又该怎么解释&#xff1f; 优先级队列&#xff08;堆&#xff09;算法是一种特殊的数据结构和算法&#xf…

【CMOS输出缓冲器驱动强度】

一 、学习笔记 原始资料&#xff1a;https://www.ti.com.cn/cn/lit/an/zhcae18/zhcae18.pdf?ts1743589394832 Q1、电平转换芯片的其中一个关键指标是转换速率&#xff0c;转换速率跟什么因素有关系呢&#xff1f; 1、瞬态驱动强度 上升或下降时间用于评估瞬态驱动强度。需要…

【C++】Cplusplus进阶

模板的进阶&#xff1a; 非类型模板参数 是C模板中允许使用具体值&#xff08;而非类型&#xff09;作为模板参数的特性。它们必须是编译时常量&#xff0c;且类型仅限于整型、枚举、指针、引用。&#xff08;char也行&#xff09; STL标准库里面也使用了非类型的模板参数。 …

透明的卡组收费模式IC++

IC是信用卡处理商用来计算每笔交易相关费用的定价模型。与统一或混合定价相比&#xff0c;IC提供了额外的透明度。 作为企业主&#xff0c;了解IC定价的来龙去脉至关重要&#xff0c;以确定它是否对您的运营有意义。 什么是IC&#xff1f; IC或interchange plus是一种流行的定…

吾爱置顶软件,吊打电脑自带功能!

今天我给大家带来一款超棒的软件&#xff0c;它来自吾爱论坛的精选推荐&#xff0c;每一款都经过精心挑选&#xff0c;绝对好用&#xff01; S_Clock 桌面计时软件 这款软件的界面设计特别漂亮&#xff0c;简洁又大方。它是一款功能齐全的时钟计时倒计时软件&#xff0c;既能正…

使用MFC ActiveX开发KingScada控件(OCX)

最近有个需求&#xff0c;要在KingScada上面开发一个控件。 原来是用的WinCC&#xff0c;WinCC本身是支持调用.net控件&#xff0c;就是winform控件的&#xff0c;winform控件开发简单&#xff0c;相对功能也更丰富。奈何WinCC不是国产的。 话说KingScada&#xff0c;国产组态软…

【AI论文】CodeARC:评估归纳程序合成中大语言模型代理的推理能力基准

摘要&#xff1a;归纳程序合成&#xff0c;或称示例编程&#xff0c;要求从输入输出示例中合成能够泛化到未见输入的函数。尽管大型语言模型代理在自然语言指导下的编程任务中展现出了潜力&#xff0c;但它们在执行归纳程序合成方面的能力仍待深入探索。现有的评估协议依赖于静…