LBS 开发微课堂|通过openGL ES轻松实现建筑物渲染及动画
为了让广大开发者
更深入地了解
百度地图开放平台的
技术能力
轻松掌握满满的
技术干货
更加简单地接入
位置服务
我们特别推出了
“位置服务(LBS)开发微课堂”
系列技术案例
第五期的主题是
通过openGL ES轻松实现
建筑物渲染及动画
对于智能穿戴设备的开发者来说,在亲子守护这类应用场景下,精确展示儿童当前的位置信息尤为重要。特别是在复杂的建筑物中,需要能够详尽地指示出儿童所在的建筑物及具体位置。
那么,如何能够在地图上结合定位技术,贴合楼块轮廓,对定位所在的楼块进行自定义纹理展示,并实现当前所在楼栋内的楼层变化的动画效果呢?
今天,我们将详细介绍如何在移动端使用OpenGL ES绘制一个n面棱柱,并探讨纹理贴图、侧面索引的原理及楼层动画的实现过程。
通过代码的方式,帮助开发者更好地理解地图SDK自定义建筑物渲染的整个过程,就让我们一起来学习一下吧!
01 绘制建筑物
1.1 定义顶点与索引
绘制建筑物本质上是绘制n面棱柱体。n面棱柱的顶点数据包括底面顶点、顶面顶点和侧面顶点。
底面和顶面是n边形,侧面由底面和顶面的对应顶点连接而成。
核心代码示例:
// 示例:绘制一个六面棱柱(即长方体)
GLfloat vertices[] = {
// 底面顶点
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
// 顶面顶点
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f
};
索引数据用于指定顶点的连接顺序,形成棱柱的各个面。
// 示例索引数据
GLushort indices[] = {
// 底面
0, 1, 2, 2, 3, 0,
// 顶面
4, 5, 6, 6, 7, 4,
// 侧面
0, 1, 5, 5, 4, 0,
1, 2, 6, 6, 5, 1,
2, 3, 7, 7, 6, 2,
3, 0, 4, 4, 7, 3
};
索引数组
索引数组定义了顶点的连接顺序,从而形成了棱柱的各个面。
侧面生成
通过连接底面和顶面对应的顶点,生成棱柱的侧面。索引数组中的每个侧面由六个顶点组成(两个三角形)。
1.2 顶点着色器和片元着色器
顶点着色器负责处理顶点数据,将其转换为屏幕坐标。
片元着色器负责为每个像素着色。
const char* vertexShaderSource = R"(
attribute vec4 vPosition;
uniform mat4 uModelViewProjectionMatrix;
void main() {
gl_Position = uModelViewProjectionMatrix * vPosition;
}
)";
const char* fragmentShaderSource = R"(
precision mediump float;
uniform vec4 vColor;
void main() {
gl_FragColor = vColor;
}
)";
02 纹理贴图
2.1 纹理坐标
纹理贴图是将二维图像映射到三维模型表面的过程。因此需要定义纹理坐标,并加载纹理图像。
纹理坐标
纹理坐标是一个二维坐标系统,范围为[0, 1]。它定义了如何将纹理图像映射到三维模型的表面上。
// 纹理坐标(示例)
GLfloat textureCoords[] = {
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
// 顶面纹理坐标(重复上述过程)
};
2.2 纹理绘制
在绘制函数中,我们需要绑定纹理、设置着色器参数、传递顶点数据和索引数据,然后调用glDrawElements进行绘制。
纹理环绕
当纹理坐标超出 [0, 1] 范围时,OpenGL提供了多种处理方式,如重复(GL_REPEAT)、镜像重复(GL_MIRRORED_REPEAT)、约束到边缘(GL_CLAMP_TO_EDGE)等。
纹理过滤
纹理过滤用于处理纹理在放大或缩小时的像素处理。常用的过滤方式有邻近过滤(GL_NEAREST)和线性过滤(GL_LINEAR)。
// 加载纹理图像(示例)
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
绘制
void draw() {
glUseProgram(program);
// 设置顶点属性位置
glEnableVertexAttribArray(positionAttribLocation);
glVertexAttribPointer(positionAttribLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
// 设置纹理坐标属性位置
glEnableVertexAttribArray(textureAttribLocation);
glVertexAttribPointer(textureAttribLocation, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
// 绑定纹理
glBindTexture(GL_TEXTURE_2D, textureId);
// 设置着色器中的矩阵参数(示例)
glUniformMatrix4fv(modelViewProjectionMatrixLocation, 1, GL_FALSE, modelViewProjectionMatrix);
// 绘制棱柱
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(GLushort), GL_UNSIGNED_SHORT, indices);
glDisableVertexAttribArray(positionAttribLocation);
glDisableVertexAttribArray(textureAttribLocation);
}
03 楼层动画
实现楼层z轴非线性动画,通过使用顶点着色器(Vertex Shader)来动态修改顶点位置实现。
这种方法可以减少 CPU 到 GPU 的数据传输,提高性能,特别是在顶点数据较多的情况下。
3.1 定义楼层的顶点着色器
定义一个顶点着色器,其中包含一个时间变量和缓动函数,用于计算当前的 Z 坐标偏移。
// Vertex Shader
attribute vec3 aPosition; // 顶点位置
uniform float uTime; // 动画时间,从外部传入
uniform float uHeight; // 最大高度
// 缓动函数
// 开始和结束时速度较慢,中间加速
float easeInOutCubic(float t) {
return t < 0.5 ? 4.0 * t * t * t : (t - 1.0) * (2.0 * t - 2.0) * (2.0 * t - 2.0) + 1.0;
}
void main() {
float t = easeInOutCubic(uTime);
float z = uHeight * t; // 计算当前高度
vec3 transformedPosition = vec3(aPosition.xy, aPosition.z + z); // 更新 Z 坐标
gl_Position = vec4(transformedPosition, 1.0);
}
缓动函数
缓动函数(Easing Functions)是在动画和运动图形中常用的一种技术,用于创建更加平滑和自然的动画效果。主要用于控制动画的速度变化,使得动画不是以恒定速度进行,而是可以加速或减速,或者两者结合。
3.2 更新时间和高度
// 更新时间,高度并传递到着色器
float time = fmod(currentTime, animationDuration) / animationDuration; // 计算归一化时间
glUniform1f(glGetUniformLocation(shaderProgram, "uTime"), time);
glUniform1f(glGetUniformLocation(shaderProgram, "uHeight"), buildingHeight);
3.3 渲染循环
void render() {
// 更新时间
updateDeltaTime();
// 设置时间和高度
glUniform1f(glGetUniformLocation(shaderProgram, "uTime"), time);
glUniform1f(glGetUniformLocation(shaderProgram, "uHeight"), buildingHeight);
// 绘制楼层
drawFloorBuilding();
}
04 效果展示
怎么样,你学会了吗?登录百度地图开放平台官网,轻松实现建筑物的渲染及动画效果!
查看路径:
开发者频道>开发文档>Android地图SDK>开发指南>在地图上绘制>绘制3D建筑物(https://lbsyun.baidu.com/faq/api?title=androidsdk/guide/render-map/3dbuilding)
开发者频道>开发文档>iOS地图SDK>开发指南>在地图上绘制>绘制3D建筑物(https://lbsyun.baidu.com/faq/api?title=iossdk/guide/map-render/3dBuilding)
·END·
你还想了解哪些技术内容?
快来评论区留言告诉我们吧!
相关文章:

LBS 开发微课堂|通过openGL ES轻松实现建筑物渲染及动画
为了让广大开发者 更深入地了解 百度地图开放平台的 技术能力 轻松掌握满满的 技术干货 更加简单地接入 位置服务 我们特别推出了 “位置服务(LBS)开发微课堂” 系列技术案例 第五期的主题是 通过openGL ES轻松实现 建筑物渲染及动画 对于…...
map1[item.id]和map1.get(item.id)的区别为何前者取出的是空,后者取出的是正确的值
在 JavaScript 中,map1[item.id] 和 map1.get(item.id) 用于从 Map 对象中获取值,但它们的工作方式有所不同: map1[item.id]:这种方式用于普通对象(Object),它将 item.id 作为键来获取对应的值…...
window端sqlplus连接linux_oracle11g
1. 环境配置回顾 下载 Oracle Instant Client:根据查询到的版本到链接: oracle官网下载对应版本的三个文件(比如我这里查询到的版本是12.2.0.1.0): instantclient-basic-windows.x64-12.2.0.1.0.zip instantclient-sqlplus-win…...
Go支付中台方案:多平台兼容与多项目对接
一、中台的概念 中台是一种企业级的架构模式,它处于前台应用和后台资源之间,将企业核心能力进行整合、封装,形成一系列可复用的业务能力组件。这些组件就像乐高积木一样,可以被不同的前台业务快速调用,从而避免重复开…...
MySQL触发器的使用详解
MySQL触发器的使用详解 MySQL触发器是一种特殊的存储过程,它与表操作紧密相关,并且在特定事件(如INSERT、UPDATE或DELETE)发生时自动执行。触发器的主要目的是确保数据完整性、实现复杂的业务逻辑以及记录审计信息。它们可以在事…...
关于NLP交互式系统的一些基础入门
【1】What 基于自然语言处理(NLP)的交互式系统是指能够理解、解析并生成人类自然语言的计算机程序。这些系统旨在通过文本或语音与用户进行交流,以提供信息、解决问题或执行任务。以下是关于这类系统的一些关键点: 核心技术&…...
如何在HTML中修改光标的位置(全面版)
如何在HTML中修改光标的位置(全面版) 在Web开发中,控制光标位置是一个重要的技巧,尤其是在表单处理、富文本编辑器开发或格式化输入的场景中。HTML中的光标位置操作不仅适用于表单元素(如<input>和<textarea…...
PHP8 动态属性被弃用兼容方案
PHP 类中可以动态设置和获取没有声明过的类属性。这些属性不遵循具体的规则,并且需要使用 __get() 和 __set() 魔术方法对动态属性如何读写进行有效控制。 class User {private int $uid; }$user new User(); $user->name Foo; 上述代码中,User 类…...

WPF表格控件的列利用模块适配动态枚举类
将枚举列表转化到类内部赋值,在初始化表格行加载和双击事件时,触发类里面的枚举列表的赋值 <c1:Column Header"变更类型" Binding"{Binding ChangeType, ModeTwoWay, ValidatesOnExceptionsTrue, ValidatesOnDataErrorsTrue, NotifyOn…...
【sgUploadImage】自定义组件:基于elementUI的el-upload封装的上传图片、相片组件,适用于上传缩略图、文章封面
sgUploadImage源码 <template><div :class"$options.name"><ul class"uploadImages"><liclass"uploadImage"v-loading"loadings[i]"v-for"(a, i) in uploadImages":key"i"click"click…...
Scala的隐式转换
一: 1.隐式转换概述: 隐式转换与模式匹配都是scala中提供的比较强大的特性。 2.隐式转换的定义: 在实际编程中,要想把一个不匹配的类型赋值,需要先转换成匹配的类型。scala的隐式转换会自动将一种类型的数据转换成…...

从视频编码的进化历程看技术革新
人类对影像的记录和传播从未停止。从最早的胶片电影到如今的数字视频,技术在不断演进。在这个过程中,视频编码技术的发展扮演着关键角色,它决定着我们如何高效地存储和传输视频内容。 视频编码技术的发展历程充满智慧。上世纪90年代…...

ECharts柱状图-阶梯瀑布图,附视频讲解与代码下载
引言: 在数据可视化的世界里,ECharts凭借其丰富的图表类型和强大的配置能力,成为了众多开发者的首选。今天,我将带大家一起实现一个柱状图图表,通过该图表我们可以直观地展示和分析数据。此外,我还将提供…...

如何让Google快速收录你的页面?
要让Google更快地收录你的网站内容,首先需要理解“爬虫”这个概念。Google的爬虫是帮助它发现和评估网站内容质量的工具,如果你的页面质量高且更新频率稳定,那么Google爬虫更可能频繁光顾。通常情况下,通过Google Search Console&…...
比例负载分配L(P);动态调整服务率:LDS
目录 比例负载分配L(P) 动态调整服务率:LDS 速度缩放技术 比例负载分配L(P) 优点 简单直观:其调度器按照服务器服务率倒数比例分配负载,这种方式易于理解和实现,不需要复杂的计算和调整机制。例如,在一个小型企业内部的简单云计算环境中,若服务器配置相对单一且任务类型…...

C++ ——— 类的 6 个默认成员函数之 构造函数
目录 何为默认成员函数 一、构造函数 构造函数的概念 构造函数的特性 日期类的构造函数 栈的构造函数 编译器自动生成的构造函数 总结 何为默认成员函数 默认成员函数就是用户没有显示实现,但是编译器会自动生成的成员函数称为默认成员函数 一、构造函数 …...

win11 恢复任务栏copilot图标, 亲测有效
1、修改C:\Windows\System32\IntegratedServicesRegionPolicySet.json,解除中国不能使用copilot的限制。 使用Notepad搜索copilot全文搜索,将下面两处的“CN,”删除,删除后如下: {"$comment": "Show Copilot on t…...

计算机网络-IPSec VPN工作原理
一、IPSec VPN工作原理 昨天我们大致了解了IPSec是什么,今天来学习下它的工作原理。 IPsec的基本工作流程如下: 通过IKE协商第一阶段协商出IKE SA。 使用IKE SA加密IKE协商第二阶段的报文,即IPsec SA。 使用IPsec SA加密数据。 IPsec基本工作…...

Tomcat项目本地部署
前言: 除了在idea中将项目启动之外,也可以将项目部署在本地tomcat或者云服务器上,本片文章主要介绍了怎样将项目部署在本地tomcat 下面介绍如何使用Tomcat部署本地项目: 1、本篇文章使用的项目案例为一个聚合项目,ha…...

开源数据同步中间件(Dbsyncer)简单玩一下 mysql to mysql 的增量,全量配置
一、什么是Dbsyncer 1、介绍 Dbsyncer是一款开源的数据同步中间件,提供MySQL、Oracle、SqlServer、PostgreSQL、Elasticsearch(ES)、Kafka、File、SQL等同步场景,支持上传插件自定义同步转换业务,提供监控全量和增量数据统计图、应用性能预警…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...