summaryrefslogtreecommitdiffhomepage
path: root/StarsEx/Solid.h
blob: 1b51a68a7efb698592efca035fa44e6ab5a75c2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
/*  Starshatter: The Open Source Project
    Copyright (c) 2021-2024, Starshatter: The Open Source Project Contributors
    Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
    Copyright (c) 1997-2006, Destroyer Studios LLC.

    AUTHOR:       John DiCamillo


    OVERVIEW
    ========
    Classes for rendering solid meshes of polygons
*/

#ifndef Solid_h
#define Solid_h

#include "Polygon.h"
#include "Graphic.h"
#include "Video.h"
#include "List.h"

// +--------------------------------------------------------------------+

class Solid;
class Model;
class ModelFile;
class Surface;
class Segment;
class Shadow;
class Light;

class OPCODE_data;   // for collision detection

// +--------------------------------------------------------------------+

class Solid : public Graphic
{
public:
    static const char* TYPENAME() { return "Solid"; }

    enum { NAMELEN = 64 };

    static bool    IsCollisionEnabled();
    static void    EnableCollision(bool enable);

    Solid();
    virtual ~Solid();

    // operations
    virtual void   Render(Video* video, DWORD flags);
    virtual void   SelectDetail(Projector* p);
    virtual void   ProjectScreenRect(Projector* p);
    virtual void   Update();

    // accessors / mutators
    Model*         GetModel()     const { return model;         }
    void           GetAllTextures(List<Bitmap>& textures);

    virtual bool   IsDynamic()    const;
    virtual void   SetDynamic(bool d);
    virtual void   SetLuminous(bool l);
    virtual void   SetOrientation(const Matrix& o);
    virtual void   SetOrientation(const Solid& match);
    const Matrix&  Orientation()  const { return orientation;   }
    float          Roll()         const { return roll;          }
    float          Pitch()        const { return pitch;         }
    float          Yaw()          const { return yaw;           }
    virtual bool   IsSolid()      const { return true;          }

    // stencil shadows
    virtual void   CreateShadows(int nlights=1);
    virtual void   UpdateShadows(List<Light>& lights);
    List<Shadow>&  GetShadows()         { return shadows;       }

    bool           Load(const char* mag_file, double scale=1.0);
    bool           Load(ModelFile*  loader,   double scale=1.0);
    void           UseModel(Model* model);
    void           ClearModel();
    bool           Rescale(double scale);

    // collision detection
    virtual int    CollidesWith(Graphic& o);
    virtual int    CheckRayIntersection(Point pt, Point vpn, double len, Point& ipt,
    bool treat_translucent_polys_as_solid=true);
    virtual Poly*  GetIntersectionPoly() const { return intersection_poly; }

    // buffer management
    virtual void   DeletePrivateData();
    virtual void   InvalidateSurfaceData();
    virtual void   InvalidateSegmentData();

protected:
    Model*         model;
    bool           own_model;

    float          roll, pitch, yaw;
    Matrix         orientation;
    Poly*          intersection_poly;

    List<Shadow>   shadows;
};

// +--------------------------------------------------------------------+

class Model
{
    friend class Solid;
    friend class ModelFile;

public:
    static const char* TYPENAME() { return "Model"; }

    enum  {  MAX_VERTS = 256000, MAX_POLYS = 64000 };

    Model();
    Model(const Model& m);
    ~Model();

    Model& operator = (const Model& m);
    int operator == (const Model& that) const { return this == &that; }

    bool           Load(const char* mag_file, double scale=1.0);
    bool           Load(ModelFile*  loader,   double scale=1.0);

    const char*    Name()         const { return name;             }
    int            NumVerts()     const { return nverts;           }
    int            NumSurfaces()  const { return surfaces.size();  }
    int            NumMaterials() const { return materials.size(); }
    int            NumPolys()     const { return npolys;           }
    int            NumSegments()  const;
    double         Radius()       const { return radius;           }
    bool           IsDynamic()    const { return dynamic;          }
    void           SetDynamic(bool d)   { dynamic = d;             }
    bool           IsLuminous()   const { return luminous;         }
    void           SetLuminous(bool l)  { luminous = l;            }

    List<Surface>&    GetSurfaces()     { return surfaces;         }
    List<Material>&   GetMaterials()    { return materials;        }
    const Material*   FindMaterial(const char* mtl_name) const;
    const Material*   ReplaceMaterial(const Material* mtl);
    void              GetAllTextures(List<Bitmap>& textures);

    Poly*          AddPolys(int nsurf, int npolys, int nverts);
    void           ExplodeMesh();
    void           OptimizeMesh();
    void           OptimizeMaterials();
    void           ScaleBy(double factor);

    void           Normalize();
    void           SelectPolys(List<Poly>&, Material* mtl);
    void           SelectPolys(List<Poly>&, Vec3 loc);

    void           AddSurface(Surface* s);
    void           ComputeTangents();

    // buffer management
    void           DeletePrivateData();

private:
    bool           LoadMag5(BYTE* block, int len, double scale);
    bool           LoadMag6(BYTE* block, int len, double scale);

    char           name[Solid::NAMELEN];
    List<Surface>  surfaces;
    List<Material> materials;
    int            nverts;
    int            npolys;
    float          radius;
    float          extents[6];
    bool           luminous;
    bool           dynamic;
};

// +--------------------------------------------------------------------+

class Surface
{
    friend class Solid;
    friend class Model;

public:
    static const char* TYPENAME() { return "Surface"; }

    enum { HIDDEN=1, LOCKED=2, SIMPLE=4, MAX_VERTS=256000, MAX_POLYS=64000 };

    Surface();
    ~Surface();

    int operator == (const Surface& s) const { return this == &s; }

    const char*    Name()            const { return name;                                }
    int            NumVerts()        const { return vertex_set ? vertex_set->nverts : 0; }
    int            NumSegments()     const { return segments.size();                     }
    int            NumPolys()        const { return npolys;                              }
    int            NumIndices()      const { return nindices;                            }
    bool           IsHidden()        const { return state & HIDDEN ? true : false;       }
    bool           IsLocked()        const { return state & LOCKED ? true : false;       }
    bool           IsSimplified()    const { return state & SIMPLE ? true : false;       }

    Model*         GetModel()        const { return model;         }
    List<Segment>& GetSegments()           { return segments;      }
    const Point&   GetOffset()       const { return offset;        }
    const Matrix&  GetOrientation()  const { return orientation;   }
    double         Radius()          const { return radius;        }
    VertexSet*     GetVertexSet()    const { return vertex_set;    }
    Vec3*          GetVLoc()         const { return vloc;          }
    Poly*          GetPolys()        const { return polys;         }

    void           SetName(const char* n);
    void           SetHidden(bool b);
    void           SetLocked(bool b);
    void           SetSimplified(bool b);

    void           CreateVerts(int nverts);
    void           CreatePolys(int npolys);
    void           AddIndices(int n)       { nindices += n;        }
    Poly*          AddPolys(int npolys, int nverts);

    VideoPrivateData* GetVideoPrivateData()   const { return video_data;    }
    void              SetVideoPrivateData(VideoPrivateData* vpd)
    { video_data = vpd; }

    void           ScaleBy(double factor);

    void           BuildHull();
    void           Normalize();
    void           SelectPolys(List<Poly>&, Material* mtl);
    void           SelectPolys(List<Poly>&, Vec3 loc);

    void           InitializeCollisionHull();
    void           ComputeTangents();
    void           CalcGradients(Poly& p, Vec3& tangent, Vec3& binormal);

    void           Copy(Surface& s, Model* m);
    void           OptimizeMesh();
    void           ExplodeMesh();

private:
    char           name[Solid::NAMELEN];
    Model*         model;
    VertexSet*     vertex_set; // for rendering
    Vec3*          vloc;       // for shadow hull
    float          radius;
    int            nhull;
    int            npolys;
    int            nindices;
    int            state;
    Poly*          polys;
    List<Segment>  segments;

    Point          offset;
    Matrix         orientation;

public:
    OPCODE_data*   opcode;

private:
    VideoPrivateData* video_data;
};

// +--------------------------------------------------------------------+

class Segment
{
public:
    static const char* TYPENAME() { return "Segment"; }

    Segment();
    Segment(int n, Poly* p, Material* mtl, Model* mod=0);
    ~Segment();

    bool        IsSolid()         const { return material ? material->IsSolid()      : true;  }
    bool        IsTranslucent()   const { return material ? material->IsTranslucent(): false; }
    bool        IsGlowing()       const { return material ? material->IsGlowing()    : false; }

    VideoPrivateData* GetVideoPrivateData()   const { return video_data;    }
    void              SetVideoPrivateData(VideoPrivateData* vpd)
    { video_data = vpd; }

    int         npolys;
    Poly*       polys;
    Material*   material;
    Model*      model;
    VideoPrivateData* video_data;
};

// +--------------------------------------------------------------------+

class ModelFile
{
public:
    ModelFile(const char* fname);
    virtual ~ModelFile();

    virtual bool   Load(Model* m, double scale=1.0);
    virtual bool   Save(Model* m);

protected:
    char        filename[256];
    Model*      model;

    // internal accessors:
    char*       pname;
    int*        pnverts;
    int*        pnpolys;
    float*      pradius;
};

// +--------------------------------------------------------------------+

#endif  // Solid_h