2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #define _USE_MATH_DEFINES
26 #include "preferences.h"
27 #include "brush_primit.h"
28 #include "signal/signal.h"
31 Signal0 g_patchTextureChangedCallbacks;
33 void Patch_addTextureChangedCallback(const SignalHandler &handler)
35 g_patchTextureChangedCallbacks.connectLast(handler);
38 void Patch_textureChanged()
40 g_patchTextureChangedCallbacks();
44 Shader *PatchInstance::m_state_selpoint;
45 Shader *Patch::m_state_ctrl;
46 Shader *Patch::m_state_lattice;
47 EPatchType Patch::m_type;
50 std::size_t MAX_PATCH_WIDTH = 0;
51 std::size_t MAX_PATCH_HEIGHT = 0;
53 int g_PatchSubdivideThreshold = 4;
55 void BezierCurveTree_Delete(BezierCurveTree *pCurve)
58 BezierCurveTree_Delete(pCurve->left);
59 BezierCurveTree_Delete(pCurve->right);
64 std::size_t BezierCurveTree_Setup(BezierCurveTree *pCurve, std::size_t index, std::size_t stride)
67 if (pCurve->left && pCurve->right) {
68 index = BezierCurveTree_Setup(pCurve->left, index, stride);
69 pCurve->index = index * stride;
71 index = BezierCurveTree_Setup(pCurve->right, index, stride);
73 pCurve->index = BEZIERCURVETREE_MAX_INDEX;
80 bool BezierCurve_IsCurved(BezierCurve *pCurve)
82 Vector3 vTemp(vector3_subtracted(pCurve->right, pCurve->left));
83 Vector3 v1(vector3_subtracted(pCurve->crd, pCurve->left));
84 Vector3 v2(vector3_subtracted(pCurve->right, pCurve->crd));
86 if (vector3_equal(v1, g_vector3_identity) || vector3_equal(vTemp, v1)) { // return 0 if 1->2 == 0 or 1->2 == 1->3
90 vector3_normalise(v1);
91 vector3_normalise(v2);
92 if (vector3_equal(v1, v2)) {
97 const double width = vector3_length(v3);
98 vector3_scale(v3, 1.0 / width);
100 if (vector3_equal(v1, v3) && vector3_equal(v2, v3)) {
104 const double angle = acos(vector3_dot(v1, v2)) / c_pi;
106 const double index = width * angle;
108 if (index > static_cast<double>( g_PatchSubdivideThreshold )) {
114 void BezierInterpolate(BezierCurve *pCurve)
116 pCurve->left = vector3_mid(pCurve->left, pCurve->crd);
117 pCurve->right = vector3_mid(pCurve->crd, pCurve->right);
118 pCurve->crd = vector3_mid(pCurve->left, pCurve->right);
121 const std::size_t PATCH_MAX_SUBDIVISION_DEPTH = 16;
123 void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList, std::size_t depth = 0)
125 GSList *pLeftList = 0;
126 GSList *pRightList = 0;
127 BezierCurve *pCurve, *pLeftCurve, *pRightCurve;
130 for (GSList *l = pCurveList; l; l = l->next) {
131 pCurve = (BezierCurve *) (l->data);
132 if (bSplit || BezierCurve_IsCurved(pCurve)) {
134 pLeftCurve = new BezierCurve;
135 pRightCurve = new BezierCurve;
136 pLeftCurve->left = pCurve->left;
137 pRightCurve->right = pCurve->right;
138 BezierInterpolate(pCurve);
139 pLeftCurve->crd = pCurve->left;
140 pRightCurve->crd = pCurve->right;
141 pLeftCurve->right = pCurve->crd;
142 pRightCurve->left = pCurve->crd;
144 pLeftList = g_slist_prepend(pLeftList, pLeftCurve);
145 pRightList = g_slist_prepend(pRightList, pRightCurve);
149 if (pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH) {
150 pTree->left = new BezierCurveTree;
151 pTree->right = new BezierCurveTree;
152 BezierCurveTree_FromCurveList(pTree->left, pLeftList, depth + 1);
153 BezierCurveTree_FromCurveList(pTree->right, pRightList, depth + 1);
155 for (GSList *l = pLeftList; l != 0; l = g_slist_next(l)) {
156 delete (BezierCurve *) l->data;
159 for (GSList *l = pRightList; l != 0; l = g_slist_next(l)) {
160 delete (BezierCurve *) l->data;
163 g_slist_free(pLeftList);
164 g_slist_free(pRightList);
172 int Patch::m_CycleCapIndex = 0;
175 void Patch::setDims(std::size_t w, std::size_t h)
180 ASSERT_MESSAGE(w <= MAX_PATCH_WIDTH, "patch too wide");
181 if (w > MAX_PATCH_WIDTH) {
183 } else if (w < MIN_PATCH_WIDTH) {
190 ASSERT_MESSAGE(h <= MAX_PATCH_HEIGHT, "patch too tall");
191 if (h > MAX_PATCH_HEIGHT) {
192 h = MAX_PATCH_HEIGHT;
193 } else if (h < MIN_PATCH_HEIGHT) {
194 h = MIN_PATCH_HEIGHT;
200 if (m_width * m_height != m_ctrl.size()) {
201 m_ctrl.resize(m_width * m_height);
202 onAllocate(m_ctrl.size());
206 inline const Colour4b &colour_for_index(std::size_t i, std::size_t width)
208 return (i % 2 || (i / width) % 2) ? colour_inside : colour_corner;
211 inline bool float_valid(float f)
216 bool Patch::isValid() const
218 if (!m_width || !m_height) {
222 for (const_iterator i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
223 if (!float_valid((*i).m_vertex.x())
224 || !float_valid((*i).m_vertex.y())
225 || !float_valid((*i).m_vertex.z())
226 || !float_valid((*i).m_texcoord.x())
227 || !float_valid((*i).m_texcoord.y())) {
228 globalErrorStream() << "patch has invalid control points\n";
235 void Patch::UpdateCachedData()
237 m_ctrl_vertices.clear();
238 m_lattice_indices.clear();
241 m_tess.m_numStrips = 0;
242 m_tess.m_lenStrips = 0;
243 m_tess.m_nArrayHeight = 0;
244 m_tess.m_nArrayWidth = 0;
245 m_tess.m_curveTreeU.resize(0);
246 m_tess.m_curveTreeV.resize(0);
247 m_tess.m_indices.resize(0);
248 m_tess.m_vertices.resize(0);
249 m_tess.m_arrayHeight.resize(0);
250 m_tess.m_arrayWidth.resize(0);
251 m_aabb_local = AABB();
255 BuildTesselationCurves(ROW);
256 BuildTesselationCurves(COL);
260 IndexBuffer ctrl_indices;
262 m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
263 ctrl_indices.reserve(m_ctrlTransformed.size());
265 UniqueVertexBuffer<PointVertex> inserter(m_ctrl_vertices);
266 for (iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i) {
267 ctrl_indices.insert(inserter.insert(pointvertex_quantised(
268 PointVertex(reinterpret_cast<const Vertex3f &>((*i).m_vertex ),
269 colour_for_index(i - m_ctrlTransformed.begin(), m_width)))));
273 for (IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i) {
274 if (std::size_t(i - ctrl_indices.begin()) % m_width) {
275 m_lattice_indices.insert(*(i - 1));
276 m_lattice_indices.insert(*i);
278 if (std::size_t(i - ctrl_indices.begin()) >= m_width) {
279 m_lattice_indices.insert(*(i - m_width));
280 m_lattice_indices.insert(*i);
287 Array<RenderIndex>::iterator first = m_tess.m_indices.begin();
288 for ( std::size_t s = 0; s < m_tess.m_numStrips; s++ )
290 Array<RenderIndex>::iterator last = first + m_tess.m_lenStrips;
292 for ( Array<RenderIndex>::iterator i( first ); i + 2 != last; i += 2 )
294 ArbitraryMeshTriangle_sumTangents( m_tess.m_vertices[*( i + 0 )], m_tess.m_vertices[*( i + 1 )], m_tess.m_vertices[*( i + 2 )] );
295 ArbitraryMeshTriangle_sumTangents( m_tess.m_vertices[*( i + 2 )], m_tess.m_vertices[*( i + 1 )], m_tess.m_vertices[*( i + 3 )] );
301 for ( Array<ArbitraryMeshVertex>::iterator i = m_tess.m_vertices.begin(); i != m_tess.m_vertices.end(); ++i )
303 vector3_normalise( reinterpret_cast<Vector3&>( ( *i ).tangent ) );
304 vector3_normalise( reinterpret_cast<Vector3&>( ( *i ).bitangent ) );
312 void Patch::InvertMatrix()
316 PatchControlArray_invert(m_ctrl, m_width, m_height);
318 controlPointsChanged();
321 void Patch::TransposeMatrix()
326 Array<PatchControl> tmp(m_width * m_height);
327 copy_ctrl(tmp.data(), m_ctrl.data(), m_ctrl.data() + m_width * m_height);
329 PatchControlIter from = tmp.data();
330 for (std::size_t h = 0; h != m_height; ++h) {
331 PatchControlIter to = m_ctrl.data() + h;
332 for (std::size_t w = 0; w != m_width; ++w, ++from, to += m_height) {
339 std::size_t tmp = m_width;
344 controlPointsChanged();
347 void Patch::Redisperse(EMatrixMajor mt)
349 std::size_t w, h, width, height, row_stride, col_stride;
350 PatchControl *p1, *p2, *p3;
356 width = (m_width - 1) >> 1;
359 row_stride = m_width;
362 width = (m_height - 1) >> 1;
364 col_stride = m_width;
368 ERROR_MESSAGE("neither row-major nor column-major");
372 for (h = 0; h < height; h++) {
373 p1 = m_ctrl.data() + (h * row_stride);
374 for (w = 0; w < width; w++) {
375 p2 = p1 + col_stride;
376 p3 = p2 + col_stride;
377 p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
382 controlPointsChanged();
385 void Patch::Smooth(EMatrixMajor mt)
387 std::size_t w, h, width, height, row_stride, col_stride;
389 PatchControl *p1, *p2, *p3, *p2b;
395 width = (m_width - 1) >> 1;
398 row_stride = m_width;
401 width = (m_height - 1) >> 1;
403 col_stride = m_width;
407 ERROR_MESSAGE("neither row-major nor column-major");
412 for (h = 0; h < height; h++) {
413 p1 = m_ctrl.data() + (h * row_stride);
414 p2 = p1 + (2 * width) * col_stride;
415 //globalErrorStream() << "compare " << p1->m_vertex << " and " << p2->m_vertex << "\n";
416 if (vector3_length_squared(vector3_subtracted(p1->m_vertex, p2->m_vertex)) > 1.0) {
417 //globalErrorStream() << "too far\n";
423 for (h = 0; h < height; h++) {
424 p1 = m_ctrl.data() + (h * row_stride) + col_stride;
425 for (w = 0; w < width - 1; w++) {
426 p2 = p1 + col_stride;
427 p3 = p2 + col_stride;
428 p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
432 p1 = m_ctrl.data() + (h * row_stride) + (2 * width - 1) * col_stride;
433 p2 = m_ctrl.data() + (h * row_stride);
434 p2b = m_ctrl.data() + (h * row_stride) + (2 * width) * col_stride;
435 p3 = m_ctrl.data() + (h * row_stride) + col_stride;
436 p2->m_vertex = p2b->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
440 controlPointsChanged();
443 void Patch::InsertRemove(bool bInsert, bool bColumn, bool bFirst)
448 if (bColumn && (m_width + 2 <= MAX_PATCH_WIDTH)) {
449 InsertPoints(COL, bFirst);
450 } else if (m_height + 2 <= MAX_PATCH_HEIGHT) {
451 InsertPoints(ROW, bFirst);
454 if (bColumn && (m_width - 2 >= MIN_PATCH_WIDTH)) {
455 RemovePoints(COL, bFirst);
456 } else if (m_height - 2 >= MIN_PATCH_HEIGHT) {
457 RemovePoints(ROW, bFirst);
461 controlPointsChanged();
464 Patch *Patch::MakeCap(Patch *patch, EPatchCap eType, EMatrixMajor mt, bool bFirst)
466 std::size_t i, width, height;
478 ERROR_MESSAGE("neither row-major nor column-major");
482 Array<Vector3> p(width);
484 std::size_t nIndex = (bFirst) ? 0 : height - 1;
486 for (i = 0; i < width; i++) {
487 p[(bFirst) ? i : (width - 1) - i] = ctrlAt(nIndex, i).m_vertex;
490 for (i = 0; i < width; i++) {
491 p[(bFirst) ? i : (width - 1) - i] = ctrlAt(i, nIndex).m_vertex;
495 patch->ConstructSeam(eType, p.data(), width);
499 void Patch::FlipTexture(int nAxis)
503 for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
504 (*i).m_texcoord[nAxis] = -(*i).m_texcoord[nAxis];
507 controlPointsChanged();
510 void Patch::TranslateTexture(float s, float t)
514 s = -1 * s / m_state->getTexture().width;
515 t = t / m_state->getTexture().height;
517 for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
518 (*i).m_texcoord[0] += s;
519 (*i).m_texcoord[1] += t;
522 controlPointsChanged();
525 void Patch::ScaleTexture(float s, float t)
529 for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
530 (*i).m_texcoord[0] *= s;
531 (*i).m_texcoord[1] *= t;
534 controlPointsChanged();
537 void Patch::RotateTexture(float angle)
541 const float s = static_cast<float>( sin(degrees_to_radians(angle)));
542 const float c = static_cast<float>( cos(degrees_to_radians(angle)));
544 for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
545 const float x = (*i).m_texcoord[0];
546 const float y = (*i).m_texcoord[1];
547 (*i).m_texcoord[0] = (x * c) - (y * s);
548 (*i).m_texcoord[1] = (y * c) + (x * s);
551 controlPointsChanged();
555 void Patch::SetTextureRepeat(float s, float t)
558 float si, ti, sc, tc;
563 si = s / (float) (m_width - 1);
564 ti = t / (float) (m_height - 1);
566 pDest = m_ctrl.data();
567 for (h = 0, tc = 0.0f; h < m_height; h++, tc += ti) {
568 for (w = 0, sc = 0.0f; w < m_width; w++, sc += si) {
569 pDest->m_texcoord[0] = sc;
570 pDest->m_texcoord[1] = tc;
575 controlPointsChanged();
579 void Patch::SetTextureInfo(texdef_t *pt)
581 if(pt->getShift()[0] || pt->getShift()[1])
582 TranslateTexture (pt->getShift()[0], pt->getShift()[1]);
583 else if(pt->getScale()[0] || pt->getScale()[1])
585 if(pt->getScale()[0] == 0.0f) pt->setScale(0, 1.0f);
586 if(pt->getScale()[1] == 0.0f) pt->setScale(1, 1.0f);
587 ScaleTexture (pt->getScale()[0], pt->getScale()[1]);
590 RotateTexture (pt->rotate);
594 inline int texture_axis(const Vector3 &normal)
596 // axis dominance order: Z, X, Y
597 return (normal.x() >= normal.y()) ? (normal.x() > normal.z()) ? 0 : 2 : (normal.y() > normal.z()) ? 1 : 2;
600 void Patch::CapTexture()
602 const PatchControl &p1 = m_ctrl[m_width];
603 const PatchControl &p2 = m_ctrl[m_width * (m_height - 1)];
604 const PatchControl &p3 = m_ctrl[(m_width * m_height) - 1];
607 Vector3 normal(g_vector3_identity);
610 Vector3 tmp(vector3_cross(
611 vector3_subtracted(p2.m_vertex, m_ctrl[0].m_vertex),
612 vector3_subtracted(p3.m_vertex, m_ctrl[0].m_vertex)
614 if (!vector3_equal(tmp, g_vector3_identity)) {
615 vector3_add(normal, tmp);
619 Vector3 tmp(vector3_cross(
620 vector3_subtracted(p1.m_vertex, p3.m_vertex),
621 vector3_subtracted(m_ctrl[0].m_vertex, p3.m_vertex)
623 if (!vector3_equal(tmp, g_vector3_identity)) {
624 vector3_add(normal, tmp);
628 ProjectTexture(texture_axis(normal));
631 // uses longest parallel chord to calculate texture coords for each row/col
632 void Patch::NaturalTexture()
637 float fSize = (float) m_state->getTexture().width * Texdef_getDefaultTextureScale();
641 PatchControl *pWidth = m_ctrl.data();
642 for (std::size_t w = 0; w < m_width; w++, pWidth++) {
644 PatchControl *pHeight = pWidth;
645 for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) {
646 pHeight->m_texcoord[0] = static_cast<float>( tex );
650 if (w + 1 == m_width) {
655 PatchControl *pHeight = pWidth;
656 for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) {
657 Vector3 v(vector3_subtracted(pHeight->m_vertex, (pHeight + 1)->m_vertex));
658 double length = tex + (vector3_length(v) / fSize);
659 if (fabs(length) > texBest) {
670 float fSize = -(float) m_state->getTexture().height * Texdef_getDefaultTextureScale();
674 PatchControl *pHeight = m_ctrl.data();
675 for (std::size_t h = 0; h < m_height; h++, pHeight += m_width) {
677 PatchControl *pWidth = pHeight;
678 for (std::size_t w = 0; w < m_width; w++, pWidth++) {
679 pWidth->m_texcoord[1] = static_cast<float>( tex );
683 if (h + 1 == m_height) {
688 PatchControl *pWidth = pHeight;
689 for (std::size_t w = 0; w < m_width; w++, pWidth++) {
690 Vector3 v(vector3_subtracted(pWidth->m_vertex, (pWidth + m_width)->m_vertex));
691 double length = tex + (vector3_length(v) / fSize);
692 if (fabs(length) > texBest) {
702 controlPointsChanged();
709 void Patch::AccumulateBBox()
711 m_aabb_local = AABB();
713 for (PatchControlArray::iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i) {
714 aabb_extend_by_point_safe(m_aabb_local, (*i).m_vertex);
721 void Patch::InsertPoints(EMatrixMajor mt, bool bFirst)
723 std::size_t width, height, row_stride, col_stride;
728 row_stride = m_width;
733 col_stride = m_width;
739 ERROR_MESSAGE("neither row-major nor column-major");
745 PatchControl *p1 = m_ctrl.data();
747 if(GlobalSelectionSystem().countSelected() != 0)
749 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
750 PatchInstance* patch = Instance_getPatch(instance);
751 patch->m_selectable.isSelected();
754 for (std::size_t w = 0; w != width; ++w, p1 += col_stride) {
756 PatchControl *p2 = p1;
757 for (std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride) {
758 if (0) { //p2->m_selectable.isSelected())
769 PatchControl *p2 = p1;
770 for (std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride) {
771 if (0) { //p2->m_selectable.isSelected())
783 Array<PatchControl> tmp(m_ctrl);
785 std::size_t row_stride2, col_stride2;
788 setDims(m_width, m_height + 2);
790 row_stride2 = m_width;
793 setDims(m_width + 2, m_height);
794 col_stride2 = m_width;
798 ERROR_MESSAGE("neither row-major nor column-major");
813 } else if (pos == 0) {
815 } else if (pos % 2) {
820 for (std::size_t w = 0; w != width; ++w) {
821 PatchControl *p1 = tmp.data() + (w * col_stride);
822 PatchControl *p2 = m_ctrl.data() + (w * col_stride2);
823 for (std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride) {
825 p2 += 2 * row_stride2;
830 p1 = tmp.data() + (w * col_stride + pos * row_stride);
831 p2 = m_ctrl.data() + (w * col_stride2 + pos * row_stride2);
833 PatchControl *r2a = (p2 + row_stride2);
834 PatchControl *r2b = (p2 - row_stride2);
835 PatchControl *c2a = (p1 - 2 * row_stride);
836 PatchControl *c2b = (p1 - row_stride);
838 // set two new row points
839 *(p2 + 2 * row_stride2) = *p1;
842 for (std::size_t i = 0; i != 3; ++i) {
843 r2a->m_vertex[i] = float_mid(c2b->m_vertex[i], p1->m_vertex[i]);
845 r2b->m_vertex[i] = float_mid(c2a->m_vertex[i], c2b->m_vertex[i]);
847 p2->m_vertex[i] = float_mid(r2a->m_vertex[i], r2b->m_vertex[i]);
849 for (std::size_t i = 0; i != 2; ++i) {
850 r2a->m_texcoord[i] = float_mid(c2b->m_texcoord[i], p1->m_texcoord[i]);
852 r2b->m_texcoord[i] = float_mid(c2a->m_texcoord[i], c2b->m_texcoord[i]);
854 p2->m_texcoord[i] = float_mid(r2a->m_texcoord[i], r2b->m_texcoord[i]);
859 void Patch::RemovePoints(EMatrixMajor mt, bool bFirst)
861 std::size_t width, height, row_stride, col_stride;
866 row_stride = m_width;
871 col_stride = m_width;
877 ERROR_MESSAGE("neither row-major nor column-major");
883 PatchControl *p1 = m_ctrl.data();
884 for (std::size_t w = 0; w != width; ++w, p1 += col_stride) {
886 PatchControl *p2 = p1;
887 for (std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride) {
888 if (0) { //p2->m_selectable.isSelected())
899 PatchControl *p2 = p1;
900 for (std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride) {
901 if (0) { //p2->m_selectable.isSelected())
913 Array<PatchControl> tmp(m_ctrl);
915 std::size_t row_stride2, col_stride2;
918 setDims(m_width, m_height - 2);
920 row_stride2 = m_width;
923 setDims(m_width - 2, m_height);
924 col_stride2 = m_width;
928 ERROR_MESSAGE("neither row-major nor column-major");
942 } else if (pos == 0) {
944 } else if (pos > height - 3) {
946 } else if (pos % 2) {
950 for (std::size_t w = 0; w != width; w++) {
951 PatchControl *p1 = tmp.data() + (w * col_stride);
952 PatchControl *p2 = m_ctrl.data() + (w * col_stride2);
953 for (std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride) {
955 p1 += 2 * row_stride2;
961 p1 = tmp.data() + (w * col_stride + pos * row_stride);
962 p2 = m_ctrl.data() + (w * col_stride2 + pos * row_stride2);
964 for (std::size_t i = 0; i < 3; i++) {
965 (p2 - row_stride2)->m_vertex[i] =
966 ((p1 + 2 * row_stride)->m_vertex[i] + (p1 - 2 * row_stride)->m_vertex[i]) * 0.5f;
968 (p2 - row_stride2)->m_vertex[i] =
969 (p2 - row_stride2)->m_vertex[i] + (2.0f * ((p1)->m_vertex[i] - (p2 - row_stride2)->m_vertex[i]));
971 for (std::size_t i = 0; i < 2; i++) {
972 (p2 - row_stride2)->m_texcoord[i] =
973 ((p1 + 2 * row_stride)->m_texcoord[i] + (p1 - 2 * row_stride)->m_texcoord[i]) * 0.5f;
975 (p2 - row_stride2)->m_texcoord[i] = (p2 - row_stride2)->m_texcoord[i] +
976 (2.0f * ((p1)->m_texcoord[i] - (p2 - row_stride2)->m_texcoord[i]));
981 void Patch::ConstructSeam(EPatchCap eType, Vector3 *p, std::size_t width)
986 m_ctrl[0].m_vertex = p[0];
987 m_ctrl[1].m_vertex = p[1];
988 m_ctrl[2].m_vertex = p[1];
989 m_ctrl[3].m_vertex = p[1];
990 m_ctrl[4].m_vertex = p[1];
991 m_ctrl[5].m_vertex = p[1];
992 m_ctrl[6].m_vertex = p[2];
993 m_ctrl[7].m_vertex = p[1];
994 m_ctrl[8].m_vertex = p[1];
999 Vector3 p3(vector3_added(p[2], vector3_subtracted(p[0], p[1])));
1000 m_ctrl[0].m_vertex = p3;
1001 m_ctrl[1].m_vertex = p3;
1002 m_ctrl[2].m_vertex = p[2];
1003 m_ctrl[3].m_vertex = p3;
1004 m_ctrl[4].m_vertex = p3;
1005 m_ctrl[5].m_vertex = p[1];
1006 m_ctrl[6].m_vertex = p3;
1007 m_ctrl[7].m_vertex = p3;
1008 m_ctrl[8].m_vertex = p[0];
1012 Vector3 p5(vector3_mid(p[0], p[4]));
1015 m_ctrl[0].m_vertex = p[0];
1016 m_ctrl[1].m_vertex = p5;
1017 m_ctrl[2].m_vertex = p[4];
1018 m_ctrl[3].m_vertex = p[1];
1019 m_ctrl[4].m_vertex = p[2];
1020 m_ctrl[5].m_vertex = p[3];
1021 m_ctrl[6].m_vertex = p[2];
1022 m_ctrl[7].m_vertex = p[2];
1023 m_ctrl[8].m_vertex = p[2];
1028 m_ctrl[0].m_vertex = p[4];
1029 m_ctrl[1].m_vertex = p[3];
1030 m_ctrl[2].m_vertex = p[2];
1031 m_ctrl[3].m_vertex = p[1];
1032 m_ctrl[4].m_vertex = p[0];
1033 m_ctrl[5].m_vertex = p[3];
1034 m_ctrl[6].m_vertex = p[3];
1035 m_ctrl[7].m_vertex = p[2];
1036 m_ctrl[8].m_vertex = p[1];
1037 m_ctrl[9].m_vertex = p[1];
1038 m_ctrl[10].m_vertex = p[3];
1039 m_ctrl[11].m_vertex = p[3];
1040 m_ctrl[12].m_vertex = p[2];
1041 m_ctrl[13].m_vertex = p[1];
1042 m_ctrl[14].m_vertex = p[1];
1045 case eCapCylinder: {
1046 std::size_t mid = (width - 1) >> 1;
1048 bool degenerate = (mid % 2) != 0;
1050 std::size_t newHeight = mid + (degenerate ? 2 : 1);
1052 setDims(3, newHeight);
1056 for (std::size_t i = width; i != width + 2; ++i) {
1057 p[i] = p[width - 1];
1062 PatchControl *pCtrl = m_ctrl.data();
1063 for (std::size_t i = 0; i != m_height; ++i, pCtrl += m_width) {
1064 pCtrl->m_vertex = p[i];
1068 PatchControl *pCtrl = m_ctrl.data() + 2;
1069 std::size_t h = m_height - 1;
1070 for (std::size_t i = 0; i != m_height; ++i, pCtrl += m_width) {
1071 pCtrl->m_vertex = p[h + (h - i)];
1079 ERROR_MESSAGE("invalid patch-cap type");
1083 controlPointsChanged();
1086 void Patch::ProjectTexture(int nAxis)
1106 ERROR_MESSAGE("invalid axis");
1110 float fWidth = 1 / (m_state->getTexture().width * Texdef_getDefaultTextureScale());
1111 float fHeight = 1 / (m_state->getTexture().height * -Texdef_getDefaultTextureScale());
1113 for (PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i) {
1114 (*i).m_texcoord[0] = (*i).m_vertex[s] * fWidth;
1115 (*i).m_texcoord[1] = (*i).m_vertex[t] * fHeight;
1118 controlPointsChanged();
1121 void Patch::constructPlane(const AABB &aabb, int axis, std::size_t width, std::size_t height)
1123 setDims(width, height);
1143 ERROR_MESSAGE("invalid view-type");
1147 if (m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH) {
1150 if (m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT) {
1155 vStart[x] = aabb.origin[x] - aabb.extents[x];
1156 vStart[y] = aabb.origin[y] - aabb.extents[y];
1157 vStart[z] = aabb.origin[z];
1159 float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float) (m_width - 1));
1160 float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float) (m_height - 1));
1163 vTmp[z] = vStart[z];
1164 PatchControl *pCtrl = m_ctrl.data();
1166 vTmp[y] = vStart[y];
1167 for (std::size_t h = 0; h < m_height; h++) {
1168 vTmp[x] = vStart[x];
1169 for (std::size_t w = 0; w < m_width; w++, ++pCtrl) {
1170 pCtrl->m_vertex = vTmp;
1179 void Patch::ConstructPrefab(const AABB &aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height)
1183 if (eType != ePlane) {
1184 vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1185 vPos[1] = aabb.origin;
1186 vPos[2] = vector3_added(aabb.origin, aabb.extents);
1189 if (eType == ePlane) {
1190 constructPlane(aabb, axis, width, height);
1191 } else if (eType == eSqCylinder
1192 || eType == eCylinder
1193 || eType == eDenseCylinder
1194 || eType == eVeryDenseCylinder
1196 || eType == eSphere) {
1197 unsigned char *pIndex;
1198 unsigned char pCylIndex[] =
1212 PatchControl *pStart;
1216 pStart = m_ctrl.data();
1218 case eDenseCylinder:
1219 case eVeryDenseCylinder:
1222 pStart = m_ctrl.data() + 1;
1226 pStart = m_ctrl.data() + 1;
1230 pStart = m_ctrl.data() + (9 + 1);
1233 ERROR_MESSAGE("this should be unreachable");
1237 for (std::size_t h = 0; h < 3; h++, pStart += 9) {
1239 PatchControl *pCtrl = pStart;
1240 for (std::size_t w = 0; w < 8; w++, pCtrl++) {
1241 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1242 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1243 pCtrl->m_vertex[2] = vPos[h][2];
1250 PatchControl *pCtrl = m_ctrl.data();
1251 for (std::size_t h = 0; h < 3; h++, pCtrl += 9) {
1252 pCtrl[8].m_vertex = pCtrl[0].m_vertex;
1256 case eDenseCylinder:
1257 case eVeryDenseCylinder:
1259 PatchControl *pCtrl = m_ctrl.data();
1260 for (std::size_t h = 0; h < 3; h++, pCtrl += 9) {
1261 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1266 PatchControl *pCtrl = m_ctrl.data();
1267 for (std::size_t h = 0; h < 2; h++, pCtrl += 9) {
1268 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1272 PatchControl *pCtrl = m_ctrl.data() + 9 * 2;
1273 for (std::size_t w = 0; w < 9; w++, pCtrl++) {
1274 pCtrl->m_vertex[0] = vPos[1][0];
1275 pCtrl->m_vertex[1] = vPos[1][1];
1276 pCtrl->m_vertex[2] = vPos[2][2];
1281 PatchControl *pCtrl = m_ctrl.data() + 9;
1282 for (std::size_t h = 0; h < 3; h++, pCtrl += 9) {
1283 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1287 PatchControl *pCtrl = m_ctrl.data();
1288 for (std::size_t w = 0; w < 9; w++, pCtrl++) {
1289 pCtrl->m_vertex[0] = vPos[1][0];
1290 pCtrl->m_vertex[1] = vPos[1][1];
1291 pCtrl->m_vertex[2] = vPos[0][2];
1295 PatchControl *pCtrl = m_ctrl.data() + (9 * 4);
1296 for (std::size_t w = 0; w < 9; w++, pCtrl++) {
1297 pCtrl->m_vertex[0] = vPos[1][0];
1298 pCtrl->m_vertex[1] = vPos[1][1];
1299 pCtrl->m_vertex[2] = vPos[2][2];
1304 ERROR_MESSAGE("this should be unreachable");
1307 } else if (eType == eXactCylinder) {
1308 int n = (width - 1) / 2; // n = number of segments
1309 setDims(width, height);
1311 // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1312 // vPos[1] = aabb.origin;
1313 // vPos[2] = vector3_added(aabb.origin, aabb.extents);
1315 float f = 1 / cos(M_PI / n);
1316 for (std::size_t i = 0; i < width; ++i) {
1317 float angle = (M_PI * i) / n; // 0 to 2pi
1318 float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * cos(angle) * ((i & 1) ? f : 1.0f);
1319 float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle) * ((i & 1) ? f : 1.0f);
1320 for (std::size_t j = 0; j < height; ++j) {
1321 float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float) (height - 1));
1323 v = &m_ctrl.data()[j * width + i];
1329 } else if (eType == eXactCone) {
1330 int n = (width - 1) / 2; // n = number of segments
1331 setDims(width, height);
1333 // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1334 // vPos[1] = aabb.origin;
1335 // vPos[2] = vector3_added(aabb.origin, aabb.extents);
1337 float f = 1 / cos(M_PI / n);
1338 for (std::size_t i = 0; i < width; ++i) {
1339 float angle = (M_PI * i) / n;
1340 for (std::size_t j = 0; j < height; ++j) {
1341 float x = vPos[1][0] + (1.0f - (j / (float) (height - 1))) * (vPos[2][0] - vPos[1][0]) * cos(angle) *
1342 ((i & 1) ? f : 1.0f);
1343 float y = vPos[1][1] + (1.0f - (j / (float) (height - 1))) * (vPos[2][1] - vPos[1][1]) * sin(angle) *
1344 ((i & 1) ? f : 1.0f);
1345 float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float) (height - 1));
1347 v = &m_ctrl.data()[j * width + i];
1353 } else if (eType == eXactSphere) {
1354 int n = (width - 1) / 2; // n = number of segments (yaw)
1355 int m = (height - 1) / 2; // m = number of segments (pitch)
1356 setDims(width, height);
1358 // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1359 // vPos[1] = aabb.origin;
1360 // vPos[2] = vector3_added(aabb.origin, aabb.extents);
1362 float f = 1 / cos(M_PI / n);
1363 float g = 1 / cos(M_PI / (2 * m));
1364 for (std::size_t i = 0; i < width; ++i) {
1365 float angle = (M_PI * i) / n;
1366 for (std::size_t j = 0; j < height; ++j) {
1367 float angle2 = (M_PI * j) / (2 * m);
1368 float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * sin(angle2) * ((j & 1) ? g : 1.0f) * cos(angle) *
1369 ((i & 1) ? f : 1.0f);
1370 float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle2) * ((j & 1) ? g : 1.0f) * sin(angle) *
1371 ((i & 1) ? f : 1.0f);
1372 float z = vPos[1][2] + (vPos[2][2] - vPos[1][2]) * -cos(angle2) * ((j & 1) ? g : 1.0f);
1374 v = &m_ctrl.data()[j * width + i];
1380 } else if (eType == eBevel) {
1381 unsigned char *pIndex;
1382 unsigned char pBevIndex[] =
1391 PatchControl *pCtrl = m_ctrl.data();
1392 for (std::size_t h = 0; h < 3; h++) {
1394 for (std::size_t w = 0; w < 3; w++, pIndex += 2, pCtrl++) {
1395 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1396 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1397 pCtrl->m_vertex[2] = vPos[h][2];
1400 } else if (eType == eEndCap) {
1401 unsigned char *pIndex;
1402 unsigned char pEndIndex[] =
1413 PatchControl *pCtrl = m_ctrl.data();
1414 for (std::size_t h = 0; h < 3; h++) {
1416 for (std::size_t w = 0; w < 5; w++, pIndex += 2, pCtrl++) {
1417 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1418 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1419 pCtrl->m_vertex[2] = vPos[h][2];
1424 if (eType == eDenseCylinder) {
1425 InsertRemove(true, false, true);
1428 if (eType == eVeryDenseCylinder) {
1429 InsertRemove(true, false, false);
1430 InsertRemove(true, false, true);
1436 void Patch::RenderDebug(RenderStateFlags state) const
1438 for (std::size_t i = 0; i < m_tess.m_numStrips; i++) {
1439 glBegin(GL_QUAD_STRIP);
1440 for (std::size_t j = 0; j < m_tess.m_lenStrips; j++) {
1441 glNormal3fv(normal3f_to_array(
1442 (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->normal));
1443 glTexCoord2fv(texcoord2f_to_array(
1444 (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->texcoord));
1445 glVertex3fv(vertex3f_to_array(
1446 (m_tess.m_vertices.data() + m_tess.m_indices[i * m_tess.m_lenStrips + j])->vertex));
1452 void RenderablePatchSolid::RenderNormals() const
1454 const std::size_t width = m_tess.m_numStrips + 1;
1455 const std::size_t height = m_tess.m_lenStrips >> 1;
1457 for (std::size_t i = 0; i < width; i++) {
1458 for (std::size_t j = 0; j < height; j++) {
1462 vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex),
1464 normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->normal), 8)
1467 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex));
1468 glVertex3fv(&vNormal[0]);
1473 vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex),
1475 normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->tangent), 8)
1478 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex));
1479 glVertex3fv(&vNormal[0]);
1484 vertex3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->vertex),
1486 normal3f_to_vector3((m_tess.m_vertices.data() + (j * width + i))->bitangent), 8)
1489 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j * width + i))->vertex));
1490 glVertex3fv(&vNormal[0]);
1497 const int DEGEN_0a = 0x01;
1498 const int DEGEN_1a = 0x02;
1499 const int DEGEN_2a = 0x04;
1500 const int DEGEN_0b = 0x08;
1501 const int DEGEN_1b = 0x10;
1502 const int DEGEN_2b = 0x20;
1503 const int SPLIT = 0x40;
1504 const int AVERAGE = 0x80;
1507 unsigned int subarray_get_degen(PatchControlIter subarray, std::size_t strideU, std::size_t strideV)
1509 unsigned int nDegen = 0;
1510 const PatchControl *p1;
1511 const PatchControl *p2;
1515 if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
1520 if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
1524 p1 = subarray + strideV;
1526 if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
1531 if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
1535 p1 = subarray + (strideV << 1);
1537 if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
1542 if (vector3_equal(p1->m_vertex, p2->m_vertex)) {
1551 deCasteljau3(const Vector3 &P0, const Vector3 &P1, const Vector3 &P2, Vector3 &P01, Vector3 &P12, Vector3 &P012)
1553 P01 = vector3_mid(P0, P1);
1554 P12 = vector3_mid(P1, P2);
1555 P012 = vector3_mid(P01, P12);
1558 inline void BezierInterpolate3(const Vector3 &start, Vector3 &left, Vector3 &mid, Vector3 &right, const Vector3 &end)
1560 left = vector3_mid(start, mid);
1561 right = vector3_mid(mid, end);
1562 mid = vector3_mid(left, right);
1565 inline void BezierInterpolate2(const Vector2 &start, Vector2 &left, Vector2 &mid, Vector2 &right, const Vector2 &end)
1567 left[0] = float_mid(start[0], mid[0]);
1568 left[1] = float_mid(start[1], mid[1]);
1569 right[0] = float_mid(mid[0], end[0]);
1570 right[1] = float_mid(mid[1], end[1]);
1571 mid[0] = float_mid(left[0], right[0]);
1572 mid[1] = float_mid(left[1], right[1]);
1576 inline Vector2 &texcoord_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1578 return reinterpret_cast<Vector2 &>( vertices[index].texcoord );
1581 inline Vector3 &vertex_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1583 return reinterpret_cast<Vector3 &>( vertices[index].vertex );
1586 inline Vector3 &normal_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1588 return reinterpret_cast<Vector3 &>( vertices[index].normal );
1591 inline Vector3 &tangent_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1593 return reinterpret_cast<Vector3 &>( vertices[index].tangent );
1596 inline Vector3 &bitangent_for_index(Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1598 return reinterpret_cast<Vector3 &>( vertices[index].bitangent );
1601 inline const Vector2 &texcoord_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1603 return reinterpret_cast<const Vector2 &>( vertices[index].texcoord );
1606 inline const Vector3 &vertex_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1608 return reinterpret_cast<const Vector3 &>( vertices[index].vertex );
1611 inline const Vector3 &normal_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1613 return reinterpret_cast<const Vector3 &>( vertices[index].normal );
1616 inline const Vector3 &tangent_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1618 return reinterpret_cast<const Vector3 &>( vertices[index].tangent );
1621 inline const Vector3 &bitangent_for_index(const Array<ArbitraryMeshVertex> &vertices, std::size_t index)
1623 return reinterpret_cast<const Vector3 &>( vertices[index].bitangent );
1626 #include "math/curve.h"
1628 inline PatchControl QuadraticBezier_evaluate(const PatchControl *firstPoint, double t)
1630 PatchControl result = {Vector3(0, 0, 0), Vector2(0, 0)};
1631 double denominator = 0;
1634 double weight = BernsteinPolynomial<Zero, Two>::apply(t);
1635 vector3_add(result.m_vertex, vector3_scaled(firstPoint[0].m_vertex, weight));
1636 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[0].m_texcoord, weight));
1637 denominator += weight;
1640 double weight = BernsteinPolynomial<One, Two>::apply(t);
1641 vector3_add(result.m_vertex, vector3_scaled(firstPoint[1].m_vertex, weight));
1642 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[1].m_texcoord, weight));
1643 denominator += weight;
1646 double weight = BernsteinPolynomial<Two, Two>::apply(t);
1647 vector3_add(result.m_vertex, vector3_scaled(firstPoint[2].m_vertex, weight));
1648 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[2].m_texcoord, weight));
1649 denominator += weight;
1652 vector3_divide(result.m_vertex, denominator);
1653 vector2_divide(result.m_texcoord, denominator);
1657 inline Vector3 vector3_linear_interpolated(const Vector3 &a, const Vector3 &b, double t)
1659 return vector3_added(vector3_scaled(a, 1.0 - t), vector3_scaled(b, t));
1662 inline Vector2 vector2_linear_interpolated(const Vector2 &a, const Vector2 &b, double t)
1664 return vector2_added(vector2_scaled(a, 1.0 - t), vector2_scaled(b, t));
1667 void normalise_safe(Vector3 &normal)
1669 if (!vector3_equal(normal, g_vector3_identity)) {
1670 vector3_normalise(normal);
1674 inline void QuadraticBezier_evaluate(const PatchControl &a, const PatchControl &b, const PatchControl &c, double t,
1675 PatchControl &point, PatchControl &left, PatchControl &right)
1677 left.m_vertex = vector3_linear_interpolated(a.m_vertex, b.m_vertex, t);
1678 left.m_texcoord = vector2_linear_interpolated(a.m_texcoord, b.m_texcoord, t);
1679 right.m_vertex = vector3_linear_interpolated(b.m_vertex, c.m_vertex, t);
1680 right.m_texcoord = vector2_linear_interpolated(b.m_texcoord, c.m_texcoord, t);
1681 point.m_vertex = vector3_linear_interpolated(left.m_vertex, right.m_vertex, t);
1682 point.m_texcoord = vector2_linear_interpolated(left.m_texcoord, right.m_texcoord, t);
1685 void Patch::TesselateSubMatrixFixed(ArbitraryMeshVertex *vertices, std::size_t strideX, std::size_t strideY,
1686 unsigned int nFlagsX, unsigned int nFlagsY, PatchControl *subMatrix[3][3])
1688 double incrementU = 1.0 / m_subdivisions_x;
1689 double incrementV = 1.0 / m_subdivisions_y;
1690 const std::size_t width = m_subdivisions_x + 1;
1691 const std::size_t height = m_subdivisions_y + 1;
1693 for (std::size_t i = 0; i != width; ++i) {
1694 double tU = (i + 1 == width) ? 1 : i * incrementU;
1695 PatchControl pointX[3];
1696 PatchControl leftX[3];
1697 PatchControl rightX[3];
1698 QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0],
1700 QuadraticBezier_evaluate(*subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1],
1702 QuadraticBezier_evaluate(*subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2],
1705 ArbitraryMeshVertex *p = vertices + i * strideX;
1706 for (std::size_t j = 0; j != height; ++j) {
1707 if ((j == 0 || j + 1 == height) && (i == 0 || i + 1 == width)) {
1709 double tV = (j + 1 == height) ? 1 : j * incrementV;
1711 PatchControl pointY[3];
1712 PatchControl leftY[3];
1713 PatchControl rightY[3];
1714 QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0],
1716 QuadraticBezier_evaluate(*subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1],
1718 QuadraticBezier_evaluate(*subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2],
1724 QuadraticBezier_evaluate(pointX[0], pointX[1], pointX[2], tV, point, left, right);
1727 QuadraticBezier_evaluate(pointY[0], pointY[1], pointY[2], tU, point, up, down);
1729 vertex3f_to_vector3(p->vertex) = point.m_vertex;
1730 texcoord2f_to_vector2(p->texcoord) = point.m_texcoord;
1732 ArbitraryMeshVertex a, b, c;
1734 a.vertex = vertex3f_for_vector3(left.m_vertex);
1735 a.texcoord = texcoord2f_for_vector2(left.m_texcoord);
1736 b.vertex = vertex3f_for_vector3(right.m_vertex);
1737 b.texcoord = texcoord2f_for_vector2(right.m_texcoord);
1740 c.vertex = vertex3f_for_vector3(up.m_vertex);
1741 c.texcoord = texcoord2f_for_vector2(up.m_texcoord);
1743 c.vertex = vertex3f_for_vector3(down.m_vertex);
1744 c.texcoord = texcoord2f_for_vector2(down.m_texcoord);
1747 Vector3 normal = vector3_normalised(
1748 vector3_cross(right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex));
1750 Vector3 tangent, bitangent;
1751 ArbitraryMeshTriangle_calcTangents(a, b, c, tangent, bitangent);
1752 vector3_normalise(tangent);
1753 vector3_normalise(bitangent);
1755 if (((nFlagsX & AVERAGE) != 0 && i == 0) || ((nFlagsY & AVERAGE) != 0 && j == 0)) {
1756 normal3f_to_vector3(p->normal) = vector3_normalised(
1757 vector3_added(normal3f_to_vector3(p->normal), normal));
1758 normal3f_to_vector3(p->tangent) = vector3_normalised(
1759 vector3_added(normal3f_to_vector3(p->tangent), tangent));
1760 normal3f_to_vector3(p->bitangent) = vector3_normalised(
1761 vector3_added(normal3f_to_vector3(p->bitangent), bitangent));
1763 normal3f_to_vector3(p->normal) = normal;
1764 normal3f_to_vector3(p->tangent) = tangent;
1765 normal3f_to_vector3(p->bitangent) = bitangent;
1774 void Patch::TesselateSubMatrix(const BezierCurveTree *BX, const BezierCurveTree *BY,
1775 std::size_t offStartX, std::size_t offStartY,
1776 std::size_t offEndX, std::size_t offEndY,
1777 std::size_t nFlagsX, std::size_t nFlagsY,
1778 Vector3 &left, Vector3 &mid, Vector3 &right,
1779 Vector2 &texLeft, Vector2 &texMid, Vector2 &texRight,
1782 int newFlagsX, newFlagsY;
1785 Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1;
1787 Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1;
1792 BezierInterpolate2(texcoord_for_index(m_tess.m_vertices, offStartX + offStartY),
1794 texcoord_for_index(m_tess.m_vertices, BX->index + offStartY),
1796 texcoord_for_index(m_tess.m_vertices, offEndX + offStartY));
1799 BezierInterpolate2(texcoord_for_index(m_tess.m_vertices, offStartX + offEndY),
1801 texcoord_for_index(m_tess.m_vertices, BX->index + offEndY),
1803 texcoord_for_index(m_tess.m_vertices, offEndX + offEndY));
1807 BezierInterpolate2(texLeft,
1813 if (!BezierCurveTree_isLeaf(BY)) {
1814 texcoord_for_index(m_tess.m_vertices, BX->index + BY->index) = texTmp;
1818 if (!BezierCurveTree_isLeaf(BX->left)) {
1819 texcoord_for_index(m_tess.m_vertices, BX->left->index + offStartY) = texcoord_0_0;
1820 texcoord_for_index(m_tess.m_vertices, BX->left->index + offEndY) = texcoord_2_0;
1822 if (!BezierCurveTree_isLeaf(BY)) {
1823 texcoord_for_index(m_tess.m_vertices, BX->left->index + BY->index) = texcoord_1_0;
1826 if (!BezierCurveTree_isLeaf(BX->right)) {
1827 texcoord_for_index(m_tess.m_vertices, BX->right->index + offStartY) = texcoord_0_1;
1828 texcoord_for_index(m_tess.m_vertices, BX->right->index + offEndY) = texcoord_2_1;
1830 if (!BezierCurveTree_isLeaf(BY)) {
1831 texcoord_for_index(m_tess.m_vertices, BX->right->index + BY->index) = texcoord_1_1;
1838 BezierInterpolate3(vertex_for_index(m_tess.m_vertices, offStartX + offStartY),
1840 vertex_for_index(m_tess.m_vertices, BX->index + offStartY),
1842 vertex_for_index(m_tess.m_vertices, offEndX + offStartY));
1845 BezierInterpolate3(vertex_for_index(m_tess.m_vertices, offStartX + offEndY),
1847 vertex_for_index(m_tess.m_vertices, BX->index + offEndY),
1849 vertex_for_index(m_tess.m_vertices, offEndX + offEndY));
1854 BezierInterpolate3(left,
1860 if (!BezierCurveTree_isLeaf(BY)) {
1861 vertex_for_index(m_tess.m_vertices, BX->index + BY->index) = tmp;
1865 if (!BezierCurveTree_isLeaf(BX->left)) {
1866 vertex_for_index(m_tess.m_vertices, BX->left->index + offStartY) = vertex_0_0;
1867 vertex_for_index(m_tess.m_vertices, BX->left->index + offEndY) = vertex_2_0;
1869 if (!BezierCurveTree_isLeaf(BY)) {
1870 vertex_for_index(m_tess.m_vertices, BX->left->index + BY->index) = vertex_1_0;
1873 if (!BezierCurveTree_isLeaf(BX->right)) {
1874 vertex_for_index(m_tess.m_vertices, BX->right->index + offStartY) = vertex_0_1;
1875 vertex_for_index(m_tess.m_vertices, BX->right->index + offEndY) = vertex_2_1;
1877 if (!BezierCurveTree_isLeaf(BY)) {
1878 vertex_for_index(m_tess.m_vertices, BX->right->index + BY->index) = vertex_1_1;
1884 if (nFlagsX & SPLIT) {
1885 ArbitraryMeshVertex a, b, c;
1888 if (!(nFlagsX & DEGEN_0a) || !(nFlagsX & DEGEN_0b)) {
1889 tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
1890 a.vertex = vertex3f_for_vector3(vertex_0_0);
1891 a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
1892 c.vertex = vertex3f_for_vector3(vertex_0_1);
1893 c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
1894 } else if (!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b)) {
1895 tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
1896 a.vertex = vertex3f_for_vector3(vertex_1_0);
1897 a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
1898 c.vertex = vertex3f_for_vector3(vertex_1_1);
1899 c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
1901 tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
1902 a.vertex = vertex3f_for_vector3(vertex_2_0);
1903 a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
1904 c.vertex = vertex3f_for_vector3(vertex_2_1);
1905 c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
1910 if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a)) {
1911 tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
1912 b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offEndY].vertex;
1913 b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offEndY].texcoord;
1915 tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
1916 b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offStartY].vertex;
1917 b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord;
1921 Vector3 normal, s, t;
1922 ArbitraryMeshVertex &v = m_tess.m_vertices[offStartY + BX->index];
1923 Vector3 &p = normal3f_to_vector3(v.normal);
1924 Vector3 &ps = normal3f_to_vector3(v.tangent);
1925 Vector3 &pt = normal3f_to_vector3(v.bitangent);
1928 normal = vector3_cross(tangentV, tangentU);
1930 normal = vector3_cross(tangentU, tangentV);
1932 normalise_safe(normal);
1934 ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
1938 if (nFlagsX & AVERAGE) {
1939 p = vector3_normalised(vector3_added(p, normal));
1940 ps = vector3_normalised(vector3_added(ps, s));
1941 pt = vector3_normalised(vector3_added(pt, t));
1950 ArbitraryMeshVertex a, b, c;
1953 if (!(nFlagsX & DEGEN_2a) || !(nFlagsX & DEGEN_2b)) {
1954 tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
1955 a.vertex = vertex3f_for_vector3(vertex_2_0);
1956 a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
1957 c.vertex = vertex3f_for_vector3(vertex_2_1);
1958 c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
1959 } else if (!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b)) {
1960 tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
1961 a.vertex = vertex3f_for_vector3(vertex_1_0);
1962 a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
1963 c.vertex = vertex3f_for_vector3(vertex_1_1);
1964 c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
1966 tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
1967 a.vertex = vertex3f_for_vector3(vertex_0_0);
1968 a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
1969 c.vertex = vertex3f_for_vector3(vertex_0_1);
1970 c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
1975 if ((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b)) {
1976 tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
1977 b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offStartY].vertex;
1978 b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord;
1980 tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
1981 b.vertex = vertex3f_for_vector3(tmp); //m_tess.m_vertices[BX->index + offEndY].vertex;
1982 b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offEndY].texcoord;
1985 ArbitraryMeshVertex &v = m_tess.m_vertices[offEndY + BX->index];
1986 Vector3 &p = normal3f_to_vector3(v.normal);
1987 Vector3 &ps = normal3f_to_vector3(v.tangent);
1988 Vector3 &pt = normal3f_to_vector3(v.bitangent);
1991 p = vector3_cross(tangentV, tangentU);
1993 p = vector3_cross(tangentU, tangentV);
1997 ArbitraryMeshTriangle_calcTangents(a, b, c, ps, pt);
2004 newFlagsX = newFlagsY = 0;
2006 if ((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_0b)) {
2007 newFlagsX |= DEGEN_0a;
2008 newFlagsX |= DEGEN_0b;
2010 if ((nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_1b)) {
2011 newFlagsX |= DEGEN_1a;
2012 newFlagsX |= DEGEN_1b;
2014 if ((nFlagsX & DEGEN_2a) && (nFlagsX & DEGEN_2b)) {
2015 newFlagsX |= DEGEN_2a;
2016 newFlagsX |= DEGEN_2b;
2018 if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a)) {
2019 newFlagsY |= DEGEN_0a;
2020 newFlagsY |= DEGEN_1a;
2021 newFlagsY |= DEGEN_2a;
2023 if ((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b)) {
2024 newFlagsY |= DEGEN_0b;
2025 newFlagsY |= DEGEN_1b;
2026 newFlagsY |= DEGEN_2b;
2030 //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; }
2031 //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; }
2033 newFlagsX |= (nFlagsX & SPLIT);
2034 newFlagsX |= (nFlagsX & AVERAGE);
2036 if (!BezierCurveTree_isLeaf(BY)) {
2038 int nTemp = newFlagsY;
2040 if ((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_0b)) {
2041 newFlagsY |= DEGEN_0a;
2042 newFlagsY |= DEGEN_0b;
2044 newFlagsY |= (nFlagsY & SPLIT);
2045 newFlagsY |= (nFlagsY & AVERAGE);
2047 Vector3 &p = vertex_for_index(m_tess.m_vertices, BX->index + BY->index);
2050 Vector2 &p2 = texcoord_for_index(m_tess.m_vertices, BX->index + BY->index);
2053 TesselateSubMatrix(BY, BX->left,
2054 offStartY, offStartX,
2056 newFlagsY, newFlagsX,
2057 vertex_0_0, vertex_1_0, vertex_2_0,
2058 texcoord_0_0, texcoord_1_0, texcoord_2_0,
2066 if ((nFlagsY & DEGEN_2a) && (nFlagsY & DEGEN_2b)) {
2067 newFlagsY |= DEGEN_2a;
2068 newFlagsY |= DEGEN_2b;
2071 TesselateSubMatrix(BY, BX->right,
2072 offStartY, BX->index,
2074 newFlagsY, newFlagsX,
2075 vertex_0_1, vertex_1_1, vertex_2_1,
2076 texcoord_0_1, texcoord_1_1, texcoord_2_1,
2079 if (!BezierCurveTree_isLeaf(BX->left)) {
2080 TesselateSubMatrix(BX->left, BY,
2081 offStartX, offStartY,
2083 newFlagsX, newFlagsY,
2084 left, vertex_1_0, tmp,
2085 texLeft, texcoord_1_0, texTmp,
2089 if (!BezierCurveTree_isLeaf(BX->right)) {
2090 TesselateSubMatrix(BX->right, BY,
2091 BX->index, offStartY,
2093 newFlagsX, newFlagsY,
2094 tmp, vertex_1_1, right,
2095 texTmp, texcoord_1_1, texRight,
2102 void Patch::BuildTesselationCurves(EMatrixMajor major)
2104 std::size_t nArrayStride, length, cross, strideU, strideV;
2108 length = (m_width - 1) >> 1;
2114 BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU);
2119 nArrayStride = m_tess.m_nArrayWidth;
2120 length = (m_height - 1) >> 1;
2126 BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV);
2131 ERROR_MESSAGE("neither row-major nor column-major");
2135 Array<std::size_t> arrayLength(length);
2136 Array<BezierCurveTree *> pCurveTree(length);
2138 std::size_t nArrayLength = 1;
2141 for (Array<std::size_t>::iterator i = arrayLength.begin(); i != arrayLength.end(); ++i) {
2142 *i = Array<std::size_t>::value_type((major == ROW) ? m_subdivisions_x : m_subdivisions_y);
2146 // create a list of the horizontal control curves in each column of sub-patches
2147 // adaptively tesselate each horizontal control curve in the list
2148 // create a binary tree representing the combined tesselation of the list
2149 for (std::size_t i = 0; i != length; ++i) {
2150 PatchControl *p1 = m_ctrlTransformed.data() + (i * 2 * strideU);
2151 GSList *pCurveList = 0;
2152 for (std::size_t j = 0; j < cross; j += 2) {
2153 PatchControl *p2 = p1 + strideV;
2154 PatchControl *p3 = p2 + strideV;
2156 // directly taken from one row of control points
2158 BezierCurve *pCurve = new BezierCurve;
2159 pCurve->crd = (p1 + strideU)->m_vertex;
2160 pCurve->left = p1->m_vertex;
2161 pCurve->right = (p1 + (strideU << 1))->m_vertex;
2162 pCurveList = g_slist_prepend(pCurveList, pCurve);
2165 if (j + 2 >= cross) {
2169 // interpolated from three columns of control points
2171 BezierCurve *pCurve = new BezierCurve;
2172 pCurve->crd = vector3_mid((p1 + strideU)->m_vertex, (p3 + strideU)->m_vertex);
2173 pCurve->left = vector3_mid(p1->m_vertex, p3->m_vertex);
2174 pCurve->right = vector3_mid((p1 + (strideU << 1))->m_vertex, (p3 + (strideU << 1))->m_vertex);
2176 pCurve->crd = vector3_mid(pCurve->crd, (p2 + strideU)->m_vertex);
2177 pCurve->left = vector3_mid(pCurve->left, p2->m_vertex);
2178 pCurve->right = vector3_mid(pCurve->right, (p2 + (strideU << 1))->m_vertex);
2179 pCurveList = g_slist_prepend(pCurveList, pCurve);
2185 pCurveTree[i] = new BezierCurveTree;
2186 BezierCurveTree_FromCurveList(pCurveTree[i], pCurveList);
2187 for (GSList *l = pCurveList; l != 0; l = g_slist_next(l)) {
2188 delete static_cast<BezierCurve *>((*l).data );
2190 g_slist_free(pCurveList);
2192 // set up array indices for binary tree
2193 // accumulate subarray width
2194 arrayLength[i] = Array<std::size_t>::value_type(
2195 BezierCurveTree_Setup(pCurveTree[i], nArrayLength, nArrayStride) - (nArrayLength - 1));
2196 // accumulate total array width
2197 nArrayLength += arrayLength[i];
2203 m_tess.m_nArrayWidth = nArrayLength;
2204 std::swap(m_tess.m_arrayWidth, arrayLength);
2207 std::swap(m_tess.m_curveTreeU, pCurveTree);
2211 m_tess.m_nArrayHeight = nArrayLength;
2212 std::swap(m_tess.m_arrayHeight, arrayLength);
2215 std::swap(m_tess.m_curveTreeV, pCurveTree);
2221 inline void vertex_assign_ctrl(ArbitraryMeshVertex &vertex, const PatchControl &ctrl)
2223 vertex.vertex = vertex3f_for_vector3(ctrl.m_vertex);
2224 vertex.texcoord = texcoord2f_for_vector2(ctrl.m_texcoord);
2227 inline void vertex_clear_normal(ArbitraryMeshVertex &vertex)
2229 vertex.normal = Normal3f(0, 0, 0);
2230 vertex.tangent = Normal3f(0, 0, 0);
2231 vertex.bitangent = Normal3f(0, 0, 0);
2234 inline void tangents_remove_degenerate(Vector3 tangents[6], Vector2 textureTangents[6], unsigned int flags)
2236 if (flags & DEGEN_0a) {
2237 const std::size_t i =
2239 ? (flags & DEGEN_1a)
2240 ? (flags & DEGEN_1b)
2241 ? (flags & DEGEN_2a)
2247 tangents[0] = tangents[i];
2248 textureTangents[0] = textureTangents[i];
2250 if (flags & DEGEN_0b) {
2251 const std::size_t i =
2253 ? (flags & DEGEN_1b)
2254 ? (flags & DEGEN_1a)
2255 ? (flags & DEGEN_2b)
2261 tangents[1] = tangents[i];
2262 textureTangents[1] = textureTangents[i];
2264 if (flags & DEGEN_2a) {
2265 const std::size_t i =
2267 ? (flags & DEGEN_1a)
2268 ? (flags & DEGEN_1b)
2269 ? (flags & DEGEN_0a)
2275 tangents[4] = tangents[i];
2276 textureTangents[4] = textureTangents[i];
2278 if (flags & DEGEN_2b) {
2279 const std::size_t i =
2281 ? (flags & DEGEN_1b)
2282 ? (flags & DEGEN_1a)
2283 ? (flags & DEGEN_0b)
2289 tangents[5] = tangents[i];
2290 textureTangents[5] = textureTangents[i];
2294 void bestTangents00(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
2296 if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
2297 if (!(degenerateFlags & DEGEN_1a)) { // if this tangent is degenerate we cannot use it
2300 } else if (!(degenerateFlags & DEGEN_0b)) {
2307 } else if (fabs(dot - length) < 0.001) { // same direction = degenerate
2308 if (degenerateFlags & DEGEN_0b) {
2318 void bestTangents01(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
2320 if (fabs(dot - length) < 0.001) { // same direction = degenerate
2321 if (!(degenerateFlags & DEGEN_1a)) { // if this tangent is degenerate we cannot use it
2324 } else if (!(degenerateFlags & DEGEN_2b)) {
2331 } else if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
2332 if (degenerateFlags & DEGEN_2b) {
2342 void bestTangents10(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
2344 if (fabs(dot - length) < 0.001) { // same direction = degenerate
2345 if (!(degenerateFlags & DEGEN_1b)) { // if this tangent is degenerate we cannot use it
2348 } else if (!(degenerateFlags & DEGEN_0a)) {
2355 } else if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
2356 if (degenerateFlags & DEGEN_0a) {
2366 void bestTangents11(unsigned int degenerateFlags, double dot, double length, std::size_t &index0, std::size_t &index1)
2368 if (fabs(dot + length) < 0.001) { // opposing direction = degenerate
2369 if (!(degenerateFlags & DEGEN_1b)) { // if this tangent is degenerate we cannot use it
2372 } else if (!(degenerateFlags & DEGEN_2a)) {
2379 } else if (fabs(dot - length) < 0.001) { // same direction = degenerate
2380 if (degenerateFlags & DEGEN_2a) {
2391 Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6],
2392 Vector2 tangentT[6], std::size_t index0, std::size_t index1)
2395 Vector3 normal(vector3_cross(tangentX[index0], tangentY[index1]));
2396 if (!vector3_equal(normal, g_vector3_identity)) {
2397 vector3_add(normal_for_index(m_tess.m_vertices, index), vector3_normalised(normal));
2402 ArbitraryMeshVertex a, b, c;
2403 a.vertex = Vertex3f(0, 0, 0);
2404 a.texcoord = TexCoord2f(0, 0);
2405 b.vertex = vertex3f_for_vector3(tangentX[index0]);
2406 b.texcoord = texcoord2f_for_vector2(tangentS[index0]);
2407 c.vertex = vertex3f_for_vector3(tangentY[index1]);
2408 c.texcoord = texcoord2f_for_vector2(tangentT[index1]);
2411 ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
2412 if (!vector3_equal(s, g_vector3_identity)) {
2413 vector3_add(tangent_for_index(m_tess.m_vertices, index), vector3_normalised(s));
2415 if (!vector3_equal(t, g_vector3_identity)) {
2416 vector3_add(bitangent_for_index(m_tess.m_vertices, index), vector3_normalised(t));
2421 const std::size_t PATCH_MAX_VERTEX_ARRAY = 1048576;
2423 void Patch::BuildVertexArray()
2425 const std::size_t strideU = 1;
2426 const std::size_t strideV = m_width;
2428 const std::size_t numElems =
2429 m_tess.m_nArrayWidth * m_tess.m_nArrayHeight; // total number of elements in vertex array
2431 const bool bWidthStrips = (m_tess.m_nArrayWidth >=
2432 m_tess.m_nArrayHeight); // decide if horizontal strips are longer than vertical
2435 // allocate vertex, normal, texcoord and primitive-index arrays
2436 m_tess.m_vertices.resize(numElems);
2437 m_tess.m_indices.resize(m_tess.m_nArrayWidth * 2 * (m_tess.m_nArrayHeight - 1));
2439 // set up strip indices
2441 m_tess.m_numStrips = m_tess.m_nArrayHeight - 1;
2442 m_tess.m_lenStrips = m_tess.m_nArrayWidth * 2;
2444 for (std::size_t i = 0; i < m_tess.m_nArrayWidth; i++) {
2445 for (std::size_t j = 0; j < m_tess.m_numStrips; j++) {
2446 m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2] = RenderIndex(j * m_tess.m_nArrayWidth + i);
2447 m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2 + 1] = RenderIndex(
2448 (j + 1) * m_tess.m_nArrayWidth + i);
2449 // reverse because radiant uses CULL_FRONT
2450 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(j*m_tess.m_nArrayWidth+i);
2451 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
2455 m_tess.m_numStrips = m_tess.m_nArrayWidth - 1;
2456 m_tess.m_lenStrips = m_tess.m_nArrayHeight * 2;
2458 for (std::size_t i = 0; i < m_tess.m_nArrayHeight; i++) {
2459 for (std::size_t j = 0; j < m_tess.m_numStrips; j++) {
2460 m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2] = RenderIndex(
2461 ((m_tess.m_nArrayHeight - 1) - i) * m_tess.m_nArrayWidth + j);
2462 m_tess.m_indices[(j * m_tess.m_lenStrips) + i * 2 + 1] = RenderIndex(
2463 ((m_tess.m_nArrayHeight - 1) - i) * m_tess.m_nArrayWidth + j + 1);
2464 // reverse because radiant uses CULL_FRONT
2465 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
2466 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1);
2473 PatchControlIter pCtrl = m_ctrlTransformed.data();
2474 for (std::size_t j = 0, offStartY = 0; j + 1 < m_height; j += 2, pCtrl += (strideU + strideV)) {
2475 // set up array offsets for this sub-patch
2476 const bool leafY = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeV[j >> 1]);
2477 const std::size_t offMidY = (m_patchDef3) ? 0 : m_tess.m_curveTreeV[j >> 1]->index;
2478 const std::size_t widthY = m_tess.m_arrayHeight[j >> 1] * m_tess.m_nArrayWidth;
2479 const std::size_t offEndY = offStartY + widthY;
2481 for (std::size_t i = 0, offStartX = 0; i + 1 < m_width; i += 2, pCtrl += (strideU << 1)) {
2482 const bool leafX = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i >> 1]);
2483 const std::size_t offMidX = (m_patchDef3) ? 0 : m_tess.m_curveTreeU[i >> 1]->index;
2484 const std::size_t widthX = m_tess.m_arrayWidth[i >> 1];
2485 const std::size_t offEndX = offStartX + widthX;
2487 PatchControl *subMatrix[3][3];
2488 subMatrix[0][0] = pCtrl;
2489 subMatrix[0][1] = subMatrix[0][0] + strideU;
2490 subMatrix[0][2] = subMatrix[0][1] + strideU;
2491 subMatrix[1][0] = subMatrix[0][0] + strideV;
2492 subMatrix[1][1] = subMatrix[1][0] + strideU;
2493 subMatrix[1][2] = subMatrix[1][1] + strideU;
2494 subMatrix[2][0] = subMatrix[1][0] + strideV;
2495 subMatrix[2][1] = subMatrix[2][0] + strideU;
2496 subMatrix[2][2] = subMatrix[2][1] + strideU;
2498 // assign on-patch control points to vertex array
2499 if (i == 0 && j == 0) {
2500 vertex_clear_normal(m_tess.m_vertices[offStartX + offStartY]);
2502 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offStartY], *subMatrix[0][0]);
2504 vertex_clear_normal(m_tess.m_vertices[offEndX + offStartY]);
2506 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offStartY], *subMatrix[0][2]);
2508 vertex_clear_normal(m_tess.m_vertices[offStartX + offEndY]);
2510 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offEndY], *subMatrix[2][0]);
2512 vertex_clear_normal(m_tess.m_vertices[offEndX + offEndY]);
2513 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offEndY], *subMatrix[2][2]);
2516 // assign remaining control points to vertex array
2518 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offStartY], *subMatrix[0][1]);
2519 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offEndY], *subMatrix[2][1]);
2522 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offMidY], *subMatrix[1][0]);
2523 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offMidY], *subMatrix[1][2]);
2526 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offMidY], *subMatrix[1][1]);
2531 // test all 12 edges for degeneracy
2532 unsigned int nFlagsX = subarray_get_degen(pCtrl, strideU, strideV);
2533 unsigned int nFlagsY = subarray_get_degen(pCtrl, strideV, strideU);
2534 Vector3 tangentX[6], tangentY[6];
2535 Vector2 tangentS[6], tangentT[6];
2537 // set up tangents for each of the 12 edges if they were not degenerate
2538 if (!(nFlagsX & DEGEN_0a)) {
2539 tangentX[0] = vector3_subtracted(subMatrix[0][1]->m_vertex, subMatrix[0][0]->m_vertex);
2540 tangentS[0] = vector2_subtracted(subMatrix[0][1]->m_texcoord, subMatrix[0][0]->m_texcoord);
2542 if (!(nFlagsX & DEGEN_0b)) {
2543 tangentX[1] = vector3_subtracted(subMatrix[0][2]->m_vertex, subMatrix[0][1]->m_vertex);
2544 tangentS[1] = vector2_subtracted(subMatrix[0][2]->m_texcoord, subMatrix[0][1]->m_texcoord);
2546 if (!(nFlagsX & DEGEN_1a)) {
2547 tangentX[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[1][0]->m_vertex);
2548 tangentS[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[1][0]->m_texcoord);
2550 if (!(nFlagsX & DEGEN_1b)) {
2551 tangentX[3] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[1][1]->m_vertex);
2552 tangentS[3] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[1][1]->m_texcoord);
2554 if (!(nFlagsX & DEGEN_2a)) {
2555 tangentX[4] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[2][0]->m_vertex);
2556 tangentS[4] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[2][0]->m_texcoord);
2558 if (!(nFlagsX & DEGEN_2b)) {
2559 tangentX[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[2][1]->m_vertex);
2560 tangentS[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[2][1]->m_texcoord);
2563 if (!(nFlagsY & DEGEN_0a)) {
2564 tangentY[0] = vector3_subtracted(subMatrix[1][0]->m_vertex, subMatrix[0][0]->m_vertex);
2565 tangentT[0] = vector2_subtracted(subMatrix[1][0]->m_texcoord, subMatrix[0][0]->m_texcoord);
2567 if (!(nFlagsY & DEGEN_0b)) {
2568 tangentY[1] = vector3_subtracted(subMatrix[2][0]->m_vertex, subMatrix[1][0]->m_vertex);
2569 tangentT[1] = vector2_subtracted(subMatrix[2][0]->m_texcoord, subMatrix[1][0]->m_texcoord);
2571 if (!(nFlagsY & DEGEN_1a)) {
2572 tangentY[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[0][1]->m_vertex);
2573 tangentT[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[0][1]->m_texcoord);
2575 if (!(nFlagsY & DEGEN_1b)) {
2576 tangentY[3] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[1][1]->m_vertex);
2577 tangentT[3] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[1][1]->m_texcoord);
2579 if (!(nFlagsY & DEGEN_2a)) {
2580 tangentY[4] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[0][2]->m_vertex);
2581 tangentT[4] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[0][2]->m_texcoord);
2583 if (!(nFlagsY & DEGEN_2b)) {
2584 tangentY[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[1][2]->m_vertex);
2585 tangentT[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[1][2]->m_texcoord);
2588 // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge
2589 tangents_remove_degenerate(tangentX, tangentS, nFlagsX);
2590 tangents_remove_degenerate(tangentY, tangentT, nFlagsY);
2594 std::size_t index = offStartX + offStartY;
2595 std::size_t index0 = 0;
2596 std::size_t index1 = 0;
2598 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2599 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2601 bestTangents00(nFlagsX, dot, length, index0, index1);
2603 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2608 std::size_t index = offEndX + offStartY;
2609 std::size_t index0 = 1;
2610 std::size_t index1 = 4;
2612 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2613 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2615 bestTangents10(nFlagsX, dot, length, index0, index1);
2617 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2622 std::size_t index = offStartX + offEndY;
2623 std::size_t index0 = 4;
2624 std::size_t index1 = 1;
2626 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2627 double length = vector3_length(tangentX[index1]) * vector3_length(tangentY[index1]);
2629 bestTangents01(nFlagsX, dot, length, index0, index1);
2631 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2636 std::size_t index = offEndX + offEndY;
2637 std::size_t index0 = 5;
2638 std::size_t index1 = 5;
2640 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2641 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2643 bestTangents11(nFlagsX, dot, length, index0, index1);
2645 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2648 //normalise normals that won't be accumulated again
2649 if (i != 0 || j != 0) {
2650 normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offStartY));
2651 normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offStartY));
2652 normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offStartY));
2654 if (i + 3 == m_width) {
2655 normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offStartY));
2656 normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offStartY));
2657 normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offStartY));
2659 if (j + 3 == m_height) {
2660 normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offEndY));
2661 normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offEndY));
2662 normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offEndY));
2664 if (i + 3 == m_width && j + 3 == m_height) {
2665 normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offEndY));
2666 normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offEndY));
2667 normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offEndY));
2670 // set flags to average normals between shared edges
2677 // set flags to save evaluating shared edges twice
2681 // if the patch is curved.. tesselate recursively
2682 // use the relevant control curves for this sub-patch
2684 TesselateSubMatrixFixed(m_tess.m_vertices.data() + offStartX + offStartY, 1, m_tess.m_nArrayWidth,
2685 nFlagsX, nFlagsY, subMatrix);
2688 TesselateSubMatrix(m_tess.m_curveTreeU[i >> 1], m_tess.m_curveTreeV[j >> 1],
2689 offStartX, offStartY, offEndX, offEndY, // array offsets
2691 subMatrix[1][0]->m_vertex, subMatrix[1][1]->m_vertex,
2692 subMatrix[1][2]->m_vertex,
2693 subMatrix[1][0]->m_texcoord, subMatrix[1][1]->m_texcoord,
2694 subMatrix[1][2]->m_texcoord,
2696 } else if (!leafY) {
2697 TesselateSubMatrix(m_tess.m_curveTreeV[j >> 1], m_tess.m_curveTreeU[i >> 1],
2698 offStartY, offStartX, offEndY, offEndX, // array offsets
2700 subMatrix[0][1]->m_vertex, subMatrix[1][1]->m_vertex,
2701 subMatrix[2][1]->m_vertex,
2702 subMatrix[0][1]->m_texcoord, subMatrix[1][1]->m_texcoord,
2703 subMatrix[2][1]->m_texcoord,
2708 offStartX = offEndX;
2710 offStartY = offEndY;
2716 class PatchFilterWrapper : public Filter {
2719 PatchFilter &m_filter;
2721 PatchFilterWrapper(PatchFilter &filter, bool invert) : m_invert(invert), m_filter(filter)
2725 void setActive(bool active)
2735 bool filter(const Patch &patch)
2737 return m_invert ^ m_filter.filter(patch);
2742 typedef std::list<PatchFilterWrapper> PatchFilters;
2743 PatchFilters g_patchFilters;
2745 void add_patch_filter(PatchFilter &filter, int mask, bool invert)
2747 g_patchFilters.push_back(PatchFilterWrapper(filter, invert));
2748 GlobalFilterSystem().addFilter(g_patchFilters.back(), mask);
2751 bool patch_filtered(Patch &patch)
2753 for (PatchFilters::iterator i = g_patchFilters.begin(); i != g_patchFilters.end(); ++i) {
2754 if ((*i).active() && (*i).filter(patch)) {