Python+OpenGL绘制3D模型(七)制作3dsmax导出插件
系列文章
一、逆向工程
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: # objectobj = 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 Falseev2 = True if tri.GetEdgeVis(1) else Falseev3 = True if tri.GetEdgeVis(2) else Falsent = 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 = 0self.smGroup = 0self.edgevis=(True, True, True)class CVector3:def __init__(self, x, y, z):self.x=xself.y=yself.z=z
系列文章预告
目标是一个完善的Viewer,能够显示Sketchup的.skp文件中的3D模型

Corona渲染器照片级渲染效果

相关文章:
Python+OpenGL绘制3D模型(七)制作3dsmax导出插件
系列文章 一、逆向工程 Sketchup 逆向工程(一)破解.skp文件数据结构 Sketchup 逆向工程(二)分析三维模型数据结构 Sketchup 逆向工程(三)软件逆向工程从何处入手 Sketchup 逆向工程(四…...
MediaPipeUnityPlugin Win10环境搭建(22年3月的记录,新版本已完全不同,这里只做记录)
https://github.com/homuler/MediaPipeUnityPlugin You cannot build libraries for Android with the following steps. 1、安装msys2配置系统环境变量Path添加 C:\msys64\usr\bin 执行 pacman -Su 执行 pacman -S git patch unzip 2、安装Python3.9.10 勾选系统环境变量 …...
Nginx - location块中的alias和try_files重定向
nginx.conf片段: location /logo/general/ {autoindex_localtime on;alias /opt/config/;try_files /logo/logo.png /www/html/logo.png 404;} 意为:访问/logo/general/地址时, 如:访问http://127.0.0.1/logo/general/logo.png…...
二刷Laravel 教程(用户模型)总结Ⅲ
一、数据库迁移 当我们运行迁移时,up 方法会被调用;(创建表) 当我们回滚迁移时,down 方法会被调用。(删除表) public function up() { //create 方法会接收两个参数:一个是数据…...
安装PyTorch及环境配置(应用于Python上的YOLO)
这个基本都是Bilibili网站里面叫“小手丫子”up的视频教程,此前自己需要装了好几次又卸载了好几次,现在根据视频教学整理出来自己所理解的文档。 注意事项 1.安装的pycharm版本和anaconda版本无要求。 2.运行pycharm尽量以管理员身份运行。 3.Cuda是独…...
【194】PostgreSQL 14.5 编写SQL从身份证号中查找性别,并且更新性别字段。
假设有一张用户表 t_user ,该表设计如下: id: character varying 主键 name: character varying 姓名 idcard: character varying 身份证号 gender: smallint 性别,女是0,男是1根据身份证号查找所有未填写…...
微服务管家:NestJS 如何使用服务发现 Consul 实现高效的微服务节点管理
前言 在微服务架构中,服务发现是一项基础且关键的功能,它允许服务实例在网络中被动态发现。Consul 是一种服务网格解决方案,提供了服务发现、运行状况检查,过去和现代应用程序的连接等功能。 本教程将向您展示如何在 NestJS 框架…...
Baumer工业相机堡盟工业相机如何联合NEOAPI SDK和OpenCV实现相机图像转换为Mat图像格式(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK实现相机掉线自动重连(C) Baumer工业相机Baumer工业相机的图像转换为OpenCV的Mat图像的技术背景在NEOAPI SDK里实现相机图像转换为Mat图像格式联合OpenCV实现相机图像转换为Mat图像格式测试演示图 工业相机…...
铁塔基站数字化管理监测解决方案
截至2023年10月,我国5G基站总数达321.5万个,占全国通信基站总数的28.1%。然而,随着5G基站数量的快速增长,基站的能耗问题也逐渐日益凸显,基站的用电给运营商带来了巨大的电费开支压力,降低5G基站的能耗成为…...
如何使用Python3 Boto3删除AWS CloudFormation的栈(Stacks)
文章目录 小结问题及解决有关Json文件的输入和输出使用Python3及正则表达式查找字符串包含某个子字符串使用Python3 Boto3删除AWS CloudFormation的栈(Stacks) 参考 小结 本文记录了使用Python3的Boto3包删除AWS CloudFormation的栈(Stacks&…...
差分约束算法
差分约束 差分约束系统包含 m m m个涉及 n n n个变量的差额限制条件,这些差额限制条件每个都是形式为 x i − x j ≤ b ∈ [ 1 , m ] x_i-x_j\leq b_{\in[1,m]} xi−xj≤b∈[1,m]的简单线性不等式。 通常我们要求解出一组可行解。 最短路差分约束 如果我们…...
彻底解决vue-video-player播放视频有黑边
需求 最近需要接入海康视频摄像头,然后把视频的画面接入到自己的网站系统中。以前对接过rtsp固定IP的显示视频,这次的不一样,没有了固定IP。海康的解决办法是,摄像头通过配置服务器到萤石云平台,然后购买企业版账号和…...
区域负责人常用的ChatGPT通用提示词模板
区域市场分析:如何分析区域市场的特点、竞争态势和客户需求? 区域销售策略制定:如何制定针对区域市场的销售策略,包括产品定位、价格策略、渠道策略等? 区域销售目标设定:如何设定明确的区域销售目标&…...
Java Spring boot 可變參數,以及弊端
function中 不固定的參數 public boolean sendEmail(String manFrom, String manTo,String manCc, String subject, String... msg); 必須是最後一個參數,傳值時可以多個。 sendEmail(“a.gmail”,"b.gmail","c.gmail","subject",…...
机器视觉系统选型-线阵工业相机选型
线阵相机特点: 1.线阵相机使用的线扫描传感器通常只有一行感光单元(少数彩色线阵使用三行感光单元的传感器) 2.线阵相机每次只采集一行图像; 3.线阵相机每次只输出一行图像; 4.与传统的面阵相机相比,面阵扫…...
单机开机无感全自动进入B\S架构系统
单机开机无感全自动进入B\S架构系统 标题:单机用jar包启动项目bat(批处理)不弹黑窗口,并设置开机自启,打开浏览器,访问系统。引言:在实际工作中,遇到单机部署的情况,如今…...
大一,如何成为一名fpga工程师?
1、数电(必须掌握的基础),然后进阶学模电(选学), 2、掌握HDL(HDLverilogVHDL)可以选择verilog或者VHDL,建议verilog就行。 3、掌握FPGA设计流程/原理(推…...
MyBatisPlus学习三:Service接口、代码生成器
学习教程 黑马程序员最新MybatisPlus全套视频教程,4小时快速精通mybatis-plus框架 Service接口 简介 在MyBatis-Plus框架中,Service接口的作用是为实体类提供一系列的通用CRUD(增删改查)操作方法。通常情况下,Servi…...
产品经理如何选择城市?
年底,全国性的人口大迁徙即将开始。选择城市,堪称年轻人的“二次投胎”,族望留原籍,家贫走他乡。 古人在选择城市时,主要的考量因素是家族势力,这一点放在当代,大致也成立,如果在老…...
再谈“敏捷”与“瀑布”在产品开发过程中的反思
作为一家专注于软件开发的公司《智创有术》,我们致力于为客户提供创新、高效和可靠的解决方案。通过多年的经验和专业知识,我们已经在行业内建立了良好的声誉,并赢得了客户的信任和支持。 支持各种源码,网站搭建,APP&a…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
