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 Shaderattribute 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等同步场景,支持上传插件自定义同步转换业务,提供监控全量和增量数据统计图、应用性能预警…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
