• 【splishsplash】关于如何在GUI和json上接收/显示用户参数、MVC模式和GenParam


    原理:splishsplash中的MVC模式与GenericParameter

    splishsplash中采用了MVC设计模式。该设计模式最大的特点就是将用户界面与后端数据计算分开,也就是俗称的“前端”和“后端”分开。实际上,只要是涉及到GUI或者图形学的程序,都几乎或多或少要有MVC设计模式。

    MVC中的三个字母代表的是Model View Controller
    Model负责数据的计算,View负责用户IO(也就是显示界面和接收用户输入),Controller负责两者的通讯。通过Controller,我们彻底截断了后端和前端。实现了系统的解耦。

    splishsplash中的Model不必多说,就是计算的主体,可以认为是FluidModel等实例的计算数据。

    View代表的则是GUI,目前默认采用的是IMGUI。

    而Controller,则是GenericParamerter 这个第三方库。这个库是splishsplash项目组自己开发的另一个项目。在splishsplash中作为第三方库来使用。它的用处就是管理参数。只要你想要将Model中的参数与用户界面的参数相互通讯,就可以将GenericParameter作为你当前类的父类。GenericParameter就会负责和IMGUI相互沟通。那么,对我们代码开发者来说,只需要会用GenericParameter的API就可以实现与GUI之间的通讯了。

    你可能会问为何要中间加一个中介,而不是直接去联通IMGUI呢?原因是1)GUI库有很多种选择,IMGUI,TweakBar(曾经的默认GUI)等等。假如我变更了GUI,那岂不是算法中的所有代码都要变?所以为了统一API,增加一个中介是有好处的。2)假如没有中介的Controller,两者沟通的代码,要么写在GUI的源文件里,要么写在算法的源文件里,两者都会造成很令人头疼的耦合问题。3)简化了使用。IMGUI有很多功能,但我们这里只需要管理参数就够了,多余的对我们来说反而是负担。

    因此,下面我们只关注这个中介Controller(也就是GenericParameters)的API。

    使用方式讲解

    我们看一个例子,代码来自SurfaceTensionBase.cpp

    SURFACE_TENSION = createNumericParameter("surfaceTension", "Surface tension coefficient", &m_surfaceTension); 
    setGroup(SURFACE_TENSION, "Surface tension");
    setDescription(SURFACE_TENSION, "Coefficient for the surface tension computation"); 
    RealParameter* rparam = static_cast<RealParameter*>(getParameter(SURFACE_TENSION));
    rparam->setMinValue(0.0);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    该代码的作用是:绑定参数m_surfaceTension到GUI上去,GUI中显示的参数叫做surfaceTension。

    我们一行行分析:
    第一行

    SURFACE_TENSION = createNumericParameter("surfaceTension", "Surface tension coefficient", &m_surfaceTension); 
    
    • 1

    createNumericParameter这个函数就是创建一个数值型的参数。这个参数的名字叫做surfaceTension(这个名字同样适用于json文件)。描述为Surface tension coefficient,所绑定的参数为m_surfaceTension(注意传递的是指针)。至于返回的那个整数型变量,是GUI的组号。必然是一个static的(因为要求静态生存期)

    第二行

    setGroup(SURFACE_TENSION, "Surface tension"); 
    
    • 1

    为了方便管理,参数通常要分组。这在GUI上面的效果就是分页。每个组就是单独的一页来显示。

    第三行

    setDescription(SURFACE_TENSION, "Coefficient for the surface tension computation"); 
    
    • 1

    鼠标悬浮的时候显示的描述。

    第四行

    RealParameter* rparam = static_cast<RealParameter*>(getParameter(SURFACE_TENSION));
    
    • 1

    用来设定最大最小值的。这是为了防止用户错误输入。

    第五行

    rparam->setMinValue(0.0);
    
    • 1

    设定最小值

    我们来修改一下试验效果

    刚才讲完了原理和用法,那么我们就尝试改动一些东西,看看是不是理论符合实践。

    测试改名字和描述和初始值

    第一行改为

    SURFACE_TENSION = createNumericParameter("thisIsName", "This is Discription", &m_surfaceTension); 
    
    • 1

    编译运行
    在这里插入图片描述
    我们发现确实如此

    那么是否能通过json改变它的参数呢?目前默认是0.05
    我们在一个json中更改

    "Materials": [
    	{
    		"id": "Fluid",
    		"thisIsName": 1.11
    	}
    ],
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    运行
    在这里插入图片描述
    发现确实读入了参数

    测试分组

    第二行更改为

    setGroup(SURFACE_TENSION, "A new group");
    
    • 1

    编译运行

    当你选择任何SurfaceTension算法的时候就会出现新分组
    在这里插入图片描述
    在这里插入图片描述

    并且我们之前的那个参数也被挪到新分页内了。

    请注意:决定你的参数是否在新分页的,是你的参数所在的组(也就是组号SURFACE_TENSION所决定的)

    例如原有的Boundary surface tension coeff就没有分到新租“A new group”

    测试组描述

    与之前那个不同,这个是针对组内每个变量的描述

    setDescription(SURFACE_TENSION, "This is the group discription");
    
    • 1

    在这里插入图片描述

    测试最大最小值

    第五行更改为

    rparam->setMinValue(1.0);
    rparam->setMaxValue(5.0);
    
    • 1
    • 2

    假如我们键入0.9,会自动弹回1.0
    在这里插入图片描述
    最大值同理

  • 相关阅读:
    【数据结构】带头结点的单链表的头插法
    Java时间复杂度和空间复杂度(详解)
    kmp:831. KMP字符串
    U-Mail信创邮件系统解决方案
    关于Docker中容器之间互相访问问题
    k8s+kubeedge+sedna安装的全套流程
    Conmi的正确答案——Ubuntu修改国内源(阿里云 aliyun)
    VSFTPD2.3.4(笑脸漏洞)复现
    CMMI3认证和CMMI5认证有哪些不同
    一文读懂 Redis 缓存系统
  • 原文地址:https://blog.csdn.net/weixin_43940314/article/details/125549215