写入纹理数据:

  主要分为五种写入方式:新建纹理、编辑已有纹理、编辑ExtHeader中的指定项、写入元数据和写入指定面的纹理数据。写入过程中数据存在一个临时文件中,在close时才会把临时文件的内容拷贝到指定写入的文件中并删除临时文件。

  1. 新建纹理。调用对应的open函数,首先应该校验新建的纹理参数是否符合要求,然后用main writer(继承自base writer)写入,基本就是初始化header和ruduce函数的绑定,同时设置压缩方式并新建临时tile文件以供写入。新纹理写入到.new文件,保存时再写入到最终位置。初始化时用到了std::vector.reserve和resize,以前没注意,现在知道,增大时,reserve改变vector的容量(分配空间)并使所有迭代器无效,resize增加元素,减小时,reserve没有减小的功能(可用shrink_to_fit),resize会减小元素数,但不会改变容量,二者对应的大小用capacity和size获取。由于是新建,所以tex参数为空指针,在初始化PtexMainWriter时不会有纹理信息的复制。
  2. 编辑已有纹理。校验格式后需检查是否已有该文件,如果文件存在,编辑方式根据是否为incremental决定用incremental writer(继承自base writer)或main writer,如果文件存在,则关闭已打开文件后再用reader打开并校验header,否则和新建一样直接用main writer。incremental writer写入的数据不压缩(main writer要压缩,在base writer初始化时设置),从而避免每次保存都要压缩编辑又要解压缩,只在最终保存时压缩一次,提高保存效率。校验header和extended header(不需要用reader打开),通过后移到文件末位准备写入。
  3. 写入元数据。根据参数的不同,分为添加和复制,复制实际是对添加的一层封装,先校验key的长度和value的大小,如果当前key已存在,则覆盖value,不存在则新建。
  4. 写入指定面的纹理数据。分写入普通数据和常量数据,main writer和incremental writer写入方式不同:
    1. main writer
      1. 写入普通数据时,需校验faceinfo,记录当前面在文件中的位置后,写入面数据,如果有alpha通道,先将数据复制到临时buffer中,然后乘上alpha通道,然后再用临时buffer的数据覆盖原数据,最后,如果需要生成mipmap则生成第一级reduction,默认分辨率大于2x2才能生成,否则所有数据除以uv分辨率的乘积后保存到面的常量区,如果有alpha通道还要再除以alpha值。所有操作完成后释放临时buffer并标记有新数据写入。
      2. 写入常量数据时,校验faceinfo后,直接复制数据到面的常量区。
    2. incremental writer
      1. 写入普通数据时,与main writer大部分过程相似,但是因为要更新header信息,所以多了header写入,但是header的信息要在面数据写入后才能获得,所以先留出header的空间并记录位置,写完面信息后再倒回去写header,最后再把fp移到末尾。
      2. 写入常量数据时,同样需要写入header,不过因为是常量数据,所以header信息预先知道,所以可以写入header后再写入面数据就完成了。
  5.   关闭文件。main writer和incremental writer的close函数都需要先调用base writer的close函数间接调用各自的finish函数写入新数据,main writer较为复杂,如果已有reader(在编辑的时候会将用reader打开纹理,reader存在说明新添加了纹理),则需要从reader中获取facedata,然后根据是否为常量写入数据(从reader里复制),如果没有reader(说明没有添加新纹理),则直接将缺失纹理的面标记为常量。然后根据需要生存mipmap,标记有常量相邻面的面,更新header的level和face数目信息。然后新建文件,根据ptex规定的存储顺序依次写入数据,注意header、extended header和level的部分信息(header大小和levelinfo)在数据写入完成前是不知道的,所以要预先留空,之后再填上。faceinfo和constdata直接写入新建文件,facedata需要按level写入,每一个level先写leveldataheader,然后再从之前写入的临时文件复制该level的各个面的纹理数据到新文件。所有都完成后关闭新文件(即保存的文件),如果之前是按tile写入的,base writer会在完成后删除tile文件,main writer需要释放reader和删除临时文件(如果有),最后删除原文件,将新文件的文件名(原文件名后面加了.new)改成原文件的文件名(去掉.new)。incremental writer在base writer关闭后关闭fp就可以了。

Ptex源码学习笔记-2的更多相关文章

  1. Ptex源码学习笔记-1

    Ptex是Walt Disney Animation Studios开发的纹理映射工具.在看一个叫appleseed的渲染器时看到他支持这种纹理,所以就查看一下,发现比较轻量,所以就想趁此机会学习下. ...

  2. Underscore.js 源码学习笔记(下)

    上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...

  3. Underscore.js 源码学习笔记(上)

    版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}());  这样的东西,我们应该知道这是一个 IIFE(立即执行 ...

  4. AXI_LITE源码学习笔记

    AXI_LITE源码学习笔记 1. axi_awready信号的产生 准备接收写地址信号 // Implement axi_awready generation // axi_awready is a ...

  5. Hadoop源码学习笔记(6)——从ls命令一路解剖

    Hadoop源码学习笔记(6) ——从ls命令一路解剖 Hadoop几个模块的程序我们大致有了点了解,现在我们得细看一下这个程序是如何处理命令的. 我们就从原头开始,然后一步步追查. 我们先选中ls命 ...

  6. Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构

    Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构 之前我们简要的看过了DataNode的main函数以及整个类的大至,现在结合前面我们研究的线程和RPC,则可以进一步 ...

  7. Hadoop源码学习笔记(4) ——Socket到RPC调用

    Hadoop源码学习笔记(4) ——Socket到RPC调用 Hadoop是一个分布式程序,分布在多台机器上运行,事必会涉及到网络编程.那这里如何让网络编程变得简单.透明的呢? 网络编程中,首先我们要 ...

  8. Hadoop源码学习笔记(3) ——初览DataNode及学习线程

    Hadoop源码学习笔记(3) ——初览DataNode及学习线程 进入了main函数,我们走出了第一步,接下来看看再怎么走: public class DataNode extends Config ...

  9. Hadoop源码学习笔记(2) ——进入main函数打印包信息

    Hadoop源码学习笔记(2) ——进入main函数打印包信息 找到了main函数,也建立了快速启动的方法,然后我们就进去看一看. 进入NameNode和DataNode的主函数后,发现形式差不多: ...

随机推荐

  1. ACdream 1017 [分层图][网络流]

    /* 大连热身C题 不要低头,不要放弃,不要气馁,不要慌张 题意: 给一个城市路线图,给定起点给定终点.有n个货物从起点运送到终点.城市的边是无向边. 每个货物每天如果通过某条路,那么这天这条路只能运 ...

  2. php服务生成exe附件下载

    <?php $realname = "zhuast.exe"; //原始文件名 $filename = "中文 文件名.exe"; //下载到浏览器的文件 ...

  3. js模版解析

    function JzRender(tpl, data) { // 模版解析 data是对象则返回字符串,是数组则返回字符串数组 if (data instanceof Array) { var s ...

  4. Apache日志分析

    Apache日志统计举例 加些来了解一下如何统计Apache的访问日志,一般可以用tail命令来实时查看日志文件变化,但是各种的应用系统中的日志会非常复杂,一堆长度超过你浏览极限的日志出现在你眼前时, ...

  5. backup2

    /// <summary> /// 先在窗体上添加LicenceControl控件 /// Enable 3D analysis /// </summary> public v ...

  6. TCP/IP之大明内阁---协议的制定

    个人感言:真正的知识是深入浅出的,码农翻身" 公共号将苦涩难懂的计算机知识,用形象有趣的生活中实例呈现给我们,让我们更好地理解.感谢"码农翻身" 公共号,感谢你们的成果, ...

  7. 从request获取远程IP地址

    public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("X-F ...

  8. re正则表达式

    1.matchimport rem = re.match("[0-9]{0,10}","7564565abcdefg") #match从开头开始匹配if m: ...

  9. C语言typedef的用法(转)

    http://www.cnblogs.com/afarmer/archive/2011/05/05/2038201.html 一.基本概念剖析 int* (*a[5])(int, char*);    ...

  10. 优秀的JavaScript开发框架

    JavaScript基本上是一个面向对象的脚本语言,创建web应用程序和互动网站.Javascript框架也被称为Javascript库.JavaScript框架很容易提高设计web开发工作,提供了许 ...