以前 Simple2D 使用 TextureManager,现在将它改为 TexturePool (纹理池)。主要是负责加载和管理纹理,这次为 TexturePool 添加纹理集的功能,纹理集就是将大量的图片拼合成一张纹理。

  纹理集的制作

  你可以使用软件 TexturePacher 来创建纹理集:

  将图片文件拖曳到左边的窗口,然后将 Output 的 DataFormat 设置为 cocos2d,最后选择 Data File 和 Texture File 的输出路径,点击工具栏的 Publish 按钮后得到两个文件 xxx.plist 和 xxx.png,再将这两个文件放置在 Assert 文件夹即可。

  解析 Plist 文件

  由于 Plist 文件时 xml 格式的,所以可以使用 Tinyxml 库来解析,其中只需要读取 plist 文件的三个信息即可:

  1、纹理文件名,与小图相关联的标签

  2、小图的大小和小图在大图中的位置偏移,用来计算纹理坐标

  3、小图是否旋转,TexturePacher 在合并小图时为了合理分配空间位置,必要时会对小图旋转 90o,计算纹理坐标时要进行旋转

  OpenGL 为每个纹理分配一个唯一的 ID,而纹理集的多张小图都来自于一张纹理,为了管理这些纹理,需要两个结构:TextureUnique 和 Texture2D。TextureUnique 对于着一张纹理,而 Texture2D 则对应小图:

    struct Texture2D{TextureUnique* textureUnique;int     width;int     height;Vec2 uv[4];};

  Texture2D 保存图片的大小(该大小是小图的大小,不是纹理的大小)、纹理坐标和 TextureUnique 对象。

  TexturePool 使用 ParsePlistFile( ) 函数来解析 plist 文件:

bool TexturePool::ParsePlistFile(const std::string& filename, std::vector<PlistParseData>& ppd_list){tinyxml2::XMLDocument doc;auto path = PathHelper::fullPath(filename);if ( doc.LoadFile(path.c_str()) != tinyxml2::XML_NO_ERROR ) {LOG_WRITE_DEBUG("不存在 plist 文件:%s", filename.c_str());return false;}tinyxml2::XMLElement* frame_ele = nullptr;tinyxml2::XMLElement* context_ele = nullptr;tinyxml2::XMLNode* plist_node = doc.RootElement();plist_node = plist_node->FirstChildElement();frame_ele = plist_node->FirstChildElement();tinyxml2::XMLElement* begin_node = frame_ele->NextSiblingElement()->FirstChildElement();std::string left, right;while ( begin_node ) {PlistParseData ppd;ppd.filename = begin_node->GetText();context_ele = begin_node->NextSiblingElement();context_ele = context_ele->FirstChildElement("string");std::string size = context_ele->GetText();/* {{xx, xx},{xx, xx}} */left = size.substr(2, size.find_first_of("}") - 2);right = left.substr(left.find_first_of(",") + 1, left.size() - left.find_first_of(","));left = left.substr(0, left.find_first_of(","));ppd.offsetx = atoi(left.c_str());ppd.offsety = atoi(right.c_str());right = size.substr(size.find_last_of("{") + 1, size.size() - size.find_last_of("{") - 3);left = right.substr(0, right.find_first_of(","));right = right.substr(right.find_first_of(",") + 1, right.size() - right.find_first_of(","));ppd.width = atoi(left.c_str());ppd.height = atoi(right.c_str());context_ele = context_ele->NextSiblingElement();context_ele = context_ele->NextSiblingElement();context_ele = context_ele->NextSiblingElement();context_ele = context_ele->NextSiblingElement();std::string rotate = context_ele->Name();ppd.rotate = (rotate.compare("true") == 0);begin_node = begin_node->NextSiblingElement();begin_node = begin_node->NextSiblingElement();ppd_list.push_back(ppd);}/* 获取图像文件名 */frame_ele = frame_ele->NextSiblingElement();frame_ele = frame_ele->NextSiblingElement();frame_ele = frame_ele->NextSiblingElement();tinyxml2::XMLElement* metadata = frame_ele->FirstChildElement("string");std::string texture_name = metadata->GetText();metadata = metadata->NextSiblingElement("string");std::string texture_size = metadata->GetText();int dot = texture_size.find_first_of(",");PlistParseData ppd;ppd.filename = texture_name;ppd.width    = atoi(texture_size.substr(1, dot - 1).c_str());ppd.height   = atoi(texture_size.substr(dot + 1, texture_size.size() - dot - 2).c_str());ppd_list.push_back(ppd);return true;}

  将解析得到的小图数据保存到 PlistParseData 结构中,然后得到一个 PlistParseData 数组:

        struct PlistParseData{std::string filename;bool rotate;int offsetx;int offsety;int width;int height;};

  通过 PlistParseData 数组就可以创建 TextureUnique 和 Texture2D 对象了:

bool TexturePool::LoadFileFromPlist(const std::string& filename){std::vector<PlistParseData> ppd_list;if ( ParsePlistFile(filename, ppd_list) == false ) {LOG_WRITE("解析文件 %s 失败!", filename.c_str());return false;}TextureUnique* texture_unique = new TextureUnique(ppd_list.back().filename.c_str());for ( int i = 0; i < ppd_list.size() - 1; i++ ) {PlistParseData& ppd = ppd_list[i];Texture2D* texture_2d = new Texture2D;texture_2d->textureUnique = texture_unique;texture_2d->width = ppd.width;texture_2d->height = ppd.height;/* 计算纹理坐标 */Vec2 p1, p2;if ( ppd.rotate ) {p1.x = ( float ) ppd.offsetx / texture_unique->width;p1.y = 1 - ( float ) (ppd.offsety + ppd.width) / texture_unique->height;p2.x = ( float ) (ppd.offsetx + ppd.height) / texture_unique->width;p2.y = 1 - ( float ) ppd.offsety / texture_unique->height;texture_2d->uv[3].set(p1.x, p1.y);texture_2d->uv[0].set(p1.x, p2.y);texture_2d->uv[1].set(p2.x, p2.y);texture_2d->uv[2].set(p2.x, p1.y);}else {p1.x = ( float ) ppd.offsetx / texture_unique->width;p1.y = 1- ( float ) (ppd.offsety + ppd.height) / texture_unique->height;p2.x = ( float ) (ppd.offsetx + ppd.width) / texture_unique->width;p2.y = 1- ( float ) ppd.offsety / texture_unique->height;texture_2d->uv[0].set(p1.x, p1.y);texture_2d->uv[1].set(p1.x, p2.y);texture_2d->uv[2].set(p2.x, p2.y);texture_2d->uv[3].set(p2.x, p1.y);}vTextureMap.insert(std::make_pair(ppd.filename, texture_2d));}return true;}

  将得到的 Texture2D 对象保存到一个数组中,最后通过 TexturePool 提供的函数 Texture2D* GetTexture(const std::string& filename) 获取 Texture2D 对象。而 TextureUnique 则用于纹理的删除,但 TexturePool 并没有提供纹理的删除操作,也就是你无法再不需要纹理时删除纹理,只能在程序结束后删除。

  Texture2D 是 Sprite、Painter 和 ImGui 使用的图片渲染对象,而 TextureUnique 只是在 TexturePool 内部使用。

  源码下载:Simple2D-20.rar

转载于:https://www.cnblogs.com/ForEmail5/p/7464647.html

Simple2D-22(重构)纹理池相关推荐

  1. javaweb学习总结(三十九)——数据库连接池

    javaweb学习总结(三十九)--数据库连接池 一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10 ...

  2. javaweb学习总结(三十九):数据库连接池

    一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...

  3. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(一)

    课程简介: 课程目标:通过本课程学习,深入理解Java线程池,提升自身技术能力与价值. 适用人群:具有Java多线程基础的人群,希望深入理解线程池底层原理的人群. 课程概述:多线程的异步执行方式,虽然 ...

  4. 《Real-Time Rendering 4th Edition》读书笔记--简单粗糙翻译 第六章 纹理 Texturing

    写在前面的话:因为英语不好,所以看得慢,所以还不如索性按自己的理解简单粗糙翻译一遍,就当是自己的读书笔记了.不对之处甚多,以后理解深刻了,英语好了再回来修改.相信花在本书上的时间和精力是值得的. -- ...

  5. 用于视觉识别的深度卷积网络空间金字塔池化方法

    摘要 现有的深卷积神经网络(CNN)需要一个固定大小的神经网络(例如224x224)的输入图像.这种要求是"人为的",可能会降低对任意大小/尺度的图像或子图像的识别精度.在这项工作 ...

  6. Real-Time Rendering 4th 译文《六 纹理(上)》

    "所需要做的仅是为了使渲染图像看起来正确." -- 吉姆·布林 表面的质感就是外观和感觉 -- 只要想一想油画的质感就知道了.在计算机图形学中,纹理化是获取表面并使用某些图片.函数 ...

  7. 使用Druid,C3P0连接池连接达梦主备集群

    使用Druid,C3P0连接达梦数据库主备集群 导入连接池对应的驱动包,达梦的JDBC驱动包进行连接 连接池信息: Druid连接池版本:1.1.22 C3P0连接池版本:0.9.1 链接:https ...

  8. Real-Time Rendering——6.3 Procedural Texturing程序纹理

    Given a texture-space location, performing an image lookup is one way of generating texture values. ...

  9. 孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(三十九)——数据库连接池 一、应用程序直接获取数据库连接的缺点   用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要

    孤傲苍狼 只为成功找方法,不为失败找借口! javaweb学习总结(三十九)--数据库连接池 一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对 ...

最新文章

  1. 透过水晶球一瞥下一代SOC
  2. 电脑开机出现C:\Windows\System32\drivers\fs_rec.sys
  3. HP ML110/120 G7配置阵列卡安装server 2003
  4. mybatis plug 只查id_mybatis-plugin的几种常用的方法
  5. 开头th_是什么文件_Python文件读写最详细的讲解
  6. 从 0 到 1,高德 Serverless 平台建设及实践
  7. 万字详解Lambda、Stream和日期
  8. 正则化、归一化含义解析(一)
  9. Centos7通过yum安装jdk8
  10. MSSOAP与WebService
  11. 一道和逆向和溢出有关的竞赛题分析
  12. 基于iframe的CFS(Cross Frame Script)和Clickjacking(点击劫持)攻击
  13. LoadRunner录制app脚本详解
  14. 外卖霸王餐返利小程序开发制作功能介绍
  15. unity3d通过粒子系统制作火焰效果
  16. 计算机内存条多大容量,电脑内存条到底怎么选?选多大容量最合适?
  17. 使用Python统计股票高开后的走势
  18. python手机端给电脑端发送数据_神途传奇 (手机端+电脑端) 数据互通 传奇来袭 www.8wf.com...
  19. 不使用库函数实现字符串复制函数strCopy
  20. 大学“电路分析基础”试题合集第四章

热门文章

  1. 企业信息化投入中咨询服务_嘉萱企业管理咨询服务 让发展中的企业真正实现全面性效益增长...
  2. php 判定是否是数组,php判断一个数组是否为有序
  3. g的python实现_Python Gevent
  4. java中插入排序_Java中的插入排序
  5. android爬虫_进行Android Web爬虫改造
  6. jquery 查找祖先元素_如何获得jQuery中元素的第一个祖先
  7. vscode中vue-cli项目es-lint的配置
  8. 温故之.NET 任务并行
  9. 支付宝微信支付回调地址访问不成功
  10. 在mac中配置apache+php5.3+mysql的环境,修改hosts