当前位置: 首页 > news >正文

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轻松实现建筑物渲染及动画

为了让广大开发者 更深入地了解 百度地图开放平台的 技术能力 轻松掌握满满的 技术干货 更加简单地接入 位置服务 我们特别推出了 “位置服务&#xff08;LBS&#xff09;开发微课堂” 系列技术案例 第五期的主题是 通过openGL ES轻松实现 建筑物渲染及动画 对于…...

map1[item.id]和map1.get(item.id)的区别为何前者取出的是空,后者取出的是正确的值

在 JavaScript 中&#xff0c;map1[item.id] 和 map1.get(item.id) 用于从 Map 对象中获取值&#xff0c;但它们的工作方式有所不同&#xff1a; map1[item.id]&#xff1a;这种方式用于普通对象&#xff08;Object&#xff09;&#xff0c;它将 item.id 作为键来获取对应的值…...

window端sqlplus连接linux_oracle11g

1. 环境配置回顾 下载 Oracle Instant Client&#xff1a;根据查询到的版本到链接: oracle官网下载对应版本的三个文件&#xff08;比如我这里查询到的版本是12.2.0.1.0&#xff09;&#xff1a; instantclient-basic-windows.x64-12.2.0.1.0.zip instantclient-sqlplus-win…...

Go支付中台方案:多平台兼容与多项目对接

一、中台的概念 中台是一种企业级的架构模式&#xff0c;它处于前台应用和后台资源之间&#xff0c;将企业核心能力进行整合、封装&#xff0c;形成一系列可复用的业务能力组件。这些组件就像乐高积木一样&#xff0c;可以被不同的前台业务快速调用&#xff0c;从而避免重复开…...

MySQL触发器的使用详解

MySQL触发器的使用详解 MySQL触发器是一种特殊的存储过程&#xff0c;它与表操作紧密相关&#xff0c;并且在特定事件&#xff08;如INSERT、UPDATE或DELETE&#xff09;发生时自动执行。触发器的主要目的是确保数据完整性、实现复杂的业务逻辑以及记录审计信息。它们可以在事…...

关于NLP交互式系统的一些基础入门

【1】What 基于自然语言处理&#xff08;NLP&#xff09;的交互式系统是指能够理解、解析并生成人类自然语言的计算机程序。这些系统旨在通过文本或语音与用户进行交流&#xff0c;以提供信息、解决问题或执行任务。以下是关于这类系统的一些关键点&#xff1a; 核心技术&…...

如何在HTML中修改光标的位置(全面版)

如何在HTML中修改光标的位置&#xff08;全面版&#xff09; 在Web开发中&#xff0c;控制光标位置是一个重要的技巧&#xff0c;尤其是在表单处理、富文本编辑器开发或格式化输入的场景中。HTML中的光标位置操作不仅适用于表单元素&#xff08;如<input>和<textarea…...

PHP8 动态属性被弃用兼容方案

PHP 类中可以动态设置和获取没有声明过的类属性。这些属性不遵循具体的规则&#xff0c;并且需要使用 __get() 和 __set() 魔术方法对动态属性如何读写进行有效控制。 class User {private int $uid; }$user new User(); $user->name Foo; 上述代码中&#xff0c;User 类…...

WPF表格控件的列利用模块适配动态枚举类

将枚举列表转化到类内部赋值&#xff0c;在初始化表格行加载和双击事件时&#xff0c;触发类里面的枚举列表的赋值 <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的隐式转换

一&#xff1a; 1.隐式转换概述&#xff1a; 隐式转换与模式匹配都是scala中提供的比较强大的特性。 2.隐式转换的定义&#xff1a; 在实际编程中&#xff0c;要想把一个不匹配的类型赋值&#xff0c;需要先转换成匹配的类型。scala的隐式转换会自动将一种类型的数据转换成…...

从视频编码的进化历程看技术革新

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

ECharts柱状图-阶梯瀑布图,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个柱状图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供…...

如何让Google快速收录你的页面?

要让Google更快地收录你的网站内容&#xff0c;首先需要理解“爬虫”这个概念。Google的爬虫是帮助它发现和评估网站内容质量的工具&#xff0c;如果你的页面质量高且更新频率稳定&#xff0c;那么Google爬虫更可能频繁光顾。通常情况下&#xff0c;通过Google Search Console&…...

比例负载分配L(P);动态调整服务率:LDS

目录 比例负载分配L(P) 动态调整服务率:LDS 速度缩放技术 比例负载分配L(P) 优点 简单直观:其调度器按照服务器服务率倒数比例分配负载,这种方式易于理解和实现,不需要复杂的计算和调整机制。例如,在一个小型企业内部的简单云计算环境中,若服务器配置相对单一且任务类型…...

C++ ——— 类的 6 个默认成员函数之 构造函数

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

win11 恢复任务栏copilot图标, 亲测有效

1、修改C:\Windows\System32\IntegratedServicesRegionPolicySet.json&#xff0c;解除中国不能使用copilot的限制。 使用Notepad搜索copilot全文搜索&#xff0c;将下面两处的“CN,”删除&#xff0c;删除后如下&#xff1a; {"$comment": "Show Copilot on t…...

计算机网络-IPSec VPN工作原理

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

Tomcat项目本地部署

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

开源数据同步中间件(Dbsyncer)简单玩一下 mysql to mysql 的增量,全量配置

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

虚幻引擎开发命名规则

UE的命名规则如下&#xff1a; 模版类以T作为前缀&#xff0c;例如TArray, TMap, TSet。UObject派生类都以U前缀。AActor派生类都以A前缀。SWidget派生类都以S前缀。全局对象使用G开头&#xff0c;如GEngine。抽象接口以I前缀。枚举以E开头。bool变量以b前缀&#xff0c;如bPe…...

解释强化学习中的batch, epoch, episode有什么区别与联系,分别有什么作用

强化学习中的batch, epoch, episode 1.Batch1.1 最后一个batch不足32该怎么处理&#xff1f;1.1.1 方法一&#xff1a;丢弃最后一个不完整的 batch1.1.2 方法二&#xff1a;填充最后一个不完整的 batch1.1.3 选择哪种方法&#xff1f; 2.Epoch3.Episode4.区别与联系4.1 区别4.2…...

MVC基础——市场管理系统(一)

文章目录 项目地址一、创建项目结构1.1 创建程序以及Controller1.2 创建View1.3 创建Models层,并且在Edit页面显示1.4 创建Layou模板页面1.5 创建静态文件css中间件二、Categories的CRUD2.1 使用静态仓库存储数据2.2 将Categorie的列表显示在页面中(List)2.3 创建_ViewImport.…...

使用docker-compose安装Milvus向量数据库及Attu可视化连接工具

首先确保系统已经安装上了docker 然后去https://github.com/docker/compose/releases/下载安装docker-compose 跟随自己下系统和服务器情况下载 上传到服务器 mv docker-compose-linux-aarch64 docker-compose chmod x docker-compose2.dockr-compose命令 docker-compose …...

PostgreSQL函数中使用now()或current_timestamp的异同

在PostgreSQL函数中使用now()或current_timestamp可以获取当前的日期和时间。 now()函数返回当前的日期和时间&#xff0c;包括时区信息。它可以用于记录操作的时间戳或在查询中进行时间比较。 current_timestamp函数也返回当前的日期和时间&#xff0c;但不包括时区信息。它…...

开发类似的同款小程序系统制作流程

很多老板想要开发一款和别人家类似的同款小程序系统&#xff0c;但是不知道该怎么开发制作&#xff0c;本文就为大家详细介绍一下开发类似的同款小程序的流程为大家做参考。 一、前期准备找到对标小程序&#xff1a;首先&#xff0c;需要找到你想要模仿的同款小程序&#xff0…...

bsp是板级支持包

里面有很多的针对该型号的板子的函数&#xff0c;可以直接调用&#xff0c;也可以直接在里面。 也可以在vivado的sdk上&#xff0c;看到很多相关文档和寄存器偏移等等。...

P1784 数独 C语言(普遍超时写法)

题目&#xff1a; https://www.luogu.com.cn/problem/P1784 题目描述 数独是根据 99 盘面上的已知数字&#xff0c;推理出所有剩余空格的数字&#xff0c;并满足每一行、每一列、每一个粗线宫内的数字均含 1−9 &#xff0c;不重复。每一道合格的数独谜题都有且仅有唯一答案…...

基于最新的Apache StreamPark搭建指南

一、StreamPark 的介绍 官方文档:Apache StreamPark (incubating) | Apache StreamPark (incubating) 中文文档:Apache StreamPark (incubating) | Apache StreamPark (incubating)Github地址:https://github.com/apache/incubator-streampark Apache StreamPark™ 是一个…...

思科模拟器路由器的基本配置

一、实验目的 了解路由器的作用掌握路由器的基本配置方法 3、掌握路由器模块的使用和互连方式 二、实验环境 2811路由器一台&#xff0c;计算机两台&#xff0c;Console配置线一根&#xff0c;网线若干&#xff1b;本实验拓扑图如图8-1所示&#xff1b;计算机IP地址规划如表8-…...

建设银行网站登录首页/给网站做seo的价格

客制化键盘的那些事儿——GH60篇&#xff0c;入坑的朋友们一定要注意的事是由B2B101网站(www.b2b101.com)为您收集修改整理而来&#xff0c;更多相关内容请关注B2B101网站其他品牌栏目。客制化键盘中的gh60&#xff0c;是国外一个geek论坛的一群大神们无聊搞出来的一个东西&…...

自己网站上做淘宝搜索引擎/搜索引擎优化排名优化培训

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace _053_委托的使用 {//定义一个委托跟函数差不多&#xff0c;区别在于//1,定义委托需要加上delegate关键字//2,委托的定义不需要函数体public d…...

外包加工网可信吗/seo推广软件怎样

我已经创建了一个相机应用程序,我想让我的应用程序在所有4个可能的方向转换,并相应地更新相机预览.因为我已经使用我从以下复制的以下方法&#xff1a;Android – Camera preview is sidewayspublic void updateCameraDisplay(int w, int h) {// set preview size and make any…...

网站建设与制作/百度推广托管

Part 13 Jay&Gloria ——2018.10.12(五) 写 ——2018.10.13(六) 读 狗娘养...你给我的螺丝刀不对 Ah, son of a- You gave me the wr…...

潍坊点睛做网站怎么样/goole官网

在上一篇文章中我们了解到颜色在甘特图中也有不同的作用。其中颜色在甘特图中扮演着三个角色&#xff0c;才能使甘特图对用户有意义。 颜色决定甘特图的外观。颜色还可以用来定义甘特图的语义。因此&#xff0c;它们帮助用户更快地理解甘特图所呈现的完整且常常复杂的现实。颜…...

用微信微博网站来做睡眠经济/社交媒体营销

很多Linux发行版本都提供了可视化的系统管理工具&#xff0c;比如&#xff1a;Red Hat的administrator tool及SUSe。这些可视化的工具给Linux用户带来了很大的方便。从而让系统管理工作变得只是单击鼠标这样简单。然而这些工具在另一个方面只是隐藏了实施配置的底层机制。尽管这…...