Python+OpenGL绘制3D模型(七)制作3dsmax导出插件

news2024/12/28 2:43:32

系列文章

一、逆向工程
Sketchup 逆向工程(一)破解.skp文件数据结构
Sketchup 逆向工程(二)分析三维模型数据结构
Sketchup 逆向工程(三)软件逆向工程从何处入手
Sketchup 逆向工程(四)破解的乐趣 钩子 外挂 代码注入

二、OpenGL渲染模型
Python+OpenGL绘制3D模型(一)Python 和 PyQt环境搭建
Python+OpenGL绘制3D模型(二)程序框架PyQt5
Python+OpenGL绘制3D模型(三)程序框架PyQt6
Python+OpenGL绘制3D模型(四)绘制线段
Python+OpenGL绘制3D模型(五)绘制三角型
Python+OpenGL绘制3D模型(六)材质文件载入和贴图映射
Python+OpenGL绘制3D模型(七)制作3dsmax导出插件
Python+OpenGL绘制3D模型(八)绘制插件导出的插件
Python+OpenGL绘制3D模型(九)完善插件功能: 矩阵,材质,法线
Python+OpenGL 杂谈(一)

三、成果
疫情期间关在家里实在没事干,破解了Sketchup,成功做出可以读取并显示.skp文件的程序SuViewer

前言

Sketchup作为目前设计院最为流行的设计软件(非工程制图软件),深受设计师的喜爱,软件小巧,而功能强大,有不少为之开发的插件应运而生,不过呢,关于底层数据结构和工作原理相关的文章少之又少,本文意在填补一下这方面的空缺,通过逆向软件分析,展示软件内部奥秘。本文用到的工具:IDA Pro,Immunity Debugger,Visual Studio (逆向工程三件套)数据结构属于知识产权的核心机密:


在这里插入图片描述

文章目录

  • 系列文章
  • 前言
    • 一、介绍
    • 二、使用方法
    • 三、插件源代码
  • 系列文章预告

一、介绍

3dsmax支持python2.7,所以同样可以用python编写插件,不需要编译安装,一键执行,非常方便,
编写插件是个比较复杂的过程,涉及3dsmax中模型、材质、贴图、等数据的组织结构,以后专门用一个专题详细介绍,有兴趣的同学可以仔细读一下插件源代码
插件和程序需要交换文件数据格式,这里定义一个CModel,数据保存使用了python内置的pickle,也是一键保存,在程序里一键载入,不需要专门编写读写文件的代码

二、使用方法

1、下载源代码,保存到:c:/temp/maxplus_export_sel_model.py
2、打开3dsmax,菜单 》Scripting 》 MAXScript Listener
3、运行 python.ExecuteFile “C:/temp/maxplus_export_sel_model.py”

如果看到如下输出,说明已经导出成功

find INode: Teapot001, <0X0000000048D3CBB0>, class:Teapot
---ProcMesh()---
numVertics:530
numFaces:1024
#success

模型导出到 “c:/temp/CModel.pickle”

注意:保证c:/temp存在,否则导出失败

三、插件源代码

maxplus_export_sel_model.py

import MaxPlus
import pickle
from CModel import CModel, CMesh, CTriangle, CVector3

################################
#                   FILE DESCRIPTION
#  文件描述:CModelExport
#  对应文章:Python+OpenGL绘制3D模型(七) 制作3dsmax导出插件
#  作者:李航 Lihang
#  使用方法:
#   1、选择要导出的模型
#   2、在命令行窗口中输入
#          python.ExecuteFile "C:/_proj/SuViewer/articles/step3/maxplus_export_sel_model.py"
#   3、把命令行拖入工具栏可以生成快捷方式,方便下次使用
#   4、测试可使用的版本:3dsmax2016
#   ELSE..
################################



# 注意: 保证c:/temp目录存在,否则无法导出
EXPORT_PATH_FILE = "c:/temp/CModel.pickle"

############
# CModelExport
############  
class CModelExport:
    def __init__(self):
        self.list_mats = []
        
    ############
    # export
    #   插件主入口
    ############  
    def export(self):
        model = CModel()

        for n, obj, triObj in self.EnumSeletciontGeometry():
            print ("find %s, class:%s"%(n, obj.GetClassName()) )
            mesh = triObj.GetMesh()

            out_mesh = self.ProcMesh(n, mesh)
            model.list_mesh.append(out_mesh)
        
        with open(EXPORT_PATH_FILE,  "wb") as hf:
            pickle.dump(model,  hf,  2)

    ############
    # EnumSeletciontGeometry
    #   1、遍历选择的物体
    #   2、生成列表sel_list并返回
    ############  
    def EnumSeletciontGeometry(self):
        sel_list = []
        for n in MaxPlus.SelectionManager.Nodes:        
            # object
            obj = n.EvalWorldState().Getobj()
            if obj.CanConvertToType(MaxPlus.ClassIds.TriMeshGeometry):
                triObj = obj.ConvertToType(MaxPlus.ClassIds.TriMeshGeometry)
                item = (n, obj, MaxPlus.TriObject._CastFrom(triObj))
                sel_list.append(item)
                #print ("find %s, class:%s"%(n, obj.GetClassName()) )
            else:
                print("can't conv triMesh, Type is:%s" % obj.GetClassName())
         
        return sel_list

    ############
    # ProcMesh
    #   1、处理max中的模型
    #   2、转成需要的CModel数据
    ############
    def ProcMesh(self, node, mesh):
        print("---ProcMesh()---")

        #=====================
        # Color
        #=====================
        new_mesh = CMesh()
        color1 = node.GetWireColor()
        new_mesh.color = (color1.GetR(), color1.GetG(), color1.GetB())
        
        #=====================
        # Vertices
        #=====================
        num_verts = mesh.GetNumVertices()
        print ("numVertics:%d"%num_verts)
        for i in range(num_verts):
            point = mesh.GetVertex(i)
            nv = CVector3(point.X, point.Y, point.Z)
            new_mesh.list_vertices.append(nv)

        #=====================
        # Triangles
        #=====================
        num_faces = mesh.GetNumFaces()
        print ("numFaces:%d"%num_faces)
        for i in range(num_faces):
            tri = mesh.GetFace(i)
            vi1 = tri.GetVert(0)
            vi2= tri.GetVert(1)
            vi3 = tri.GetVert(2)
            ev1 = True if tri.GetEdgeVis(0) else False
            ev2 = True if tri.GetEdgeVis(1) else False
            ev3 = True if tri.GetEdgeVis(2) else False
            nt = CTriangle()
            nt.a = (vi1, 0, 0)
            nt.b = (vi2, 0, 0)
            nt.c = (vi3, 0, 0)
            norm = mesh.FaceNormal(i)
            nt.matId = tri.GetMatID()
            nt.faceNormal = CVector3(norm.X, norm.Y, norm.Z)
            nt.smGroup = tri.GetSmGroup()
            nt.edgevis = (ev1, ev2, ev3)
            new_mesh.list_tris.append(nt)
            
        return new_mesh

############
# Main
#   1、创建插件导出对象CModelExport
#   2、执行export
############
modelExport = CModelExport()
modelExport.export()

CModel.py

class CModel:
    def __init__(self):
        self.list_mesh = []
        
class CMesh:
    def __init__(self):
        self.name = ""
        self.color = (0, 0, 0)
        self.list_vertices = []
        self.list_tris = []

class CTriangle:
    def __init__(self):
        self.a=(0, 0, 0)
        self.b=(0, 0, 0)
        self.c=(0, 0, 0)
        self.faceNormal = CVector3(0, 0, 0)
        self.matId = 0
        self.smGroup = 0
        self.edgevis=(True, True, True)

class CVector3:
    def __init__(self, x, y, z):
        self.x=x
        self.y=y
        self.z=z

系列文章预告

目标是一个完善的Viewer,能够显示Sketchup的.skp文件中的3D模型
在这里插入图片描述

Corona渲染器照片级渲染效果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1353009.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最新Tomcat下载安装详细教程

Tomcat下载安装教程 Tomcat简介Tomcat下载tomcat安装验证安装是否成功 Tomcat简介 Tomcat是什么&#xff1f; Tomcat是web容器。你在做web项目时&#xff0c;多数需要http协议&#xff0c;也就是基于请求和响应&#xff0c;比如你在百度输入一行内容搜索&#xff0c;那么百度服…

一文讲清数据资产入表实操

《中共中央 国务院关于构建数据基础制度更好发挥数据要素作用的意见》已发布一年&#xff0c;数据资产化和入表已成为2023年的热门话题&#xff0c;随着2023年底国家数据局吹风《"数据要素x"三年行动计划&#xff08;2024-2026年&#xff09;》即将发布&#xff0c;这…

Java_IO流(字节流)

一、IO流&#xff08;字节流&#xff09; 1.1 IO流概述 在前面已经学习过File类。知道File只能操作文件&#xff0c;但是不能操作文件中的内容。我们也学习了字符集&#xff0c;不同的字符集存字符数据的原理是不一样的。有了前面两个知识的基础&#xff0c;接下来我们再学习…

Git(3):Git环境常用命令

1 获取本地仓库 要使用Git对我们的代码进行版本控制&#xff0c;首先需要获得本地仓库 &#xff08;1&#xff09;在电脑的任意位置创建一个空目录&#xff08;例如test&#xff09;作为我们的本地Git仓库 &#xff08;2&#xff09;进入这个目录中&#xff0c;点击右键打开…

NSSCTF sql

开启环境: ?wllm1 回显正常,试试?wllm1 出现报错;加上%23正常 ?wllm-1or 11%23出现过滤 测试,空格用**替代, 等号用like替代 测试长度 ?wlmm1order/**/by/**/3%23正常 ?wlmm1order/**/by/**/4%23报错 长度为3,测试回显位置: ?wlmm-1union/**/select/**/1,2,3%23 …

c++ / day06

1. 利用模板类完成顺序表(两天时间&#xff0c;今天至少写出大致框架) 代码 //implement template in sqlist #include <iostream> #include <cstring>#define MAXSIZE 100using namespace std;template <typename T> class Sqlist {unsigned int len 0;T…

【普中开发板】基于51单片机音乐盒LCD1602显示( proteus仿真+程序+设计报告+讲解视频)

【普中开发板】基于51单片机音乐盒LCD1602显示( proteus仿真程序设计报告讲解视频&#xff09; 仿真图proteus7.8及以上 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;P08 1. 主要功能&#xff1a; 基于51单片机AT89C51/52&#…

环境准备-VMware安装

照顾到很多人不是很会环境搭建,我这里会将搭建的步骤讲的细致点 第一步,VMware下载。目的是通过VMware搭建Linux服务器,因为大家大部分还是Windows的电脑,我们先下载虚拟机搭建一个Linux系统的服务器 下载完成之后,点击安装,如下: 点击“下一步” 勾选“我接受许可协议…

app store里面的构建版本在线上传

开发苹果ios应用&#xff0c;无论是用原生开发、用hbuilderx开发还是用其他h5框架开发的app&#xff0c;都需要将打包好的ipa文件上传到app store。 在上架app store的过程中&#xff0c;我们会遇到下图的这样一个问题&#xff1a; 就是它要求我们上传一个构建版本&#xff0c…

IDEA断点调试

IDEA断点调试 断点调试是一种在程序执行过程中暂停执行并逐步检查代码状态的方法。它允许开发者在程序运行到特定位置时暂停执行&#xff0c;查看变量的值、执行过程和调用栈等信息&#xff0c;从而更好地理解代码的运行情况和解决问题。可以帮助我们查看java底层源代码的执行…

分布微服软件体系快速云端架构

1 概述 分布微服软件体系云端架构平台&#xff0c;以主流的NACOS服务器作为注册配置中心&#xff0c;采用主流的Gradle框架&#xff0c;内嵌Tomcat10以上版本&#xff0c;用于快速构造各类基于JDK17以上的信息应用系统的分布式微服务软件体系架构&#xff0c;可以适用关系型SQ…

图像识别原理

图像识别是计算机视觉领域中的一个重要任务&#xff0c;其目标是使计算机系统能够理解和解释图像中的信息。以下是图像识别的基本原理&#xff1a; 1. 数据采集&#xff1a;首先&#xff0c;需要获取图像数据。这可以通过摄像头、传感器、扫描仪等设备来实现。图像可以是静态的…

在Linux中以后台静默运行Java应用程序

在Linux系统上运行Java应用程序时&#xff0c;有时我们希望将其设置为后台运行&#xff0c;而关闭终端窗口时不会影响进程的执行。在本文中&#xff0c;我们将介绍几种实现这一目标的方法。 1. 使用nohup命令 nohup是一个用于在后台运行进程的命令&#xff0c;而且关闭终端窗…

8868体育助力赫塔菲 格林伍德渐入佳境

西甲赫塔菲俱乐部是8868体育合作球队之一。近日&#xff0c;赫塔费在西甲联赛3-3战平马竞&#xff0c;赛后赫塔费主帅博达拉斯称赞了格林伍德。格林伍德在本场比赛中虽然没有收获进球或助攻&#xff0c;但他表现出色&#xff0c;赛后获得8分评价。 在比赛中&#xff0c;格林伍德…

依赖注入实现原理

依赖注入实现原理 一、Autowire 流程图&#xff1a; Autowire的后置处理器类是AutowiredAnnotationBeanPostProcessor&#xff0c;在启动时会执行这里面的方法 步骤一&#xff1a;寻找注入点 在创建一个Bean的过程中&#xff0c;Spring会利用AutowiredAnnotationBeanPostPro…

单片机原理及应用:独立式键盘控制LED与多功能按键识别

今天来介绍另一个外设——按键与LED的配合工作&#xff0c;与开关不同&#xff0c;按键需要注意消除抖动带来的影响&#xff0c;代码逻辑也会更复杂一写&#xff0c;下面先为大家介绍独立式键盘的相关知识。 单片机的独立式键盘指的是一种不依赖于计算机或其他外部设备的键盘输…

数据结构:堆的三部曲(二)top K问题

堆的应用&#xff08;一&#xff09;top K问题 一.top k问题的应用本质解析二.top K问题使用案例——从100亿整型的文件中找出前5个最大值1.建堆1.1过程分析1.2过程图模拟1.3向上调整算法代码1.4建堆代码 2.处理文件中剩余剩余元素2.1过程分析2.2过程图示例2.3向下调整算法代码…

百度百科词条创建多久可以通过?

一个优质的百度百科词条&#xff0c;能提升个人或企业的品牌形象。因此&#xff0c;越来越多的人希望创建自己的百度百科词条&#xff0c;那么&#xff0c;创建一个百度百科词条到底需要多久才能通过审核呢&#xff1f;接下来伯乐网络传媒就来给大家分享一下。 一、百度百科词条…

AI计算,为什么要用GPU?

今天这篇文章&#xff0c;我们继续来聊聊芯片。 在之前的文章里&#xff0c;小枣君说过&#xff0c;行业里通常会把半导体芯片分为数字芯片和模拟芯片。其中&#xff0c;数字芯片的市场规模占比较大&#xff0c;达到70%左右。 数字芯片&#xff0c;还可以进一步细分&#xff0…