zoukankan      html  css  js  c++  java
  • 读取3ds文件

    3ds文件是3D Max的一种二进制存储格式,它始终没被官方公开,但是也基本被大家hack出来了大半。其“格式”总的来说非常简单,这里介绍一个概念:chunk。3ds文件里的数据都是按chunk一块一块隔离的。每个chunk都有两个标记:2个字节大小的chunkId,用来标识这个chunk存的是什么数据。接着是一个4个字节大小的chunkLen,它根据chunkId不同,可能表示该chunk的大小,也可能表示下一个chunk的位置偏移。

    -----------------------------

    chunk Id       2 Byte

    chunk Len   4 Byte

    -----------------------------

    想要读取3ds文件,chunk Id是比较重要的部分,下面是hack出来的常用Id:

    -------------------------------------------------------------------------------------------------------------------------------------

    0x4D4D // Main Chunk
    ├─ 0x3D3D // 3D Editor Chunk
    │  ├─ 0x4000 // Object Block
    │  │  ├─ 0x4100 // Triangular Mesh
    │  │  │  ├─ 0x4110 // Vertices List
    │  │  │  ├─ 0x4120 // Faces Description
    │  │  │  │  └─ 0x4130 // Faces Material
    │  │  │  ├─ 0x4140 // Mapping Coordinates List
    │  │  │  │  └─ 0x4150 // Smoothing Group List
    │  │  │  └─ 0x4160 // Local Coordinates System
    │  │  ├─ 0x4600 // Light
    │  │  │  └─ 0x4610 // Spotlight
    │  │  └─ 0x4700 // Camera
    │  └─ 0xAFFF // Material Block
    │     ├─ 0xA000 // Material Name
    │     ├─ 0xA010 // Ambient Color
    │     ├─ 0xA020 // Diffuse Color
    │     ├─ 0xA030 // Specular Color
    │     ├─ 0xA200 // Texture Map 1
    │     ├─ 0xA230 // Bump Map
    │     └─ 0xA220 // Reflection Map
    │        │  /* Sub Chunks For Each Map */
    │        ├─ 0xA300 // Mapping Filename
    │        └─ 0xA351 // Mapping Parameters
    └─ 0xB000 // Keyframer Chunk
       ├─ 0xB002 // Mesh Information Block
       ├─ 0xB007 // Spot Light Information Block
       └─ 0xB008 // Frames (Start and End)
          ├─ 0xB010 // Object Name
          ├─ 0xB013 // Object Pivot Point
          ├─ 0xB020 // Position Track
          ├─ 0xB021 // Rotation Track
          ├─ 0xB022 // Scale Track
          └─ 0xB030 // Hierarchy Position
    ------------------------------------------------------------------------------------------------------------
    一般来说,一个chunk可能还包含子chunk,比如0x4100表示Mesh的chunk里就包含了0x4110,0x4120等chunk,同时,0x4100这个chunk的长度标识,是把这些子chunk的长度也计算在内的。一般来说,我们读取3ds文件,只要解析主要chunk,遇到不识别的chunk,跳过即可。因为3ds里的数据,大多数并不是程序员需要的。我们只要顶点和uv这些就够了。 
    下面是读取3ds文件的源代码:
    IModel.h
    View Code
     1 #ifndef IModel_h__
    2 #define IModel_h__
    3 /********************************************************************
    4 created: 2012/03/20
    5 created: 20:3:2012 20:08
    6 author: Baesky
    7
    8 purpose: provide an interface for loading model from various format.
    9 *********************************************************************/
    10
    11 class IModelLoader
    12 {
    13 public:
    14 virtual bool Load(const char* fileName) = 0; //load model file
    15 virtual unsigned short* GetIB() = 0; //got index buffer
    16 virtual float* GetVB() = 0; //got vertex buffer
    17 virtual short GetVertexNum() = 0; //got vertex num
    18 virtual unsigned short GetPolygonNum() = 0;
    19 };
    20
    21 #endif // IModel_h__
    Model3ds.h
    View Code
     1 #pragma once
    2 #include "imodel.h"
    3
    4 #define MAINCHUNK_3DS 0x4D4D
    5 #define MASHDATA_3DS 0x3D3D
    6 #define OBJNAME_3DS 0x4000
    7 #define MESH_DATA_3DS 0x4100
    8 #define VERTEX_DATA_3DS 0x4110
    9 #define INDEX_DATA_3DS 0x4120
    10 #define TEXMAP_DATA_3DS 0x4140
    11
    12 struct SVertex3DS
    13 {
    14 union
    15 {
    16 float v[3];
    17 struct
    18 {
    19 float X;
    20 float Y;
    21 float Z;
    22 };
    23 };
    24 };
    25
    26 struct SIndex3DS
    27 {
    28 union
    29 {
    30 unsigned short i[3];
    31 struct
    32 {
    33 unsigned short p1;
    34 unsigned short p2;
    35 unsigned short p3;
    36 };
    37 };
    38 };
    39
    40 class CModel3ds :
    41 public IModelLoader
    42 {
    43 public:
    44 CModel3ds(void);
    45 virtual ~CModel3ds(void);
    46
    47 //interface
    48 bool Load(const char* fileName);
    49 unsigned short* GetIB();
    50 float* GetVB();
    51 inline short GetVertexNum(){return m_VertexNum;}
    52 inline unsigned short GetPolygonNum(){return m_PolygonNum;}
    53 private:
    54 SIndex3DS* m_pIBbuff;
    55 SVertex3DS* m_pVBbuff;
    56 unsigned short m_VertexNum;
    57 unsigned short m_PolygonNum;
    58 };
    Model3ds.cpp
    View Code
     1 #include "Model3ds.h"
    2 #include <iosfwd>
    3 #include <fstream>
    4 using namespace std;
    5
    6 CModel3ds::CModel3ds(void):m_pIBbuff(0),m_pVBbuff(0),m_VertexNum(0)
    7 {
    8
    9 }
    10
    11
    12 CModel3ds::~CModel3ds(void)
    13 {
    14 if(m_pIBbuff)
    15 delete m_pIBbuff;
    16 if(m_pVBbuff)
    17 delete m_pVBbuff;
    18 }
    19
    20 bool CModel3ds::Load(const char* fileName )
    21 {
    22 ifstream f;
    23 f.open(fileName, ios::in|ios::binary);
    24
    25
    26 short chunk_id = 0;
    27 unsigned int chunk_len = 0;
    28 while(!f.eof())
    29 {
    30 f.read((char*)&chunk_id, 2);
    31 f.read((char*)&chunk_len,4);
    32 switch(chunk_id)
    33 {
    34 case MAINCHUNK_3DS://find out main chunk
    35 break;
    36 case MASHDATA_3DS: //find out mesh obj
    37 break;
    38 case OBJNAME_3DS:
    39 {
    40 int i=0;
    41 char c;
    42 do
    43 {
    44 f.read(&c,1);
    45 i++;
    46 }while(c != '\0' && i<20);
    47 }
    48
    49 break;
    50 case MESH_DATA_3DS:
    51 break;
    52 case VERTEX_DATA_3DS: //find out the vertex data
    53 f.read((char*)&m_VertexNum,2);
    54 m_pVBbuff = new SVertex3DS[m_VertexNum];
    55 for(int i = 0; i<m_VertexNum; ++i)
    56 {
    57 f.read((char*)&(m_pVBbuff[i].X),sizeof(float));
    58 f.read((char*)&(m_pVBbuff[i].Y),sizeof(float));
    59 f.read((char*)&(m_pVBbuff[i].Z),sizeof(float));
    60 }
    61 break;
    62 case INDEX_DATA_3DS:
    63 f.read((char*)&m_PolygonNum, 2);
    64 if(m_PolygonNum <= 0) return false;
    65 m_pIBbuff = new SIndex3DS[m_PolygonNum];
    66 for(int i = 0; i<m_PolygonNum; ++i)
    67 {
    68 f.read((char*)&m_pIBbuff[i].p1, 2);
    69 f.read((char*)&m_pIBbuff[i].p2, 2);
    70 f.read((char*)&m_pIBbuff[i].p3, 2);
    71 f.seekg(2, ios_base::cur);
    72 }
    73 break;
    74 case TEXMAP_DATA_3DS:
    75 break;
    76 default:
    77 f.seekg(chunk_len - 6, ios_base::cur);
    78 }
    79 }
    80 f.close();
    81 return true;
    82 }
    83
    84 unsigned short* CModel3ds::GetIB()
    85 {
    86 return (unsigned short*)m_pIBbuff;
    87 }
    88
    89 float* CModel3ds::GetVB()
    90 {
    91 return (float*)m_pVBbuff;
    92 }
    需要注意的是,3ds文件没normal chunk,所以法向量需要我们自己来计算。

    下面来读取下Cube.3ds(可从RenderMonkey附带例子中找到该文件)试试:



  • 相关阅读:
    移动端html的overflow:hidden属性失效问题
    js获取url传递参数,js获取url?号后面的参数
    zoom和transform:scale的区别
    css媒体查询来书写二倍图三倍图设置
    ajax和promise的结合使用
    react-router 嵌套路由 内层route找不到
    antd中按需加载使用react-app-rewired报错
    ts+antd报错error TS2605: JSX element type Xxx is not a constructor function for JSX elements
    在taro中跳转页面的时候执行两遍componentDidMount周期的原因和解决方法
    HDU 4602 Partition (矩阵乘法)
  • 原文地址:https://www.cnblogs.com/Baesky/p/Load_3ds_basic.html
Copyright © 2011-2022 走看看