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
24 #include <glib/gslist.h>
25 #include "preferences.h"
26 #include "brush_primit.h"
27 #include "signal/signal.h"
30 Signal0 g_patchTextureChangedCallbacks;
32 void Patch_addTextureChangedCallback(const SignalHandler& handler)
34 g_patchTextureChangedCallbacks.connectLast(handler);
37 void Patch_textureChanged()
39 g_patchTextureChangedCallbacks();
43 Shader* PatchInstance::m_state_selpoint;
44 Shader* Patch::m_state_ctrl;
45 Shader* Patch::m_state_lattice;
46 EPatchType Patch::m_type;
49 std::size_t MAX_PATCH_WIDTH = 0;
50 std::size_t MAX_PATCH_HEIGHT = 0;
52 int g_PatchSubdivideThreshold = 4;
54 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)
68 if(pCurve->left && pCurve->right)
70 index = BezierCurveTree_Setup(pCurve->left, index, stride);
71 pCurve->index = index*stride;
73 index = BezierCurveTree_Setup(pCurve->right, index, stride);
77 pCurve->index = BEZIERCURVETREE_MAX_INDEX;
84 bool BezierCurve_IsCurved(BezierCurve *pCurve)
86 Vector3 vTemp(vector3_subtracted(pCurve->right, pCurve->left));
87 Vector3 v1(vector3_subtracted(pCurve->crd, pCurve->left));
88 Vector3 v2(vector3_subtracted(pCurve->right, pCurve->crd));
90 if(vector3_equal(v1, g_vector3_identity) || vector3_equal(vTemp, v1)) // return 0 if 1->2 == 0 or 1->2 == 1->3
93 vector3_normalise(v1);
94 vector3_normalise(v2);
95 if(vector3_equal(v1, v2))
99 const double width = vector3_length(v3);
100 vector3_scale(v3, 1.0 / width);
102 if(vector3_equal(v1, v3) && vector3_equal(v2, v3))
105 const double angle = acos(vector3_dot(v1, v2)) / c_pi;
107 const double index = width * angle;
109 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 void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, GSList *pCurveList)
123 GSList *pLeftList = 0;
124 GSList *pRightList = 0;
125 BezierCurve *pCurve, *pLeftCurve, *pRightCurve;
128 for (GSList *l = pCurveList; l; l = l->next)
130 pCurve = (BezierCurve *)(l->data);
131 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)
151 pTree->left = new BezierCurveTree;
152 pTree->right = new BezierCurveTree;
153 BezierCurveTree_FromCurveList(pTree->left, pLeftList);
154 BezierCurveTree_FromCurveList(pTree->right, pRightList);
158 for (l = pLeftList; l != 0; l = g_slist_next(l))
159 delete (BezierCurve*)l->data;
161 for (l = pRightList; l != 0; l = g_slist_next(l))
162 delete (BezierCurve*)l->data;
165 g_slist_free(pLeftList);
166 g_slist_free(pRightList);
176 int Patch::m_CycleCapIndex = 0;
179 void Patch::setDims (std::size_t w, std::size_t h)
183 ASSERT_MESSAGE(w <= MAX_PATCH_WIDTH, "patch too wide");
184 if(w > MAX_PATCH_WIDTH)
186 else if(w < MIN_PATCH_WIDTH)
191 ASSERT_MESSAGE(h <= MAX_PATCH_HEIGHT, "patch too tall");
192 if(h > MAX_PATCH_HEIGHT)
193 h = MAX_PATCH_HEIGHT;
194 else if(h < MIN_PATCH_HEIGHT)
195 h = MIN_PATCH_HEIGHT;
197 m_width = w; m_height = h;
199 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 void Patch::UpdateCachedData()
213 if(!m_width || !m_height)
215 BuildTesselationCurves(ROW);
216 BuildTesselationCurves(COL);
220 IndexBuffer ctrl_indices;
222 m_ctrl_vertices.clear();
223 m_lattice_indices.clear();
225 m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
226 ctrl_indices.reserve(m_ctrlTransformed.size());
228 UniqueVertexBuffer<PointVertex> inserter(m_ctrl_vertices);
229 for(iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
231 ctrl_indices.insert(inserter.insert(pointvertex_quantised(PointVertex(reinterpret_cast<const Vertex3f&>((*i).m_vertex), colour_for_index(i - m_ctrlTransformed.begin(), m_width)))));
235 for(IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i)
237 if(std::size_t(i - ctrl_indices.begin()) % m_width)
239 m_lattice_indices.insert(*(i - 1));
240 m_lattice_indices.insert(*i);
242 if(std::size_t(i - ctrl_indices.begin()) >= m_width)
244 m_lattice_indices.insert(*(i - m_width));
245 m_lattice_indices.insert(*i);
252 Array<RenderIndex>::iterator first = m_tess.m_indices.begin();
253 for(std::size_t s=0; s<m_tess.m_numStrips; s++)
255 Array<RenderIndex>::iterator last = first + m_tess.m_lenStrips;
257 for(Array<RenderIndex>::iterator i(first); i+2 != last; i += 2)
259 ArbitraryMeshTriangle_sumTangents(m_tess.m_vertices[*(i+0)], m_tess.m_vertices[*(i+1)], m_tess.m_vertices[*(i+2)]);
260 ArbitraryMeshTriangle_sumTangents(m_tess.m_vertices[*(i+2)], m_tess.m_vertices[*(i+1)], m_tess.m_vertices[*(i+3)]);
266 for(Array<ArbitraryMeshVertex>::iterator i = m_tess.m_vertices.begin(); i != m_tess.m_vertices.end(); ++i)
268 vector3_normalise(reinterpret_cast<Vector3&>((*i).tangent));
269 vector3_normalise(reinterpret_cast<Vector3&>((*i).bitangent));
277 void Patch::InvertMatrix()
281 PatchControlArray_invert(m_ctrl, m_width, m_height);
283 controlPointsChanged();
286 void Patch::TransposeMatrix()
291 Array<PatchControl> tmp(m_width * m_height);
292 copy_ctrl(tmp.data(), m_ctrl.data(), m_ctrl.data() + m_width * m_height);
294 PatchControlIter from = tmp.data();
295 for(std::size_t h = 0; h != m_height; ++h)
297 PatchControlIter to = m_ctrl.data() + h;
298 for(std::size_t w = 0; w != m_width; ++w, ++from, to += m_height)
306 std::size_t tmp = m_width;
311 controlPointsChanged();
314 void Patch::Redisperse(EMatrixMajor mt)
316 std::size_t w, h, width, height, row_stride, col_stride;
317 PatchControl* p1, * p2, * p3;
324 width = (m_width-1)>>1;
327 row_stride = m_width;
330 width = (m_height-1)>>1;
332 col_stride = m_width;
336 ERROR_MESSAGE("neither row-major nor column-major");
340 for(h=0;h<height;h++)
342 p1 = m_ctrl.data()+(h*row_stride);
347 p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
352 controlPointsChanged();
355 void Patch::InsertRemove(bool bInsert, bool bColumn, bool bFirst)
361 if(bColumn && (m_width + 2 <= MAX_PATCH_WIDTH))
362 InsertPoints(COL, bFirst);
363 else if(m_height + 2 <= MAX_PATCH_HEIGHT)
364 InsertPoints(ROW, bFirst);
368 if(bColumn && (m_width - 2 >= MIN_PATCH_WIDTH))
369 RemovePoints(COL, bFirst);
370 else if(m_height - 2 >= MIN_PATCH_HEIGHT)
371 RemovePoints(ROW, bFirst);
374 controlPointsChanged();
377 Patch* Patch::MakeCap(Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst)
379 std::size_t i, width, height;
392 ERROR_MESSAGE("neither row-major nor column-major");
396 Array<Vector3> p(width);
398 std::size_t nIndex = (bFirst) ? 0 : height-1;
401 for (i=0; i<width; i++)
403 p[(bFirst)?i:(width-1)-i] = ctrlAt(nIndex, i).m_vertex;
408 for (i=0; i<width; i++)
410 p[(bFirst)?i:(width-1)-i] = ctrlAt(i, nIndex).m_vertex;
414 patch->ConstructSeam(eType, p.data(), width);
418 void Patch::FlipTexture(int nAxis)
422 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
424 (*i).m_texcoord[nAxis] = -(*i).m_texcoord[nAxis];
427 controlPointsChanged();
430 void Patch::TranslateTexture(float s, float t)
434 s = -1 * s / m_state->getTexture().width;
435 t = t / m_state->getTexture().height;
437 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
439 (*i).m_texcoord[0] += s;
440 (*i).m_texcoord[1] += t;
443 controlPointsChanged();
446 void Patch::ScaleTexture(float s, float t)
450 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
452 (*i).m_texcoord[0] *= s;
453 (*i).m_texcoord[1] *= t;
456 controlPointsChanged();
459 void Patch::RotateTexture(float angle)
463 const float s = static_cast<float>(sin(degrees_to_radians(angle)));
464 const float c = static_cast<float>(cos(degrees_to_radians(angle)));
466 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
468 const float x = (*i).m_texcoord[0];
469 const float y = (*i).m_texcoord[1];
470 (*i).m_texcoord[0] = (x * c) - (y * s);
471 (*i).m_texcoord[1] = (y * c) + (x * s);
474 controlPointsChanged();
478 void Patch::SetTextureRepeat(float s, float t)
481 float si, ti, sc, tc;
486 si = s / (float)(m_width - 1);
487 ti = t / (float)(m_height - 1);
489 pDest = m_ctrl.data();
490 for (h=0, tc = 0.0f; h<m_height; h++, tc+=ti)
492 for (w=0, sc = 0.0f; w<m_width; w++, sc+=si)
494 pDest->m_texcoord[0] = sc;
495 pDest->m_texcoord[1] = tc;
500 controlPointsChanged();
504 void Patch::SetTextureInfo(texdef_t *pt)
506 if(pt->getShift()[0] || pt->getShift()[1])
507 TranslateTexture (pt->getShift()[0], pt->getShift()[1]);
508 else if(pt->getScale()[0] || pt->getScale()[1])
510 if(pt->getScale()[0] == 0.0f) pt->setScale(0, 1.0f);
511 if(pt->getScale()[1] == 0.0f) pt->setScale(1, 1.0f);
512 ScaleTexture (pt->getScale()[0], pt->getScale()[1]);
515 RotateTexture (pt->rotate);
519 inline int texture_axis(const Vector3& normal)
521 // axis dominance order: Z, X, Y
522 return (normal.x() >= normal.y()) ? (normal.x() > normal.z()) ? 0 : 2 : (normal.y() > normal.z()) ? 1 : 2;
525 void Patch::CapTexture()
527 const PatchControl& p1 = m_ctrl[m_width];
528 const PatchControl& p2 = m_ctrl[m_width*(m_height-1)];
529 const PatchControl& p3 = m_ctrl[(m_width*m_height)-1];
532 Vector3 normal(g_vector3_identity);
535 Vector3 tmp(vector3_cross(
536 vector3_subtracted(p2.m_vertex, m_ctrl[0].m_vertex),
537 vector3_subtracted(p3.m_vertex, m_ctrl[0].m_vertex)
539 if(!vector3_equal(tmp, g_vector3_identity))
541 vector3_add(normal, tmp);
545 Vector3 tmp(vector3_cross(
546 vector3_subtracted(p1.m_vertex, p3.m_vertex),
547 vector3_subtracted(m_ctrl[0].m_vertex, p3.m_vertex)
549 if(!vector3_equal(tmp, g_vector3_identity))
551 vector3_add(normal, tmp);
555 ProjectTexture(texture_axis(normal));
558 // uses longest parallel chord to calculate texture coords for each row/col
559 void Patch::NaturalTexture()
564 float fSize = (float)m_state->getTexture().width * Texdef_getDefaultTextureScale();
568 PatchControl* pWidth = m_ctrl.data();
569 for (std::size_t w=0; w<m_width; w++, pWidth++)
572 PatchControl* pHeight = pWidth;
573 for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
574 pHeight->m_texcoord[0] = static_cast<float>(tex);
581 PatchControl* pHeight = pWidth;
582 for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
584 Vector3 v(vector3_subtracted(pHeight->m_vertex, (pHeight+1)->m_vertex));
585 double length = tex + (vector3_length(v) / fSize);
586 if(fabs(length) > texBest) texBest = length;
595 float fSize = -(float)m_state->getTexture().height * Texdef_getDefaultTextureScale();
599 PatchControl* pHeight = m_ctrl.data();
600 for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
603 PatchControl* pWidth = pHeight;
604 for (std::size_t w=0; w<m_width; w++, pWidth++)
605 pWidth->m_texcoord[1] = static_cast<float>(tex);
612 PatchControl* pWidth = pHeight;
613 for (std::size_t w=0; w<m_width; w++, pWidth++)
615 Vector3 v(vector3_subtracted(pWidth->m_vertex, (pWidth+m_width)->m_vertex));
616 double length = tex + (vector3_length(v) / fSize);
617 if(fabs(length) > texBest) texBest = length;
625 controlPointsChanged();
632 void Patch::AccumulateBBox()
634 m_aabb_local = AABB();
636 for(PatchControlArray::iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
638 aabb_extend_by_point_safe(m_aabb_local, (*i).m_vertex);
645 void Patch::InsertPoints(EMatrixMajor mt, bool bFirst)
647 std::size_t width, height, row_stride, col_stride;
653 row_stride = m_width;
658 col_stride = m_width;
664 ERROR_MESSAGE("neither row-major nor column-major");
670 PatchControl* p1 = m_ctrl.data();
671 for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
674 PatchControl* p2 = p1;
675 for(std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride)
677 if(0)//p2->m_selectable.isSelected())
690 PatchControl* p2 = p1;
691 for(std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride)
693 if(0)//p2->m_selectable.isSelected())
707 Array<PatchControl> tmp(m_ctrl);
709 std::size_t row_stride2, col_stride2;
713 setDims(m_width, m_height+2);
715 row_stride2 = m_width;
718 setDims(m_width+2, m_height);
719 col_stride2 = m_width;
723 ERROR_MESSAGE("neither row-major nor column-major");
748 for(std::size_t w = 0; w != width; ++w)
750 PatchControl* p1 = tmp.data() + (w*col_stride);
751 PatchControl* p2 = m_ctrl.data() + (w*col_stride2);
752 for(std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride)
756 p2 += 2 * row_stride2;
761 p1 = tmp.data() + (w*col_stride+pos*row_stride);
762 p2 = m_ctrl.data() + (w*col_stride2+pos*row_stride2);
764 PatchControl* r2a = (p2+row_stride2);
765 PatchControl* r2b = (p2-row_stride2);
766 PatchControl* c2a = (p1-2*row_stride);
767 PatchControl* c2b = (p1-row_stride);
769 // set two new row points
770 *(p2+2*row_stride2) = *p1;
773 for(std::size_t i = 0; i != 3; ++i)
775 r2a->m_vertex[i] = float_mid(c2b->m_vertex[i], p1->m_vertex[i]);
777 r2b->m_vertex[i] = float_mid(c2a->m_vertex[i], c2b->m_vertex[i]);
779 p2->m_vertex[i] = float_mid(r2a->m_vertex[i], r2b->m_vertex[i]);
781 for(std::size_t i = 0; i != 2; ++i)
783 r2a->m_texcoord[i] = float_mid(c2b->m_texcoord[i], p1->m_texcoord[i]);
785 r2b->m_texcoord[i] = float_mid(c2a->m_texcoord[i], c2b->m_texcoord[i]);
787 p2->m_texcoord[i] = float_mid(r2a->m_texcoord[i], r2b->m_texcoord[i]);
792 void Patch::RemovePoints(EMatrixMajor mt, bool bFirst)
794 std::size_t width, height, row_stride, col_stride;
800 row_stride = m_width;
805 col_stride = m_width;
811 ERROR_MESSAGE("neither row-major nor column-major");
817 PatchControl* p1 = m_ctrl.data();
818 for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
821 PatchControl* p2 = p1;
822 for(std::size_t h=1; h < height; h += 2, p2 += 2 * row_stride)
824 if(0)//p2->m_selectable.isSelected())
837 PatchControl* p2 = p1;
838 for(std::size_t h=0; h < height; h += 2, p2 += 2 * row_stride)
840 if(0)//p2->m_selectable.isSelected())
854 Array<PatchControl> tmp(m_ctrl);
856 std::size_t row_stride2, col_stride2;
860 setDims(m_width, m_height-2);
862 row_stride2 = m_width;
865 setDims(m_width-2, m_height);
866 col_stride2 = m_width;
870 ERROR_MESSAGE("neither row-major nor column-major");
889 else if(pos > height - 3)
898 for(std::size_t w = 0; w != width; w++)
900 PatchControl* p1 = tmp.data() + (w*col_stride);
901 PatchControl* p2 = m_ctrl.data() + (w*col_stride2);
902 for(std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride)
906 p1 += 2 * row_stride2; h += 2;
911 p1 = tmp.data() + (w*col_stride+pos*row_stride);
912 p2 = m_ctrl.data() + (w*col_stride2+pos*row_stride2);
914 for(std::size_t i=0; i<3; i++)
916 (p2-row_stride2)->m_vertex[i] = ((p1+2*row_stride)->m_vertex[i]+(p1-2*row_stride)->m_vertex[i]) * 0.5f;
918 (p2-row_stride2)->m_vertex[i] = (p2-row_stride2)->m_vertex[i]+(2.0f * ((p1)->m_vertex[i]-(p2-row_stride2)->m_vertex[i]));
920 for(std::size_t i=0; i<2; i++)
922 (p2-row_stride2)->m_texcoord[i] = ((p1+2*row_stride)->m_texcoord[i]+(p1-2*row_stride)->m_texcoord[i]) * 0.5f;
924 (p2-row_stride2)->m_texcoord[i] = (p2-row_stride2)->m_texcoord[i]+(2.0f * ((p1)->m_texcoord[i]-(p2-row_stride2)->m_texcoord[i]));
929 void Patch::ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width)
936 m_ctrl[0].m_vertex = p[0];
937 m_ctrl[1].m_vertex = p[1];
938 m_ctrl[2].m_vertex = p[1];
939 m_ctrl[3].m_vertex = p[1];
940 m_ctrl[4].m_vertex = p[1];
941 m_ctrl[5].m_vertex = p[1];
942 m_ctrl[6].m_vertex = p[2];
943 m_ctrl[7].m_vertex = p[1];
944 m_ctrl[8].m_vertex = p[1];
950 Vector3 p3(vector3_added(p[2], vector3_subtracted(p[0], p[1])));
951 m_ctrl[0].m_vertex = p3;
952 m_ctrl[1].m_vertex = p3;
953 m_ctrl[2].m_vertex = p[2];
954 m_ctrl[3].m_vertex = p3;
955 m_ctrl[4].m_vertex = p3;
956 m_ctrl[5].m_vertex = p[1];
957 m_ctrl[6].m_vertex = p3;
958 m_ctrl[7].m_vertex = p3;
959 m_ctrl[8].m_vertex = p[0];
964 Vector3 p5(vector3_mid(p[0], p[4]));
967 m_ctrl[0].m_vertex = p[0];
968 m_ctrl[1].m_vertex = p5;
969 m_ctrl[2].m_vertex = p[4];
970 m_ctrl[3].m_vertex = p[1];
971 m_ctrl[4].m_vertex = p[2];
972 m_ctrl[5].m_vertex = p[3];
973 m_ctrl[6].m_vertex = p[2];
974 m_ctrl[7].m_vertex = p[2];
975 m_ctrl[8].m_vertex = p[2];
981 m_ctrl[0].m_vertex = p[4];
982 m_ctrl[1].m_vertex = p[3];
983 m_ctrl[2].m_vertex = p[2];
984 m_ctrl[3].m_vertex = p[1];
985 m_ctrl[4].m_vertex = p[0];
986 m_ctrl[5].m_vertex = p[3];
987 m_ctrl[6].m_vertex = p[3];
988 m_ctrl[7].m_vertex = p[2];
989 m_ctrl[8].m_vertex = p[1];
990 m_ctrl[9].m_vertex = p[1];
991 m_ctrl[10].m_vertex = p[3];
992 m_ctrl[11].m_vertex = p[3];
993 m_ctrl[12].m_vertex = p[2];
994 m_ctrl[13].m_vertex = p[1];
995 m_ctrl[14].m_vertex = p[1];
1000 std::size_t mid = (width - 1) >> 1;
1002 bool degenerate = (mid % 2) != 0;
1004 std::size_t newHeight = mid + (degenerate ? 2 : 1);
1006 setDims(3, newHeight);
1011 for(std::size_t i = width; i != width + 2; ++i)
1013 p[i] = p[width - 1];
1018 PatchControl* pCtrl = m_ctrl.data();
1019 for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
1021 pCtrl->m_vertex = p[i];
1025 PatchControl* pCtrl = m_ctrl.data() + 2;
1026 std::size_t h = m_height - 1;
1027 for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
1029 pCtrl->m_vertex = p[h + (h - i)];
1037 ERROR_MESSAGE("invalid patch-cap type");
1041 controlPointsChanged();
1044 void Patch::ProjectTexture(int nAxis)
1065 ERROR_MESSAGE("invalid axis");
1069 float fWidth = 1 / (m_state->getTexture().width * Texdef_getDefaultTextureScale());
1070 float fHeight = 1 / (m_state->getTexture().height * -Texdef_getDefaultTextureScale());
1072 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
1074 (*i).m_texcoord[0] = (*i).m_vertex[s] * fWidth;
1075 (*i).m_texcoord[1] = (*i).m_vertex[t] * fHeight;
1078 controlPointsChanged();
1081 void Patch::constructPlane(const AABB& aabb, int axis, std::size_t width, std::size_t height)
1083 setDims(width, height);
1088 case 2: x=0; y=1; z=2; break;
1089 case 1: x=0; y=2; z=1; break;
1090 case 0: x=1; y=2; z=0; break;
1092 ERROR_MESSAGE("invalid view-type");
1096 if(m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH) m_width = 3;
1097 if(m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT) m_height = 3;
1100 vStart[x] = aabb.origin[x] - aabb.extents[x];
1101 vStart[y] = aabb.origin[y] - aabb.extents[y];
1102 vStart[z] = aabb.origin[z];
1104 float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float)(m_width - 1));
1105 float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float)(m_height - 1));
1108 vTmp[z] = vStart[z];
1109 PatchControl* pCtrl = m_ctrl.data();
1112 for (std::size_t h=0; h<m_height; h++)
1115 for (std::size_t w=0; w<m_width; w++, ++pCtrl)
1117 pCtrl->m_vertex = vTmp;
1126 void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height)
1132 vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1133 vPos[1] = aabb.origin;
1134 vPos[2] = vector3_added(aabb.origin, aabb.extents);
1139 constructPlane(aabb, axis, width, height);
1141 else if(eType == eSqCylinder
1142 || eType == eCylinder
1143 || eType == eDenseCylinder
1144 || eType == eVeryDenseCylinder
1146 || eType == eSphere)
1148 unsigned char *pIndex;
1149 unsigned char pCylIndex[] =
1163 PatchControl *pStart;
1166 case eSqCylinder: setDims(9, 3);
1167 pStart = m_ctrl.data();
1169 case eDenseCylinder:
1170 case eVeryDenseCylinder:
1173 pStart = m_ctrl.data() + 1;
1175 case eCone: setDims(9, 3);
1176 pStart = m_ctrl.data() + 1;
1180 pStart = m_ctrl.data() + (9+1);
1183 ERROR_MESSAGE("this should be unreachable");
1187 for(std::size_t h=0; h<3; h++, pStart+=9)
1190 PatchControl* pCtrl = pStart;
1191 for(std::size_t w=0; w<8; w++, pCtrl++)
1193 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1194 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1195 pCtrl->m_vertex[2] = vPos[h][2];
1204 PatchControl* pCtrl=m_ctrl.data();
1205 for(std::size_t h=0; h<3; h++, pCtrl+=9)
1207 pCtrl[8].m_vertex = pCtrl[0].m_vertex;
1211 case eDenseCylinder:
1212 case eVeryDenseCylinder:
1215 PatchControl* pCtrl=m_ctrl.data();
1216 for (std::size_t h=0; h<3; h++, pCtrl+=9)
1218 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1224 PatchControl* pCtrl=m_ctrl.data();
1225 for (std::size_t h=0; h<2; h++, pCtrl+=9)
1227 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1231 PatchControl* pCtrl=m_ctrl.data()+9*2;
1232 for (std::size_t w=0; w<9; w++, pCtrl++)
1234 pCtrl->m_vertex[0] = vPos[1][0];
1235 pCtrl->m_vertex[1] = vPos[1][1];
1236 pCtrl->m_vertex[2] = vPos[2][2];
1242 PatchControl* pCtrl=m_ctrl.data()+9;
1243 for (std::size_t h=0; h<3; h++, pCtrl+=9)
1245 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1249 PatchControl* pCtrl = m_ctrl.data();
1250 for (std::size_t w=0; w<9; w++, pCtrl++)
1252 pCtrl->m_vertex[0] = vPos[1][0];
1253 pCtrl->m_vertex[1] = vPos[1][1];
1254 pCtrl->m_vertex[2] = vPos[2][2];
1258 PatchControl* pCtrl = m_ctrl.data()+(9*4);
1259 for (std::size_t w=0; w<9; w++, pCtrl++)
1261 pCtrl->m_vertex[0] = vPos[1][0];
1262 pCtrl->m_vertex[1] = vPos[1][1];
1263 pCtrl->m_vertex[2] = vPos[2][2];
1267 ERROR_MESSAGE("this should be unreachable");
1271 else if (eType == eBevel)
1273 unsigned char *pIndex;
1274 unsigned char pBevIndex[] =
1283 PatchControl* pCtrl = m_ctrl.data();
1284 for(std::size_t h=0; h<3; h++)
1287 for(std::size_t w=0; w<3; w++, pIndex+=2, pCtrl++)
1289 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1290 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1291 pCtrl->m_vertex[2] = vPos[h][2];
1295 else if(eType == eEndCap)
1297 unsigned char *pIndex;
1298 unsigned char pEndIndex[] =
1309 PatchControl* pCtrl = m_ctrl.data();
1310 for(std::size_t h=0; h<3; h++)
1313 for(std::size_t w=0; w<5; w++, pIndex+=2, pCtrl++)
1315 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1316 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1317 pCtrl->m_vertex[2] = vPos[h][2];
1322 if(eType == eDenseCylinder)
1324 InsertRemove(true, false, true);
1327 if(eType == eVeryDenseCylinder)
1329 InsertRemove(true, false, false);
1330 InsertRemove(true, false, true);
1336 void Patch::RenderDebug(RenderStateFlags state) const
1338 for (std::size_t i = 0; i<m_tess.m_numStrips; i++)
1340 glBegin(GL_QUAD_STRIP);
1341 for (std::size_t j = 0; j<m_tess.m_lenStrips; j++)
1343 glNormal3fv(normal3f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->normal));
1344 glTexCoord2fv(texcoord2f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->texcoord));
1345 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->vertex));
1351 void RenderablePatchSolid::RenderNormals() const
1353 const std::size_t width = m_tess.m_numStrips+1;
1354 const std::size_t height = m_tess.m_lenStrips>>1;
1356 for(std::size_t i=0;i<width;i++)
1358 for(std::size_t j=0;j<height;j++)
1363 vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
1364 vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->normal), 8)
1367 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
1368 glVertex3fv(&vNormal[0]);
1373 vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
1374 vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->tangent), 8)
1377 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
1378 glVertex3fv(&vNormal[0]);
1383 vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
1384 vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->bitangent), 8)
1387 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
1388 glVertex3fv(&vNormal[0]);
1395 #define DEGEN_0a 0x01
1396 #define DEGEN_1a 0x02
1397 #define DEGEN_2a 0x04
1398 #define DEGEN_0b 0x08
1399 #define DEGEN_1b 0x10
1400 #define DEGEN_2b 0x20
1402 #define AVERAGE 0x80
1405 unsigned int subarray_get_degen(PatchControlIter subarray, std::size_t strideU, std::size_t strideV)
1407 unsigned int nDegen = 0;
1408 const PatchControl* p1;
1409 const PatchControl* p2;
1413 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1417 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1420 p1 = subarray + strideV;
1422 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1426 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1429 p1 = subarray + (strideV << 1);
1431 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1435 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1442 inline void deCasteljau3(const Vector3& P0, const Vector3& P1, const Vector3& P2, Vector3& P01, Vector3& P12, Vector3& P012)
1444 P01 = vector3_mid(P0, P1);
1445 P12 = vector3_mid(P1, P2);
1446 P012 = vector3_mid(P01, P12);
1449 inline void BezierInterpolate3( const Vector3& start, Vector3& left, Vector3& mid, Vector3& right, const Vector3& end )
1451 left = vector3_mid(start, mid);
1452 right = vector3_mid(mid, end);
1453 mid = vector3_mid(left, right);
1456 inline void BezierInterpolate2( const Vector2& start, Vector2& left, Vector2& mid, Vector2& right, const Vector2& end )
1458 left[0]= float_mid(start[0], mid[0]);
1459 left[1] = float_mid(start[1], mid[1]);
1460 right[0] = float_mid(mid[0], end[0]);
1461 right[1] = float_mid(mid[1], end[1]);
1462 mid[0] = float_mid(left[0], right[0]);
1463 mid[1] = float_mid(left[1], right[1]);
1467 inline Vector2& texcoord_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1469 return reinterpret_cast<Vector2&>(vertices[index].texcoord);
1472 inline Vector3& vertex_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1474 return reinterpret_cast<Vector3&>(vertices[index].vertex);
1477 inline Vector3& normal_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1479 return reinterpret_cast<Vector3&>(vertices[index].normal);
1482 inline Vector3& tangent_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1484 return reinterpret_cast<Vector3&>(vertices[index].tangent);
1487 inline Vector3& bitangent_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1489 return reinterpret_cast<Vector3&>(vertices[index].bitangent);
1492 inline const Vector2& texcoord_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1494 return reinterpret_cast<const Vector2&>(vertices[index].texcoord);
1497 inline const Vector3& vertex_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1499 return reinterpret_cast<const Vector3&>(vertices[index].vertex);
1502 inline const Vector3& normal_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1504 return reinterpret_cast<const Vector3&>(vertices[index].normal);
1507 inline const Vector3& tangent_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1509 return reinterpret_cast<const Vector3&>(vertices[index].tangent);
1512 inline const Vector3& bitangent_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1514 return reinterpret_cast<const Vector3&>(vertices[index].bitangent);
1517 #include "math/curve.h"
1519 inline PatchControl QuadraticBezier_evaluate(const PatchControl* firstPoint, double t)
1521 PatchControl result = { Vector3(0, 0, 0), Vector2(0, 0) };
1522 double denominator = 0;
1525 double weight = BernsteinPolynomial<Zero, Two>::apply(t);
1526 vector3_add(result.m_vertex, vector3_scaled(firstPoint[0].m_vertex, weight));
1527 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[0].m_texcoord, weight));
1528 denominator += weight;
1531 double weight = BernsteinPolynomial<One, Two>::apply(t);
1532 vector3_add(result.m_vertex, vector3_scaled(firstPoint[1].m_vertex, weight));
1533 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[1].m_texcoord, weight));
1534 denominator += weight;
1537 double weight = BernsteinPolynomial<Two, Two>::apply(t);
1538 vector3_add(result.m_vertex, vector3_scaled(firstPoint[2].m_vertex, weight));
1539 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[2].m_texcoord, weight));
1540 denominator += weight;
1543 vector3_divide(result.m_vertex, denominator);
1544 vector2_divide(result.m_texcoord, denominator);
1548 inline Vector3 vector3_linear_interpolated(const Vector3& a, const Vector3& b, double t)
1550 return vector3_added(vector3_scaled(a, 1.0 - t), vector3_scaled(b, t));
1553 inline Vector2 vector2_linear_interpolated(const Vector2& a, const Vector2& b, double t)
1555 return vector2_added(vector2_scaled(a, 1.0 - t), vector2_scaled(b, t));
1558 void normalise_safe(Vector3& normal)
1560 if(!vector3_equal(normal, g_vector3_identity))
1562 vector3_normalise(normal);
1566 inline void QuadraticBezier_evaluate(const PatchControl& a, const PatchControl& b, const PatchControl& c, double t, PatchControl& point, PatchControl& left, PatchControl& right)
1568 left.m_vertex = vector3_linear_interpolated(a.m_vertex, b.m_vertex, t);
1569 left.m_texcoord = vector2_linear_interpolated(a.m_texcoord, b.m_texcoord, t);
1570 right.m_vertex = vector3_linear_interpolated(b.m_vertex, c.m_vertex, t);
1571 right.m_texcoord = vector2_linear_interpolated(b.m_texcoord, c.m_texcoord, t);
1572 point.m_vertex = vector3_linear_interpolated(left.m_vertex, right.m_vertex, t);
1573 point.m_texcoord = vector2_linear_interpolated(left.m_texcoord, right.m_texcoord, t);
1576 void Patch::TesselateSubMatrixFixed(ArbitraryMeshVertex* vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl* subMatrix[3][3])
1578 double incrementU = 1.0 / m_subdivisions_x;
1579 double incrementV = 1.0 / m_subdivisions_y;
1580 const std::size_t width = m_subdivisions_x + 1;
1581 const std::size_t height = m_subdivisions_y + 1;
1583 for(std::size_t i = 0; i != width; ++i)
1585 double tU = (i + 1 == width) ? 1 : i * incrementU;
1586 PatchControl pointX[3];
1587 PatchControl leftX[3];
1588 PatchControl rightX[3];
1589 QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0], rightX[0]);
1590 QuadraticBezier_evaluate(*subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1], rightX[1]);
1591 QuadraticBezier_evaluate(*subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2], rightX[2]);
1593 ArbitraryMeshVertex* p = vertices + i * strideX;
1594 for(std::size_t j = 0; j != height; ++j)
1596 if((j == 0 || j + 1 == height) && (i == 0 || i + 1 == width))
1601 double tV = (j + 1 == height) ? 1 : j * incrementV;
1603 PatchControl pointY[3];
1604 PatchControl leftY[3];
1605 PatchControl rightY[3];
1606 QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0], rightY[0]);
1607 QuadraticBezier_evaluate(*subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1], rightY[1]);
1608 QuadraticBezier_evaluate(*subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2], rightY[2]);
1613 QuadraticBezier_evaluate(pointX[0], pointX[1], pointX[2], tV, point, left, right);
1616 QuadraticBezier_evaluate(pointY[0], pointY[1], pointY[2], tU, point, up, down);
1618 vertex3f_to_vector3(p->vertex) = point.m_vertex;
1619 texcoord2f_to_vector2(p->texcoord) = point.m_texcoord;
1621 ArbitraryMeshVertex a, b, c;
1623 a.vertex = vertex3f_for_vector3(left.m_vertex);
1624 a.texcoord = texcoord2f_for_vector2(left.m_texcoord);
1625 b.vertex = vertex3f_for_vector3(right.m_vertex);
1626 b.texcoord = texcoord2f_for_vector2(right.m_texcoord);
1630 c.vertex = vertex3f_for_vector3(up.m_vertex);
1631 c.texcoord = texcoord2f_for_vector2(up.m_texcoord);
1635 c.vertex = vertex3f_for_vector3(down.m_vertex);
1636 c.texcoord = texcoord2f_for_vector2(down.m_texcoord);
1639 Vector3 normal = vector3_normalised(vector3_cross(right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex));
1641 Vector3 tangent, bitangent;
1642 ArbitraryMeshTriangle_calcTangents(a, b, c, tangent, bitangent);
1643 vector3_normalise(tangent);
1644 vector3_normalise(bitangent);
1646 if(((nFlagsX & AVERAGE) != 0 && i == 0) || ((nFlagsY & AVERAGE) != 0 && j == 0))
1648 normal3f_to_vector3(p->normal) = vector3_normalised(vector3_added(normal3f_to_vector3(p->normal), normal));
1649 normal3f_to_vector3(p->tangent) = vector3_normalised(vector3_added(normal3f_to_vector3(p->tangent), tangent));
1650 normal3f_to_vector3(p->bitangent) = vector3_normalised(vector3_added(normal3f_to_vector3(p->bitangent), bitangent));
1654 normal3f_to_vector3(p->normal) = normal;
1655 normal3f_to_vector3(p->tangent) = tangent;
1656 normal3f_to_vector3(p->bitangent) = bitangent;
1665 void Patch::TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
1666 std::size_t offStartX, std::size_t offStartY,
1667 std::size_t offEndX, std::size_t offEndY,
1668 std::size_t nFlagsX, std::size_t nFlagsY,
1669 Vector3& left, Vector3& mid, Vector3& right,
1670 Vector2& texLeft, Vector2& texMid, Vector2& texRight,
1673 int newFlagsX, newFlagsY;
1676 Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1;
1678 Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1;
1683 BezierInterpolate2( texcoord_for_index(m_tess.m_vertices, offStartX + offStartY),
1685 texcoord_for_index(m_tess.m_vertices, BX->index + offStartY),
1687 texcoord_for_index(m_tess.m_vertices, offEndX + offStartY) );
1690 BezierInterpolate2( texcoord_for_index(m_tess.m_vertices, offStartX + offEndY),
1692 texcoord_for_index(m_tess.m_vertices, BX->index + offEndY),
1694 texcoord_for_index(m_tess.m_vertices, offEndX + offEndY) );
1698 BezierInterpolate2(texLeft,
1704 if(!BezierCurveTree_isLeaf(BY))
1706 texcoord_for_index(m_tess.m_vertices, BX->index + BY->index) = texTmp;
1710 if(!BezierCurveTree_isLeaf(BX->left))
1712 texcoord_for_index(m_tess.m_vertices, BX->left->index + offStartY) = texcoord_0_0;
1713 texcoord_for_index(m_tess.m_vertices, BX->left->index + offEndY) = texcoord_2_0;
1715 if(!BezierCurveTree_isLeaf(BY))
1717 texcoord_for_index(m_tess.m_vertices, BX->left->index + BY->index) = texcoord_1_0;
1720 if(!BezierCurveTree_isLeaf(BX->right))
1722 texcoord_for_index(m_tess.m_vertices, BX->right->index + offStartY) = texcoord_0_1;
1723 texcoord_for_index(m_tess.m_vertices, BX->right->index + offEndY) = texcoord_2_1;
1725 if(!BezierCurveTree_isLeaf(BY))
1727 texcoord_for_index(m_tess.m_vertices, BX->right->index + BY->index) = texcoord_1_1;
1734 BezierInterpolate3( vertex_for_index(m_tess.m_vertices, offStartX + offStartY),
1736 vertex_for_index(m_tess.m_vertices, BX->index + offStartY),
1738 vertex_for_index(m_tess.m_vertices, offEndX + offStartY) );
1741 BezierInterpolate3( vertex_for_index(m_tess.m_vertices, offStartX + offEndY),
1743 vertex_for_index(m_tess.m_vertices, BX->index + offEndY),
1745 vertex_for_index(m_tess.m_vertices, offEndX + offEndY) );
1750 BezierInterpolate3( left,
1756 if(!BezierCurveTree_isLeaf(BY))
1758 vertex_for_index(m_tess.m_vertices, BX->index + BY->index) = tmp;
1762 if(!BezierCurveTree_isLeaf(BX->left))
1764 vertex_for_index(m_tess.m_vertices, BX->left->index + offStartY) = vertex_0_0;
1765 vertex_for_index(m_tess.m_vertices, BX->left->index + offEndY) = vertex_2_0;
1767 if(!BezierCurveTree_isLeaf(BY))
1769 vertex_for_index(m_tess.m_vertices, BX->left->index + BY->index) = vertex_1_0;
1772 if(!BezierCurveTree_isLeaf(BX->right))
1774 vertex_for_index(m_tess.m_vertices, BX->right->index + offStartY) = vertex_0_1;
1775 vertex_for_index(m_tess.m_vertices, BX->right->index + offEndY) = vertex_2_1;
1777 if(!BezierCurveTree_isLeaf(BY))
1779 vertex_for_index(m_tess.m_vertices, BX->right->index + BY->index) = vertex_1_1;
1787 ArbitraryMeshVertex a, b, c;
1790 if(!(nFlagsX & DEGEN_0a) || !(nFlagsX & DEGEN_0b))
1792 tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
1793 a.vertex = vertex3f_for_vector3(vertex_0_0);
1794 a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
1795 c.vertex = vertex3f_for_vector3(vertex_0_1);
1796 c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
1798 else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
1800 tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
1801 a.vertex = vertex3f_for_vector3(vertex_1_0);
1802 a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
1803 c.vertex = vertex3f_for_vector3(vertex_1_1);
1804 c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
1808 tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
1809 a.vertex = vertex3f_for_vector3(vertex_2_0);
1810 a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
1811 c.vertex = vertex3f_for_vector3(vertex_2_1);
1812 c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
1817 if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
1819 tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
1820 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offEndY].vertex;
1821 b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offEndY].texcoord;
1825 tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
1826 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offStartY].vertex;
1827 b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord;
1831 Vector3 normal, s, t;
1832 ArbitraryMeshVertex& v = m_tess.m_vertices[offStartY + BX->index];
1833 Vector3& p = normal3f_to_vector3(v.normal);
1834 Vector3& ps = normal3f_to_vector3(v.tangent);
1835 Vector3& pt = normal3f_to_vector3(v.bitangent);
1839 normal = vector3_cross(tangentV, tangentU);
1843 normal = vector3_cross(tangentU, tangentV);
1845 normalise_safe(normal);
1847 ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
1851 if(nFlagsX & AVERAGE)
1853 p = vector3_normalised(vector3_added(p, normal));
1854 ps = vector3_normalised(vector3_added(ps, s));
1855 pt = vector3_normalised(vector3_added(pt, t));
1866 ArbitraryMeshVertex a, b, c;
1869 if(!(nFlagsX & DEGEN_2a) || !(nFlagsX & DEGEN_2b))
1871 tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
1872 a.vertex = vertex3f_for_vector3(vertex_2_0);
1873 a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
1874 c.vertex = vertex3f_for_vector3(vertex_2_1);
1875 c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
1877 else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
1879 tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
1880 a.vertex = vertex3f_for_vector3(vertex_1_0);
1881 a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
1882 c.vertex = vertex3f_for_vector3(vertex_1_1);
1883 c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
1887 tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
1888 a.vertex = vertex3f_for_vector3(vertex_0_0);
1889 a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
1890 c.vertex = vertex3f_for_vector3(vertex_0_1);
1891 c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
1896 if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
1898 tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
1899 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offStartY].vertex;
1900 b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offStartY].texcoord;
1904 tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
1905 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offEndY].vertex;
1906 b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offEndY].texcoord;
1909 ArbitraryMeshVertex& v = m_tess.m_vertices[offEndY+BX->index];
1910 Vector3& p = normal3f_to_vector3(v.normal);
1911 Vector3& ps = normal3f_to_vector3(v.tangent);
1912 Vector3& pt = normal3f_to_vector3(v.bitangent);
1916 p = vector3_cross(tangentV, tangentU);
1920 p = vector3_cross(tangentU, tangentV);
1924 ArbitraryMeshTriangle_calcTangents(a, b, c, ps, pt);
1931 newFlagsX = newFlagsY = 0;
1933 if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_0b))
1935 newFlagsX |= DEGEN_0a;
1936 newFlagsX |= DEGEN_0b;
1938 if((nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_1b))
1940 newFlagsX |= DEGEN_1a;
1941 newFlagsX |= DEGEN_1b;
1943 if((nFlagsX & DEGEN_2a) && (nFlagsX & DEGEN_2b))
1945 newFlagsX |= DEGEN_2a;
1946 newFlagsX |= DEGEN_2b;
1948 if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
1950 newFlagsY |= DEGEN_0a;
1951 newFlagsY |= DEGEN_1a;
1952 newFlagsY |= DEGEN_2a;
1954 if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
1956 newFlagsY |= DEGEN_0b;
1957 newFlagsY |= DEGEN_1b;
1958 newFlagsY |= DEGEN_2b;
1962 //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; }
1963 //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; }
1965 newFlagsX |= (nFlagsX & SPLIT);
1966 newFlagsX |= (nFlagsX & AVERAGE);
1968 if(!BezierCurveTree_isLeaf(BY))
1971 int nTemp = newFlagsY;
1973 if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_0b))
1975 newFlagsY |= DEGEN_0a;
1976 newFlagsY |= DEGEN_0b;
1978 newFlagsY |= (nFlagsY & SPLIT);
1979 newFlagsY |= (nFlagsY & AVERAGE);
1981 Vector3& p = vertex_for_index(m_tess.m_vertices, BX->index+BY->index);
1984 Vector2& p2 = texcoord_for_index(m_tess.m_vertices, BX->index+BY->index);
1987 TesselateSubMatrix( BY, BX->left,
1988 offStartY, offStartX,
1990 newFlagsY, newFlagsX,
1991 vertex_0_0, vertex_1_0, vertex_2_0,
1992 texcoord_0_0, texcoord_1_0, texcoord_2_0,
2000 if((nFlagsY & DEGEN_2a) && (nFlagsY & DEGEN_2b)) { newFlagsY |= DEGEN_2a; newFlagsY |= DEGEN_2b; }
2002 TesselateSubMatrix( BY, BX->right,
2003 offStartY, BX->index,
2005 newFlagsY, newFlagsX,
2006 vertex_0_1, vertex_1_1, vertex_2_1,
2007 texcoord_0_1, texcoord_1_1, texcoord_2_1,
2012 if(!BezierCurveTree_isLeaf(BX->left))
2014 TesselateSubMatrix( BX->left, BY,
2015 offStartX, offStartY,
2017 newFlagsX, newFlagsY,
2018 left, vertex_1_0, tmp,
2019 texLeft, texcoord_1_0, texTmp,
2023 if(!BezierCurveTree_isLeaf(BX->right))
2025 TesselateSubMatrix( BX->right, BY,
2026 BX->index, offStartY,
2028 newFlagsX, newFlagsY,
2029 tmp, vertex_1_1, right,
2030 texTmp, texcoord_1_1, texRight,
2037 void Patch::BuildTesselationCurves(EMatrixMajor major)
2039 std::size_t nArrayStride, length, cross, strideU, strideV;
2044 length = (m_width - 1) >> 1;
2051 BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU);
2056 nArrayStride = m_tess.m_nArrayWidth;
2057 length = (m_height - 1) >> 1;
2064 BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV);
2069 ERROR_MESSAGE("neither row-major nor column-major");
2073 Array<std::size_t> arrayLength(length);
2074 Array<BezierCurveTree*> pCurveTree(length);
2076 std::size_t nArrayLength = 1;
2080 for(Array<std::size_t>::iterator i = arrayLength.begin(); i != arrayLength.end(); ++i)
2082 *i = Array<std::size_t>::value_type((major == ROW) ? m_subdivisions_x : m_subdivisions_y);
2088 // create a list of the horizontal control curves in each column of sub-patches
2089 // adaptively tesselate each horizontal control curve in the list
2090 // create a binary tree representing the combined tesselation of the list
2091 for(std::size_t i = 0; i != length; ++i)
2093 PatchControl* p1 = m_ctrlTransformed.data() + (i * 2 * strideU);
2094 GSList* pCurveList = 0;
2095 for(std::size_t j = 0; j < cross; j += 2)
2097 PatchControl* p2 = p1+strideV;
2098 PatchControl* p3 = p2+strideV;
2100 // directly taken from one row of control points
2102 BezierCurve* pCurve = new BezierCurve;
2103 pCurve->crd = (p1+strideU)->m_vertex;
2104 pCurve->left = p1->m_vertex;
2105 pCurve->right = (p1+(strideU<<1))->m_vertex;
2106 pCurveList = g_slist_prepend(pCurveList, pCurve);
2114 // interpolated from three columns of control points
2116 BezierCurve* pCurve = new BezierCurve;
2117 pCurve->crd = vector3_mid((p1+strideU)->m_vertex, (p3+strideU)->m_vertex);
2118 pCurve->left = vector3_mid(p1->m_vertex, p3->m_vertex);
2119 pCurve->right = vector3_mid((p1+(strideU<<1))->m_vertex, (p3+(strideU<<1))->m_vertex);
2121 pCurve->crd = vector3_mid(pCurve->crd, (p2+strideU)->m_vertex);
2122 pCurve->left = vector3_mid(pCurve->left, p2->m_vertex);
2123 pCurve->right = vector3_mid(pCurve->right, (p2+(strideU<<1))->m_vertex);
2124 pCurveList = g_slist_prepend(pCurveList, pCurve);
2130 pCurveTree[i] = new BezierCurveTree;
2131 BezierCurveTree_FromCurveList(pCurveTree[i], pCurveList);
2132 for(GSList* l = pCurveList; l != 0; l = g_slist_next(l))
2134 delete static_cast<BezierCurve*>((*l).data);
2136 g_slist_free(pCurveList);
2138 // set up array indices for binary tree
2139 // accumulate subarray width
2140 arrayLength[i] = Array<std::size_t>::value_type(BezierCurveTree_Setup(pCurveTree[i], nArrayLength, nArrayStride) - (nArrayLength - 1));
2141 // accumulate total array width
2142 nArrayLength += arrayLength[i];
2149 m_tess.m_nArrayWidth = nArrayLength;
2150 std::swap(m_tess.m_arrayWidth, arrayLength);
2154 std::swap(m_tess.m_curveTreeU, pCurveTree);
2158 m_tess.m_nArrayHeight = nArrayLength;
2159 std::swap(m_tess.m_arrayHeight, arrayLength);
2163 std::swap(m_tess.m_curveTreeV, pCurveTree);
2169 inline void vertex_assign_ctrl(ArbitraryMeshVertex& vertex, const PatchControl& ctrl)
2171 vertex.vertex.x = ctrl.m_vertex[0];
2172 vertex.vertex.y = ctrl.m_vertex[1];
2173 vertex.vertex.z = ctrl.m_vertex[2];
2174 vertex.texcoord.s = ctrl.m_texcoord[0];
2175 vertex.texcoord.t = ctrl.m_texcoord[1];
2178 inline void vertex_clear_normal(ArbitraryMeshVertex& vertex)
2180 vertex.normal.x = 0;
2181 vertex.normal.y = 0;
2182 vertex.normal.z = 0;
2183 vertex.tangent.x = 0;
2184 vertex.tangent.y = 0;
2185 vertex.tangent.z = 0;
2186 vertex.bitangent.x = 0;
2187 vertex.bitangent.y = 0;
2188 vertex.bitangent.z = 0;
2191 inline void tangents_remove_degenerate(Vector3 tangents[6], Vector2 textureTangents[6], unsigned int flags)
2193 if(flags & DEGEN_0a)
2195 const std::size_t i =
2197 ? (flags & DEGEN_1a)
2198 ? (flags & DEGEN_1b)
2199 ? (flags & DEGEN_2a)
2205 tangents[0] = tangents[i];
2206 textureTangents[0] = textureTangents[i];
2208 if(flags & DEGEN_0b)
2210 const std::size_t i =
2212 ? (flags & DEGEN_1b)
2213 ? (flags & DEGEN_1a)
2214 ? (flags & DEGEN_2b)
2220 tangents[1] = tangents[i];
2221 textureTangents[1] = textureTangents[i];
2223 if(flags & DEGEN_2a)
2225 const std::size_t i =
2227 ? (flags & DEGEN_1a)
2228 ? (flags & DEGEN_1b)
2229 ? (flags & DEGEN_0a)
2235 tangents[4] = tangents[i];
2236 textureTangents[4] = textureTangents[i];
2238 if(flags & DEGEN_2b)
2240 const std::size_t i =
2242 ? (flags & DEGEN_1b)
2243 ? (flags & DEGEN_1a)
2244 ? (flags & DEGEN_0b)
2250 tangents[5] = tangents[i];
2251 textureTangents[5] = textureTangents[i];
2255 void bestTangents00(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2257 if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2259 if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
2264 else if(!(degenerateFlags & DEGEN_0b))
2275 else if(fabs(dot - length) < 0.001) // same direction = degenerate
2277 if(degenerateFlags & DEGEN_0b)
2290 void bestTangents01(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2292 if(fabs(dot - length) < 0.001) // same direction = degenerate
2294 if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
2299 else if(!(degenerateFlags & DEGEN_2b))
2310 else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2312 if(degenerateFlags & DEGEN_2b)
2325 void bestTangents10(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2327 if(fabs(dot - length) < 0.001) // same direction = degenerate
2329 if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
2334 else if(!(degenerateFlags & DEGEN_0a))
2345 else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2347 if(degenerateFlags & DEGEN_0a)
2360 void bestTangents11(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2362 if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2364 if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
2369 else if(!(degenerateFlags & DEGEN_2a))
2380 else if(fabs(dot - length) < 0.001) // same direction = degenerate
2382 if(degenerateFlags & DEGEN_2a)
2395 void Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1)
2398 Vector3 normal(vector3_cross(tangentX[index0], tangentY[index1]));
2399 if(!vector3_equal(normal, g_vector3_identity))
2401 vector3_add(normal_for_index(m_tess.m_vertices, index), vector3_normalised(normal));
2406 ArbitraryMeshVertex a, b, c;
2407 a.vertex = Vertex3f(0, 0, 0);
2408 a.texcoord = TexCoord2f(0, 0);
2409 b.vertex = vertex3f_for_vector3(tangentX[index0]);
2410 b.texcoord = texcoord2f_for_vector2(tangentS[index0]);
2411 c.vertex = vertex3f_for_vector3(tangentY[index1]);
2412 c.texcoord = texcoord2f_for_vector2(tangentT[index1]);
2415 ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
2416 if(!vector3_equal(s, g_vector3_identity))
2418 vector3_add(tangent_for_index(m_tess.m_vertices, index), vector3_normalised(s));
2420 if(!vector3_equal(t, g_vector3_identity))
2422 vector3_add(bitangent_for_index(m_tess.m_vertices, index), vector3_normalised(t));
2427 void Patch::BuildVertexArray()
2429 const std::size_t strideU = 1;
2430 const std::size_t strideV = m_width;
2432 const std::size_t numElems = m_tess.m_nArrayWidth*m_tess.m_nArrayHeight; // total number of elements in vertex array
2434 const bool bWidthStrips = (m_tess.m_nArrayWidth >= m_tess.m_nArrayHeight); // decide if horizontal strips are longer than vertical
2437 // allocate vertex, normal, texcoord and primitive-index arrays
2438 m_tess.m_vertices.resize(numElems);
2439 m_tess.m_indices.resize(m_tess.m_nArrayWidth *2 * (m_tess.m_nArrayHeight - 1));
2441 // set up strip indices
2444 m_tess.m_numStrips = m_tess.m_nArrayHeight-1;
2445 m_tess.m_lenStrips = m_tess.m_nArrayWidth*2;
2447 for(std::size_t i=0; i<m_tess.m_nArrayWidth; i++)
2449 for(std::size_t j=0; j<m_tess.m_numStrips; j++)
2451 m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(j*m_tess.m_nArrayWidth+i);
2452 m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
2453 // reverse because radiant uses CULL_FRONT
2454 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(j*m_tess.m_nArrayWidth+i);
2455 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
2461 m_tess.m_numStrips = m_tess.m_nArrayWidth-1;
2462 m_tess.m_lenStrips = m_tess.m_nArrayHeight*2;
2464 for(std::size_t i=0; i<m_tess.m_nArrayHeight; i++)
2466 for(std::size_t j=0; j<m_tess.m_numStrips; j++)
2468 m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
2469 m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1);
2470 // reverse because radiant uses CULL_FRONT
2471 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
2472 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1);
2479 PatchControlIter pCtrl = m_ctrlTransformed.data();
2480 for(std::size_t j = 0, offStartY = 0; j+1 < m_height; j += 2, pCtrl += (strideU + strideV))
2482 // set up array offsets for this sub-patch
2483 const bool leafY = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeV[j>>1]);
2484 const std::size_t offMidY = (m_patchDef3) ? 0 : m_tess.m_curveTreeV[j>>1]->index;
2485 const std::size_t widthY = m_tess.m_arrayHeight[j>>1] * m_tess.m_nArrayWidth;
2486 const std::size_t offEndY = offStartY + widthY;
2488 for(std::size_t i = 0, offStartX = 0; i+1 < m_width; i += 2, pCtrl += (strideU << 1))
2490 const bool leafX = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i>>1]);
2491 const std::size_t offMidX = (m_patchDef3) ? 0 : m_tess.m_curveTreeU[i>>1]->index;
2492 const std::size_t widthX = m_tess.m_arrayWidth[i>>1];
2493 const std::size_t offEndX = offStartX + widthX;
2495 PatchControl *subMatrix[3][3];
2496 subMatrix[0][0] = pCtrl;
2497 subMatrix[0][1] = subMatrix[0][0]+strideU;
2498 subMatrix[0][2] = subMatrix[0][1]+strideU;
2499 subMatrix[1][0] = subMatrix[0][0]+strideV;
2500 subMatrix[1][1] = subMatrix[1][0]+strideU;
2501 subMatrix[1][2] = subMatrix[1][1]+strideU;
2502 subMatrix[2][0] = subMatrix[1][0]+strideV;
2503 subMatrix[2][1] = subMatrix[2][0]+strideU;
2504 subMatrix[2][2] = subMatrix[2][1]+strideU;
2506 // assign on-patch control points to vertex array
2507 if(i == 0 && j == 0)
2509 vertex_clear_normal(m_tess.m_vertices[offStartX + offStartY]);
2511 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offStartY], *subMatrix[0][0]);
2514 vertex_clear_normal(m_tess.m_vertices[offEndX + offStartY]);
2516 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offStartY], *subMatrix[0][2]);
2519 vertex_clear_normal(m_tess.m_vertices[offStartX + offEndY]);
2521 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offEndY], *subMatrix[2][0]);
2523 vertex_clear_normal(m_tess.m_vertices[offEndX + offEndY]);
2524 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offEndY], *subMatrix[2][2]);
2528 // assign remaining control points to vertex array
2531 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offStartY], *subMatrix[0][1]);
2532 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offEndY], *subMatrix[2][1]);
2536 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offMidY], *subMatrix[1][0]);
2537 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offMidY], *subMatrix[1][2]);
2541 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offMidY], *subMatrix[1][1]);
2546 // test all 12 edges for degeneracy
2547 unsigned int nFlagsX = subarray_get_degen(pCtrl, strideU, strideV);
2548 unsigned int nFlagsY = subarray_get_degen(pCtrl, strideV, strideU);
2549 Vector3 tangentX[6], tangentY[6];
2550 Vector2 tangentS[6], tangentT[6];
2552 // set up tangents for each of the 12 edges if they were not degenerate
2553 if(!(nFlagsX & DEGEN_0a))
2555 tangentX[0] = vector3_subtracted(subMatrix[0][1]->m_vertex, subMatrix[0][0]->m_vertex);
2556 tangentS[0] = vector2_subtracted(subMatrix[0][1]->m_texcoord, subMatrix[0][0]->m_texcoord);
2558 if(!(nFlagsX & DEGEN_0b))
2560 tangentX[1] = vector3_subtracted(subMatrix[0][2]->m_vertex, subMatrix[0][1]->m_vertex);
2561 tangentS[1] = vector2_subtracted(subMatrix[0][2]->m_texcoord, subMatrix[0][1]->m_texcoord);
2563 if(!(nFlagsX & DEGEN_1a))
2565 tangentX[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[1][0]->m_vertex);
2566 tangentS[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[1][0]->m_texcoord);
2568 if(!(nFlagsX & DEGEN_1b))
2570 tangentX[3] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[1][1]->m_vertex);
2571 tangentS[3] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[1][1]->m_texcoord);
2573 if(!(nFlagsX & DEGEN_2a))
2575 tangentX[4] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[2][0]->m_vertex);
2576 tangentS[4] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[2][0]->m_texcoord);
2578 if(!(nFlagsX & DEGEN_2b))
2580 tangentX[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[2][1]->m_vertex);
2581 tangentS[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[2][1]->m_texcoord);
2584 if(!(nFlagsY & DEGEN_0a))
2586 tangentY[0] = vector3_subtracted(subMatrix[1][0]->m_vertex, subMatrix[0][0]->m_vertex);
2587 tangentT[0] = vector2_subtracted(subMatrix[1][0]->m_texcoord, subMatrix[0][0]->m_texcoord);
2589 if(!(nFlagsY & DEGEN_0b))
2591 tangentY[1] = vector3_subtracted(subMatrix[2][0]->m_vertex, subMatrix[1][0]->m_vertex);
2592 tangentT[1] = vector2_subtracted(subMatrix[2][0]->m_texcoord, subMatrix[1][0]->m_texcoord);
2594 if(!(nFlagsY & DEGEN_1a))
2596 tangentY[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[0][1]->m_vertex);
2597 tangentT[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[0][1]->m_texcoord);
2599 if(!(nFlagsY & DEGEN_1b))
2601 tangentY[3] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[1][1]->m_vertex);
2602 tangentT[3] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[1][1]->m_texcoord);
2604 if(!(nFlagsY & DEGEN_2a))
2606 tangentY[4] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[0][2]->m_vertex);
2607 tangentT[4] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[0][2]->m_texcoord);
2609 if(!(nFlagsY & DEGEN_2b))
2611 tangentY[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[1][2]->m_vertex);
2612 tangentT[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[1][2]->m_texcoord);
2615 // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge
2616 tangents_remove_degenerate(tangentX, tangentS, nFlagsX);
2617 tangents_remove_degenerate(tangentY, tangentT, nFlagsY);
2621 std::size_t index = offStartX + offStartY;
2622 std::size_t index0 = 0;
2623 std::size_t index1 = 0;
2625 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2626 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2628 bestTangents00(nFlagsX, dot, length, index0, index1);
2630 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2635 std::size_t index = offEndX + offStartY;
2636 std::size_t index0 = 1;
2637 std::size_t index1 = 4;
2639 double dot = vector3_dot(tangentX[index0],tangentY[index1]);
2640 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2642 bestTangents10(nFlagsX, dot, length, index0, index1);
2644 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2649 std::size_t index = offStartX + offEndY;
2650 std::size_t index0 = 4;
2651 std::size_t index1 = 1;
2653 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2654 double length = vector3_length(tangentX[index1]) * vector3_length(tangentY[index1]);
2656 bestTangents01(nFlagsX, dot, length, index0, index1);
2658 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2663 std::size_t index = offEndX + offEndY;
2664 std::size_t index0 = 5;
2665 std::size_t index1 = 5;
2667 double dot = vector3_dot(tangentX[index0],tangentY[index1]);
2668 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2670 bestTangents11(nFlagsX, dot, length, index0, index1);
2672 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2675 //normalise normals that won't be accumulated again
2678 normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offStartY));
2679 normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offStartY));
2680 normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offStartY));
2684 normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offStartY));
2685 normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offStartY));
2686 normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offStartY));
2690 normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offEndY));
2691 normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offEndY));
2692 normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offEndY));
2694 if(i+3 == m_width && j+3 == m_height)
2696 normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offEndY));
2697 normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offEndY));
2698 normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offEndY));
2701 // set flags to average normals between shared edges
2710 // set flags to save evaluating shared edges twice
2714 // if the patch is curved.. tesselate recursively
2715 // use the relevant control curves for this sub-patch
2718 TesselateSubMatrixFixed(m_tess.m_vertices.data() + offStartX + offStartY, 1, m_tess.m_nArrayWidth, nFlagsX, nFlagsY, subMatrix);
2724 TesselateSubMatrix( m_tess.m_curveTreeU[i>>1], m_tess.m_curveTreeV[j>>1],
2725 offStartX, offStartY, offEndX, offEndY, // array offsets
2727 subMatrix[1][0]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[1][2]->m_vertex,
2728 subMatrix[1][0]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[1][2]->m_texcoord,
2733 TesselateSubMatrix( m_tess.m_curveTreeV[j>>1], m_tess.m_curveTreeU[i>>1],
2734 offStartY, offStartX, offEndY, offEndX, // array offsets
2736 subMatrix[0][1]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[2][1]->m_vertex,
2737 subMatrix[0][1]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[2][1]->m_texcoord,
2742 offStartX = offEndX;
2744 offStartY = offEndY;
2751 class PatchFilterWrapper : public Filter
2755 PatchFilter& m_filter;
2757 PatchFilterWrapper(PatchFilter& filter, bool invert) : m_invert(invert), m_filter(filter)
2760 void setActive(bool active)
2768 bool filter(const Patch& patch)
2770 return m_invert ^ m_filter.filter(patch);
2775 typedef std::list<PatchFilterWrapper> PatchFilters;
2776 PatchFilters g_patchFilters;
2778 void add_patch_filter(PatchFilter& filter, int mask, bool invert)
2780 g_patchFilters.push_back(PatchFilterWrapper(filter, invert));
2781 GlobalFilterSystem().addFilter(g_patchFilters.back(), mask);
2784 bool patch_filtered(Patch& patch)
2786 for(PatchFilters::iterator i = g_patchFilters.begin(); i != g_patchFilters.end(); ++i)
2788 if((*i).active() && (*i).filter(patch))