• 【partio】继续探索粒子格式库partio


    上一节内容讲了安装与Hello World例子。

    原理

    类模型

    有三个核心的类:

    1. ParticlesInfo 是元数据。记录粒子数目、有哪些属性。
    2. ParticlesData 只读粒子数据
    3. ParticlesDataMutable 可写可读粒子数据

    对应的有三个重要函数。原型都在Partio.h之中。

    readHeaders()
    	返回元数据,如粒子数目和有哪些属性。
    readCached()
    	返回只读的ParticlesData 
    create() and read()
    	返回可读可写的ParticlesDataMutable
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    属性数据模型

    所有的粒子属性都是以下三种基本数据结构的组合

        VECTOR[3]
        FLOAT[d]
        INT[d]
    
    • 1
    • 2
    • 3
    其中 VECTOR[3] 和FLOAT[3] 是一样的
    VECTOR[4]是无效的,FLOAT[4]是有效的。FLOAT可以指定任意维度 FLOAT[1...infinity]
    
    • 1
    • 2

    遍历

    有多种遍历的方式:

    • 若使用SIMD , 则推荐dataAsFloat()和data(arrayOfIndices)
    • 推荐Cache ParticleAttributes 而非循环
    • 使用迭代器,这比data()或dataAsFloat 的方式要快

    后端

    有三种实现

    • SimpleParticles
    • ParticleHeaders
    • SimpleParticlesInterleaved

    读写器

    可以自己在io文件夹添加新的读写器。

    1. 需要实现这三个接口:
      ParticlesInfo, ParticlesData and ParticlesDataMutable
    2. 然后在io/readers.h中添加函数原型
    3. 在io/ParticleIO.cpp中添加后缀绑定

    实践(例子)

    参考src\tests\testio.cpp

    读取文件

      Partio::ParticlesDataMutable* data=Partio::read("E:/codes/try/partio/my_partio/test.bgeo");
    
    • 1

    参数:只需要提供绝对路径即可。
    返回值:Partio::ParticlesDataMutable* 是partio内部数据结构的指针

    注意路径必须是const char*。如果是std::string,需要利用.c_str()方法转换为const char *格式。

    read方法会先忽略你的.gz后缀,然后调用reader()函数匹配后缀,最后在相应后缀的函数(每个io目录下的文件对应一种格式)中读取文件。入口函数在 src\lib\io\ParticleIO.cpp

    写入文件

    write函数同理。

    Partio::write(filename,*p);
    
    • 1

    只需要给出绝对路径(同样需要const char *格式),并给出一个指针即可。

    这个指针的数据类型是partio内部数据结构的指针Partio::ParticlesData*
    也可以是ParticlesDataMutable *

    完整例子注解

    // 首先必须引入头文件Partio.h
    #include 
    #include 
    
    // 生产数据用于测试
    Partio::ParticlesDataMutable* makeData()
    {
        // 利用create创建可读写对象foo(这里用的是引用)
        Partio::ParticlesDataMutable& foo=*Partio::create();
        // 利用addAttribute方法增加三种属性:位置、寿命、id。
        Partio::ParticleAttribute positionAttr=foo.addAttribute("position",Partio::VECTOR,3);
        Partio::ParticleAttribute lifeAttr=foo.addAttribute("life",Partio::FLOAT,2);
        Partio::ParticleAttribute idAttr=foo.addAttribute("id",Partio::INT,1);
        
        // 增加的同时遍历5个粒子:
        for(int i=0;i<5;i++){
            // 粒子的编号
            Partio::ParticleIndex index=foo.addParticle();
            // 获取对应属性、对应编号的粒子数据的指针。
            float* pos=foo.dataWrite<float>(positionAttr,index);
            float* life=foo.dataWrite<float>(lifeAttr,index);
            int* id=foo.dataWrite<int>(idAttr,index);
            
            // 在指针处写入数据
            pos[0]=.1*i;
            pos[1]=.1*(i+1);
            pos[2]=.1*(i+2);
            life[0]=-1.2+i;
            life[1]=10.;
            id[0]=index;
            
        }
        // 返回foo对象指针
        return &foo;
    }
    
    void testEmptySaveLoad(const char* filename)
    {
        Partio::ParticlesDataMutable* p=Partio::create();
        p->addAttribute("position",Partio::VECTOR,3);
        std::cerr<<"Testing empty save with file '"<<filename<<"'"<<std::endl;
        Partio::write(filename,*p);
        p->release();
        Partio::ParticlesDataMutable* pread=Partio::read(filename);
        pread->release();
    }
    
    // 测试读与写。第一个参数是数据指针p, 第二个参数是文件绝对路径
    void testSaveLoad(Partio::ParticlesData* p,const char* filename)
    {
        std::cerr<<"Testing with file '"<<filename<<"'"<<std::endl;
        // 写数据
        Partio::write(filename,*p);
    
        // 读数据(与读无关)
        Partio::ParticlesData* pnew=Partio::read(filename);
        // 释放读了的数据对象
        pnew->release();
    }
    
    int main(int argc,char *argv[])
    {
        {
            // 生产数据
            Partio::ParticlesDataMutable* foo=makeData();
            // 测试各个格式的读写
            testSaveLoad(foo,"test.bgeo");
            testSaveLoad(foo,"test.bgeo.gz");
            testSaveLoad(foo,"test.geo");
            testSaveLoad(foo,"test.geo.gz");
            testSaveLoad(foo,"test.ptc");
            testSaveLoad(foo,"test.ptc.gz");
            testSaveLoad(foo,"test.pdb");
            testSaveLoad(foo,"test.pdb.gz");
            testEmptySaveLoad("testEmpty.geo");
            testEmptySaveLoad("testEmpty.bgeo");
            testEmptySaveLoad("testEmpty.pdb");
            testEmptySaveLoad("testEmpty.ptc");
            // 释放对象
            foo->release();
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    下期
    探索Partio(3): 将Partio数据封装成单例

  • 相关阅读:
    keepalived配置高可用web服务器
    浅谈IT隔离电源系统在医疗场所的接地设计研究与应用
    不同设备使用同一个Git账号
    Spring4 + SpringMVC + Hibernate4 环境搭建
    无人值守的共享台球室:微信小程序实现自助服务
    计算机SCI论文讨论部分怎么写? - 易智编译EaseEditing
    周星驰亲自下场招人 Web3.0究竟是什么?
    四 软件架构风格、质量属性、Web架构设计
    小米以“不能胜任工作”为由辞退员工,两次上诉均败诉
    基于spingboot的websocket订阅、广播、多人聊天室示例
  • 原文地址:https://blog.csdn.net/weixin_43940314/article/details/127791571