写入纹理数据:

  主要分为五种写入方式:新建纹理、编辑已有纹理、编辑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. [POJ3468] A Simple Problem with Integers (Treap)

    题目链接:http://poj.org/problem?id=3468 这题是线段树的题,拿来学习treap. 不旋转的treap. #include <cstdio> #include ...

  2. OpenGL学习笔记0——安装库

    最近需要做一个基于Zigbee室内无线定位的系统,受到TI公司ZigBee Sensor Monitor软件的启发,打算用OpenGL来做一个3D显示空间内物体位置的程序.学习阶段选择VS2010+O ...

  3. PHP中对淘宝URL中ID提取

    <?php $taobao = 'taobao.com'; $tmall = 'tmall.com'; $guojitmall = 'tmall.hk'; $juhuasuan = 'ju.ta ...

  4. setContentView R can not be resovled

    原因:gen包下没有自动生成R.java的资源文件 解决办法:再次新建android application project,默认Theme为Holo Light With Dark Action B ...

  5. setContentType、setCharacterEncoding、pageEncoding和contentType

    request.setCharacterEncoding()是设置从request中取得的值或从数据库中取出的值 response.setContentType("text/html;cha ...

  6. Ajax跨域请求

    客户端前台: //浏览器支持跨域访问,置于Ajax方法前$.support.cors = true; 服务器后台: //设置服务器端对于CORS的跨域请求支持,置于后台方法第一行 Response.A ...

  7. Win10光驱不见了

    1. 网上教程试了很多,如下: http://jingyan.baidu.com/article/02027811656a8b1bcd9ce570.html http://jingyan.todgo. ...

  8. UpdatePanel无法导出下载文件

    转自 http://www.cnblogs.com/vipsoft/p/3298299.html protected void Page_Load(object sender, EventArgs e ...

  9. ios https适配(单向验证)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https是http+tls.是在http和tcp之间添加了一层ssl加密验证,ssl将http发送的信息在将要发到传输层时进行了加密,同样数据从 ...

  10. LR12.53—第1课:构建Vuser脚本

    第1课:构建Vuser脚本 要生成系统上的负载,首先建立一个可以运行以模拟真实用户行为Vuser脚本.您使用VuGen创建和构建Vuser脚本. 在这一课中,你将涵盖以下主题: 介绍VuGen将 - ...