C#创建obj三维模型文件

介绍

使用开源库创建obj三维模型文件。
开源库地址:https://github.com/JeremyAnsel/JeremyAnsel.Media.WavefrontObj

相关API地址:https://jeremyansel.github.io/JeremyAnsel.Media.WavefrontObj/api/JeremyAnsel.Media.WavefrontObj.ObjFile.html

obj格式解读:https://blog.csdn.net/shebao3333/article/details/132094257

示例

效果图(灰色为外,红色为内):
在这里插入图片描述

测试代码:

            //面片1
            var face1Pts = new float[][]
            {
                new float[]{0,0,0},
                new float[]{0,1,0},
                new float[]{1,1,0},
                new float[]{1,0,0},
            };
            //面片2
            var face2Pts = new float[][]
            {
                new float[]{0,0,0},
                new float[]{1,0,0},
                new float[]{1,0,0.5f},
                new float[]{0,0,0.5f},
            };

            //面片3
            var face3Pts = new float[][]
            {
                new float[]{0,1,0},
                new float[]{0,1,0.5f},
                new float[]{1,1,0.5f},
                new float[]{1,1,0},
            };

            var obj = new ObjFile();

            //用组表示对象
            //第一个组有两个面
            var group1 = new ObjGroup("group1");
            obj.Groups.Add(group1);
            //添加点
            foreach (var pt in face1Pts)
            {
                obj.Vertices.Add(new ObjVertex(pt[0], pt[1], pt[2]));
            }
            //添加面
            var face = new ObjFace();//根据右手定则确定面片的正面(外面)
            face.Vertices.Add(new ObjTriplet(1, 0, 0));
            face.Vertices.Add(new ObjTriplet(2, 0, 0));
            face.Vertices.Add(new ObjTriplet(3, 0, 0));
            face.Vertices.Add(new ObjTriplet(4, 0, 0));
            face.ObjectName = "group1-face1";
            face.MapName = "group1-face1";
            face.MaterialName = "Wall";
            //面片添加到组里,也需要添加到obj的Faces集合中
            group1.Faces.Add(face);
            obj.Faces.Add(face);

            //第一个组的第二个面
            foreach (var pt in face2Pts)
            {
                obj.Vertices.Add(new ObjVertex(pt[0], pt[1], pt[2]));
            }
            var face2 = new ObjFace();
            face2.Vertices.Add(new ObjTriplet(5, 0, 0));
            face2.Vertices.Add(new ObjTriplet(6, 0, 0));
            face2.Vertices.Add(new ObjTriplet(7, 0, 0));
            face2.Vertices.Add(new ObjTriplet(8, 0, 0));
            face2.ObjectName = "group1-face2";
            face2.MapName = "group1-face2";
            face2.MaterialName = "Column";
            group1.Faces.Add(face2);
            obj.Faces.Add(face2);


            //创建第二个对象,第二个对象有一个面
            var group2 = new ObjGroup("group2");
            obj.Groups.Add(group2);
            foreach (var pt in face3Pts)
            {
                obj.Vertices.Add(new ObjVertex(pt[0], pt[1], pt[2]));
            }
            var face3 = new ObjFace();
            face3.Vertices.Add(new ObjTriplet(9, 0, 0));
            face3.Vertices.Add(new ObjTriplet(10, 0, 0));
            face3.Vertices.Add(new ObjTriplet(11, 0, 0));
            face3.Vertices.Add(new ObjTriplet(12, 0, 0));
            face3.ObjectName = "group2-face1";
            face3.MapName = "group2-face1";
            face3.MaterialName = "Window";
            group2.Faces.Add(face3);
            obj.Faces.Add(face3);
           
			//其他参数
            //face.LevelOfDetail = 2;
            //face.MapName = "c";
            //face.MaterialName = "d";
            //face.SmoothingGroupNumber = 10;
            //face.IsBevelInterpolationEnabled = true;
            //face.IsColorInterpolationEnabled = true;
            //face.IsDissolveInterpolationEnabled = true;
            obj.WriteTo("./Tmp.obj");

生成的obj文件内容:

v 0.000000 0.000000 0.000000
v 0.000000 1.000000 0.000000
v 1.000000 1.000000 0.000000
v 1.000000 0.000000 0.000000
v 0.000000 0.000000 0.000000
v 1.000000 0.000000 0.000000
v 1.000000 0.000000 0.500000
v 0.000000 0.000000 0.500000
v 0.000000 1.000000 0.000000
v 0.000000 1.000000 0.500000
v 1.000000 1.000000 0.500000
v 1.000000 1.000000 0.000000
g group1
o group1-face1
usemap group1-face1
usemtl Wall
f 1 2 3 4
o group1-face2
usemap group1-face2
usemtl Column
f 5 6 7 8
g group2
o group2-face1
usemap group2-face1
usemtl Window
f 9 10 11 12

补充:

  • 根据右手定则确定面片的正面(外面)
  • ObjectName、MapName、MaterialName的赋值可以注释跳过。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker desktop实战部署oracle篇

1、前言 oracle数据库官方已提供现成的镜像,可以直接拿来部署了。 由于项目中需要使用oracle数据库的分表功能,之前安装的是standard版本,无奈只能重新安装。网上查了一番,使用的方法都比较传统老旧:下载安装包手动安…

多线程局部存储技术

问题 多线程上下文中,每个线程需要使用一个专属的全局变量,该如何实现? 代码示例 一种可能的解决方案 test1.c #define _GNU_SOURCE /* To get pthread_getattr_np() declaration */ #define _XOPEN_SOURCE > 500 || _POSIX_C_SOURC…

谷歌上架,为什么会触发填表单,可以避免吗?怎么填表单可以提高通过率?

在谷歌上架过程中,相信大部分开发者都有收到过谷歌发来表单填写的邮件通知,要求开发者们在14天内根据表单要求回复关于应用部分情况。邮件如图: 根据触发填表单的开发者分享的经验来看,填完表之后出现的情况不尽相同,且…

【华为】路由综合实验(OSPF+BGP基础)

【华为】路由综合实验 实验需求拓扑配置AR1AR2AR3AR4AR5PC1PC2 查看通信OSPF邻居OSPF路由表 BGPBGP邻居BGP 路由表 配置文档 实验需求 ① 自行规划IP地址 ② 在区域1里面 启用OSPF ③ 在区域1和区域2 启用BGP,使AR4和AR3成为eBGP,AR4和AR5成为iBGP对等体…

【JVM】class文件格式,JVM加载class文件流程,JVM运行时内存区域,对象分配内存流程

这篇文章本来只是想讲一下class文件格式,讲着讲着越讲越多。JVM这一块吧,知识比较散比较多,如果深研究下去如死扣《深入理解Java虚拟机》,这本书很深很细,全记住是不可能的,其实也没必要。趁这个机会直接把…

RK3568平台(基础篇)linux错误码

一.概述 linux应用程序开发过程中,经常会遇到一些错误信息的返回,存在的可能性有,参数有误、非法访问、系统资源限制、设备/文件不存在、访问权限限制等等。对于这类错误,可以通过perror函数输出具体描述,或者通过str…

nacos-server-1.2.1启动

1、双击startup.cmd 2、启动日志 3、访问http://192.168.26.210:8848/nacos/index.html 4、登录 用户名:nacos 密码:nacos

掌握JavaScript面向对象编程核心密码:深入解析JavaScript面向对象机制对象概念、原型模式与继承策略全面指南,高效创建高质量、可维护代码

ECMAScript(简称ES,是JavaScript的标准规范)支持面向对象编程,通过构造函数模拟类,原型链实现继承,以及ES6引入的class语法糖简化面向对象开发。对象可通过构造函数创建,使用原型链共享方法和属…

【云原生】Docker 的网络通信

Docker 的网络通信 1.Docker 容器网络通信的基本原理1.1 查看 Docker 容器网络1.2 宿主机与 Docker 容器建立网络通信的过程 2.使用命令查看 Docker 的网络配置信息3.Docker 的 4 种网络通信模式3.1 bridge 模式3.2 host 模式3.3 container 模式3.4 none 模式 4.容器间的通信4.…

小白如何搭建git

1、安装git 在Windows上安装git: 关注微信公众号“机器人学”回复 “搭建git” 利用百度云网盘下载安装包,建议下载如下版本的否则可能会出现错误。 安装完成后,在开始菜单里Git->git bash,弹出命令窗说明git安装成功。 鼠标右…

【Python项目】基于DJANGO的【基于语音识别的智能垃圾分类系统】

技术简介:使用Python技术、DJANGO框架、MYSQL数据库等实现。 系统简介:用户们可以在系统上面录入自己的个人信息,录入后还可以对信息进行修改,网站可以对用户上传的音频文件进行识别,然后进行垃圾分类。 背景&#xf…

【学习AI-相关路程-工具使用-自我学习-NVIDIA-cuda-工具安装 (1)】

【学习AI-相关路程-工具使用-自我学习-NVIDIA-cuda (1)】 1、前言2、环境配置1、对于jetson orin nx 的cuda环境2、对于Ubuntu 20.04下cuda环境 3、自我总结-安装流程1、在ubuntu下,如果想使用cuda平台,应该注意什么 和 都安装什么…

BGE向量模型架构和训练细节

模型论文:https://arxiv.org/pdf/2309.07597 模型数据:https://data.baai.ac.cn/details/BAAI-MTP 训练数据 由无标签数据和有标签数据组成。 无标签数据使用了悟道等数据集,有标签数据使用了dureader等数据集。 都是文本对,对于…

rust使用Atomic创建全局变量和使用

Mutex用起来简单,但是无法并发读,RwLock可以并发读,但是使用场景较为受限且性能不够,那么有没有一种全能性选手呢? 欢迎我们的Atomic闪亮登场。 从 Rust1.34 版本后,就正式支持原子类型。原子指的是一系列…

【redis】Redis数据类型(五)ZSet类型

目录 类型介绍特点补充 使用场景 Zset类型数据结构ziplist:压缩列表(参考之前的文章)skiplist:跳表解析 面试题:MySQL索引为什么用B树而不用跳表区别总结 常用命令ZADD示例 ZREM示例 ZCARD示例 ZCOUNT示例 ZSCORE示例 …

在线OJ——链表经典例题详解

引言:本篇博客详细讲解了关于链表的三个经典例题,分别是:环形链表(简单),环形链表Ⅱ(中等),随机链表的复制(中等)。当你能毫无压力地听懂和成功地…

单调栈|496.下一个更大元素I

力扣题目链接 class Solution { public:vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {stack<int> st;vector<int> result(nums1.size(), -1);if (nums1.size() 0) return result;unordered_map<int, …

去哪儿网机票服务请求体bella值逆向

作者声明&#xff1a;文章仅供学习交流与参考&#xff01;严禁用于任何商业与非法用途&#xff01;否则由此产生的一切后果均与作者无关&#xff01;如有侵权&#xff0c;请联系作者本人进行删除&#xff01; 一、加密定位 直接全局搜索bella&#xff0c;在可疑的地方下断&…

pandas学习笔记12

缺失数据处理 其实在很多时候&#xff0c;人们往往不愿意过多透露自己的信息。假如您正在对用户的产品体验做调查&#xff0c;在这个过程中您会发现&#xff0c;一些用户很乐意分享自己使用产品的体验&#xff0c;但他是不愿意透露自己的姓名和联系方式&#xff1b; 还有一些用…

使用C#和NMODBUS快速搭建MODBUS从站模拟器

MODBUS是使用广泛的协议&#xff0c;通讯测试时进行有使用。Modbus通讯分为主站和从站&#xff0c;使用RS485通讯时同一个网络内只能有一个主站&#xff0c;多个从站。使用TCP通讯时没有这方面的限制&#xff0c;可以同时支持多个主站的通讯读写。 开发测试时有各种复杂的需求&…