2 * \file geom_object.cpp
3 * \brief CGeomGeomObject
4 * \date 2012-08-22 08:58GMT
5 * \author Jan Boon (Kaetemi)
10 * Copyright (C) 2012 by authors
12 * This file is part of RYZOM CORE PIPELINE.
13 * RYZOM CORE PIPELINE is free software: you can redistribute it
14 * and/or modify it under the terms of the GNU Affero General Public
15 * License as published by the Free Software Foundation, either
16 * version 3 of the License, or (at your option) any later version.
18 * RYZOM CORE PIPELINE is distributed in the hope that it will be
19 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
20 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Affero General Public License for more details.
23 * You should have received a copy of the GNU Affero General Public
24 * License along with RYZOM CORE PIPELINE. If not, see
25 * <http://www.gnu.org/licenses/>.
28 #include <nel/misc/types_nl.h>
29 #include "geom_object.h"
34 // #include <nel/misc/debug.h>
38 // using namespace std;
39 // using namespace NLMISC;
45 #define PMB_GEOM_UNKNOWN0900_CHUNK_ID 0x0900
46 #define PMB_GEOM_BUFFERS_CHUNK_ID 0x08fe
48 CGeomObject::CGeomObject(CScene
*scene
) : CObject(scene
), m_Unknown0900(NULL
), m_GeomBuffers(NULL
)
53 CGeomObject::~CGeomObject()
55 if (!m_ChunksOwnsPointers
)
62 const ucstring
CGeomObject::DisplayName
= ucstring("GeomObject");
63 const char *CGeomObject::InternalName
= "GeomObject";
64 const char *CGeomObject::InternalNameUnknown
= "GeomObjectUnknown";
65 const NLMISC::CClassId
CGeomObject::ClassId
= NLMISC::CClassId(0x37097c44, 0x38aa3f24); /* Not official, please correct */
66 const TSClassId
CGeomObject::SuperClassId
= 0x00000010;
67 const CGeomObjectClassDesc
GeomObjectClassDesc(&DllPluginDescBuiltin
);
68 const CGeomObjectSuperClassDesc
GeomObjectSuperClassDesc(&GeomObjectClassDesc
);
70 void CGeomObject::parse(uint16 version
, uint filter
)
74 CObject::parse(version
);
76 else if (filter
== PMB_GEOM_OBJECT_PARSE_FILTER
)
78 if (!m_ChunksOwnsPointers
)
80 m_Unknown0900
= getChunk(PMB_GEOM_UNKNOWN0900_CHUNK_ID
);
81 m_GeomBuffers
= static_cast<STORAGE::CGeomBuffers
*>(getChunk(PMB_GEOM_BUFFERS_CHUNK_ID
));
86 void CGeomObject::clean()
91 void CGeomObject::build(uint16 version
, uint filter
)
95 CObject::build(version
);
97 else if (filter
== PMB_GEOM_OBJECT_PARSE_FILTER
)
99 if (m_Unknown0900
) putChunk(PMB_GEOM_UNKNOWN0900_CHUNK_ID
, m_Unknown0900
);
100 if (m_GeomBuffers
) putChunk(PMB_GEOM_BUFFERS_CHUNK_ID
, m_GeomBuffers
);
104 void CGeomObject::disown()
106 m_Unknown0900
= NULL
;
107 m_GeomBuffers
= NULL
;
111 void CGeomObject::init()
116 bool CGeomObject::inherits(const NLMISC::CClassId classId
) const
118 if (classId
== classDesc()->classId()) return true;
119 return CObject::inherits(classId
);
122 const ISceneClassDesc
*CGeomObject::classDesc() const
124 return &GeomObjectClassDesc
;
127 void CGeomObject::toStringLocal(std::ostream
&ostream
, const std::string
&pad
, uint filter
) const
131 CObject::toStringLocal(ostream
, pad
);
133 else if (filter
== PMB_GEOM_OBJECT_PARSE_FILTER
)
135 std::string padpad
= pad
+ "\t";
138 ostream
<< "\n" << pad
<< "GeomObject Unknown 0x0900: ";
139 m_Unknown0900
->toString(ostream
, padpad
);
143 ostream
<< "\n" << pad
<< "GeomBuffers: ";
144 m_GeomBuffers
->toString(ostream
, padpad
);
149 inline uint32
rrsub(uint32 v
, uint32 size
)
155 inline uint32
rradd(uint32 v
, uint32 size
)
158 if (vp
!= size
) return vp
;
162 void CGeomObject::triangulatePolyFace(std::vector
<STORAGE::CGeomTriIndex
> &triangles
, const STORAGE::CGeomPolyFaceInfo
&polyFace
)
164 nlassert(polyFace
.Vertices
.size() >= 3);
165 nlassert(polyFace
.Triangulation
.size() == polyFace
.Vertices
.size() - 3);
166 uint nbVert
= polyFace
.Vertices
.size();
167 uint nbCuts
= polyFace
.Triangulation
.size();
168 uint nbTriangles
= 0;
170 // This code creates a matrix, aka a table, of all possible paths
171 // that can be traveled to get directly from one vertex to another
173 // Outer edges of the polygon are one-way, backwards.
174 // Cut edges can be traveled both ways.
175 // Each edge direction can only be traveled by one triangle.
176 // Ingenious, if I may say so myself.
177 // Bad performance by std::vector, though.
178 std::vector
<std::vector
<bool> > from_to
;
179 from_to
.resize(nbVert
);
180 for (uint i
= 0; i
< nbVert
; ++i
)
182 from_to
[i
].resize(nbVert
);
183 for (uint j
= 0; j
< nbVert
; ++j
)
185 from_to
[i
][j
] = false;
187 // Can travel backwards over the outer edge
188 from_to
[i
][rrsub(i
, nbVert
)] = true;
190 for (uint i
= 0; i
< nbCuts
; ++i
)
192 // Can travel both ways over cuts, but the first direction is handled directly!
193 // from_to[polyFace.Triangulation[i].first][polyFace.Triangulation[i].second] = true;
194 from_to
[polyFace
.Triangulation
[i
].second
][polyFace
.Triangulation
[i
].first
] = true;
196 // Triangulate all cuts, this assumes cuts are in the direction
197 // of a triangle that is not already handled by another cut...
198 for (uint i
= 0; i
< nbCuts
; ++i
)
200 uint32 a
= polyFace
.Triangulation
[i
].first
;
201 uint32 b
= polyFace
.Triangulation
[i
].second
;
202 // from_to[polyFace.Triangulation[i].first][polyFace.Triangulation[i].second] = false; // handled!
203 // Try to find a path that works
204 for (uint c
= 0; c
< nbVert
; ++c
)
206 // Can we make a triangle
207 if (from_to
[b
][c
] && from_to
[c
][a
])
209 STORAGE::CGeomTriIndex tri
;
210 tri
.a
= polyFace
.Vertices
[c
];
211 tri
.b
= polyFace
.Vertices
[b
];
212 tri
.c
= polyFace
.Vertices
[a
];
213 triangles
.push_back(tri
);
215 // nldebug("add tri from cut");
216 from_to
[b
][c
] = false;
217 from_to
[c
][a
] = false;
222 // Find... The Last Triangle
223 for (uint a
= 0; a
< nbVert
; ++a
)
225 uint b
= rrsub(a
, nbVert
);
226 // Can we still travel backwards over the outer edge?
229 for (uint c
= 0; c
< nbVert
; ++c
)
231 // Can we make a triangle
232 if (from_to
[b
][c
] && from_to
[c
][a
])
234 STORAGE::CGeomTriIndex tri
;
235 tri
.a
= polyFace
.Vertices
[c
];
236 tri
.b
= polyFace
.Vertices
[b
];
237 tri
.c
= polyFace
.Vertices
[a
];
238 triangles
.push_back(tri
);
240 // nldebug("add final tri");
241 from_to
[b
][c
] = false;
242 from_to
[c
][a
] = false;
248 // nldebug("triangles: %i", nbTriangles);
249 // nldebug("cuts: %i", nbCuts);
250 nlassert(nbTriangles
== nbCuts
+ 1);
253 IStorageObject
*CGeomObject::createChunkById(uint16 id
, bool container
)
257 case PMB_GEOM_UNKNOWN0900_CHUNK_ID
:
258 return new CStorageArray
<sint32
>();
259 case PMB_GEOM_BUFFERS_CHUNK_ID
:
260 return new STORAGE::CGeomBuffers();
262 return CObject::createChunkById(id
, container
);
265 } /* namespace BUILTIN */
266 } /* namespace MAX */
267 } /* namespace PIPELINE */