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 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)
132 pCurve = (BezierCurve *)(l->data);
133 if(bSplit || BezierCurve_IsCurved(pCurve))
136 pLeftCurve = new BezierCurve;
137 pRightCurve = new BezierCurve;
138 pLeftCurve->left = pCurve->left;
139 pRightCurve->right = pCurve->right;
140 BezierInterpolate(pCurve);
141 pLeftCurve->crd = pCurve->left;
142 pRightCurve->crd = pCurve->right;
143 pLeftCurve->right = pCurve->crd;
144 pRightCurve->left = pCurve->crd;
146 pLeftList = g_slist_prepend(pLeftList, pLeftCurve);
147 pRightList = g_slist_prepend(pRightList, pRightCurve);
151 if(pLeftList != 0 && pRightList != 0 && depth != PATCH_MAX_SUBDIVISION_DEPTH)
153 pTree->left = new BezierCurveTree;
154 pTree->right = new BezierCurveTree;
155 BezierCurveTree_FromCurveList(pTree->left, pLeftList, depth + 1);
156 BezierCurveTree_FromCurveList(pTree->right, pRightList, depth + 1);
158 for(GSList* l = pLeftList; l != 0; l = g_slist_next(l))
160 delete (BezierCurve*)l->data;
163 for(GSList* l = pRightList; l != 0; l = g_slist_next(l))
165 delete (BezierCurve*)l->data;
168 g_slist_free(pLeftList);
169 g_slist_free(pRightList);
179 int Patch::m_CycleCapIndex = 0;
182 void Patch::setDims (std::size_t w, std::size_t h)
186 ASSERT_MESSAGE(w <= MAX_PATCH_WIDTH, "patch too wide");
187 if(w > MAX_PATCH_WIDTH)
189 else if(w < MIN_PATCH_WIDTH)
194 ASSERT_MESSAGE(h <= MAX_PATCH_HEIGHT, "patch too tall");
195 if(h > MAX_PATCH_HEIGHT)
196 h = MAX_PATCH_HEIGHT;
197 else if(h < MIN_PATCH_HEIGHT)
198 h = MIN_PATCH_HEIGHT;
200 m_width = w; m_height = h;
202 if(m_width * m_height != m_ctrl.size())
204 m_ctrl.resize(m_width * m_height);
205 onAllocate(m_ctrl.size());
209 inline const Colour4b& colour_for_index(std::size_t i, std::size_t width)
211 return (i%2 || (i/width)%2) ? colour_inside : colour_corner;
214 inline bool float_valid(float f)
219 bool Patch::isValid() const
221 if(!m_width || !m_height)
226 for(const_iterator i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
228 if(!float_valid((*i).m_vertex.x())
229 || !float_valid((*i).m_vertex.y())
230 || !float_valid((*i).m_vertex.z())
231 || !float_valid((*i).m_texcoord.x())
232 || !float_valid((*i).m_texcoord.y()))
234 globalErrorStream() << "patch has invalid control points\n";
241 void Patch::UpdateCachedData()
243 m_ctrl_vertices.clear();
244 m_lattice_indices.clear();
248 m_tess.m_numStrips = 0;
249 m_tess.m_lenStrips = 0;
250 m_tess.m_nArrayHeight = 0;
251 m_tess.m_nArrayWidth = 0;
252 m_tess.m_curveTreeU.resize(0);
253 m_tess.m_curveTreeV.resize(0);
254 m_tess.m_indices.resize(0);
255 m_tess.m_vertices.resize(0);
256 m_tess.m_arrayHeight.resize(0);
257 m_tess.m_arrayWidth.resize(0);
258 m_aabb_local = AABB();
262 BuildTesselationCurves(ROW);
263 BuildTesselationCurves(COL);
267 IndexBuffer ctrl_indices;
269 m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
270 ctrl_indices.reserve(m_ctrlTransformed.size());
272 UniqueVertexBuffer<PointVertex> inserter(m_ctrl_vertices);
273 for(iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
275 ctrl_indices.insert(inserter.insert(pointvertex_quantised(PointVertex(reinterpret_cast<const Vertex3f&>((*i).m_vertex), colour_for_index(i - m_ctrlTransformed.begin(), m_width)))));
279 for(IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i)
281 if(std::size_t(i - ctrl_indices.begin()) % m_width)
283 m_lattice_indices.insert(*(i - 1));
284 m_lattice_indices.insert(*i);
286 if(std::size_t(i - ctrl_indices.begin()) >= m_width)
288 m_lattice_indices.insert(*(i - m_width));
289 m_lattice_indices.insert(*i);
296 Array<RenderIndex>::iterator first = m_tess.m_indices.begin();
297 for(std::size_t s=0; s<m_tess.m_numStrips; s++)
299 Array<RenderIndex>::iterator last = first + m_tess.m_lenStrips;
301 for(Array<RenderIndex>::iterator i(first); i+2 != last; i += 2)
303 ArbitraryMeshTriangle_sumTangents(m_tess.m_vertices[*(i+0)], m_tess.m_vertices[*(i+1)], m_tess.m_vertices[*(i+2)]);
304 ArbitraryMeshTriangle_sumTangents(m_tess.m_vertices[*(i+2)], m_tess.m_vertices[*(i+1)], m_tess.m_vertices[*(i+3)]);
310 for(Array<ArbitraryMeshVertex>::iterator i = m_tess.m_vertices.begin(); i != m_tess.m_vertices.end(); ++i)
312 vector3_normalise(reinterpret_cast<Vector3&>((*i).tangent));
313 vector3_normalise(reinterpret_cast<Vector3&>((*i).bitangent));
321 void Patch::InvertMatrix()
325 PatchControlArray_invert(m_ctrl, m_width, m_height);
327 controlPointsChanged();
330 void Patch::TransposeMatrix()
335 Array<PatchControl> tmp(m_width * m_height);
336 copy_ctrl(tmp.data(), m_ctrl.data(), m_ctrl.data() + m_width * m_height);
338 PatchControlIter from = tmp.data();
339 for(std::size_t h = 0; h != m_height; ++h)
341 PatchControlIter to = m_ctrl.data() + h;
342 for(std::size_t w = 0; w != m_width; ++w, ++from, to += m_height)
350 std::size_t tmp = m_width;
355 controlPointsChanged();
358 void Patch::Redisperse(EMatrixMajor mt)
360 std::size_t w, h, width, height, row_stride, col_stride;
361 PatchControl* p1, * p2, * p3;
368 width = (m_width-1)>>1;
371 row_stride = m_width;
374 width = (m_height-1)>>1;
376 col_stride = m_width;
380 ERROR_MESSAGE("neither row-major nor column-major");
384 for(h=0;h<height;h++)
386 p1 = m_ctrl.data()+(h*row_stride);
391 p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
396 controlPointsChanged();
399 void Patch::Smooth(EMatrixMajor mt)
401 std::size_t w, h, width, height, row_stride, col_stride;
403 PatchControl* p1, * p2, * p3, * p2b;
410 width = (m_width-1)>>1;
413 row_stride = m_width;
416 width = (m_height-1)>>1;
418 col_stride = m_width;
422 ERROR_MESSAGE("neither row-major nor column-major");
427 for(h=0;h<height;h++)
429 p1 = m_ctrl.data()+(h*row_stride);
430 p2 = p1+(2*width)*col_stride;
431 //globalErrorStream() << "compare " << p1->m_vertex << " and " << p2->m_vertex << "\n";
432 if(vector3_length_squared(vector3_subtracted(p1->m_vertex, p2->m_vertex)) > 1.0)
434 //globalErrorStream() << "too far\n";
440 for(h=0;h<height;h++)
442 p1 = m_ctrl.data()+(h*row_stride)+col_stride;
443 for(w=0;w<width-1;w++)
447 p2->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
452 p1 = m_ctrl.data()+(h*row_stride)+(2*width-1)*col_stride;
453 p2 = m_ctrl.data()+(h*row_stride);
454 p2b = m_ctrl.data()+(h*row_stride)+(2*width)*col_stride;
455 p3 = m_ctrl.data()+(h*row_stride)+col_stride;
456 p2->m_vertex = p2b->m_vertex = vector3_mid(p1->m_vertex, p3->m_vertex);
460 controlPointsChanged();
463 void Patch::InsertRemove(bool bInsert, bool bColumn, bool bFirst)
469 if(bColumn && (m_width + 2 <= MAX_PATCH_WIDTH))
470 InsertPoints(COL, bFirst);
471 else if(m_height + 2 <= MAX_PATCH_HEIGHT)
472 InsertPoints(ROW, bFirst);
476 if(bColumn && (m_width - 2 >= MIN_PATCH_WIDTH))
477 RemovePoints(COL, bFirst);
478 else if(m_height - 2 >= MIN_PATCH_HEIGHT)
479 RemovePoints(ROW, bFirst);
482 controlPointsChanged();
485 Patch* Patch::MakeCap(Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirst)
487 std::size_t i, width, height;
500 ERROR_MESSAGE("neither row-major nor column-major");
504 Array<Vector3> p(width);
506 std::size_t nIndex = (bFirst) ? 0 : height-1;
509 for (i=0; i<width; i++)
511 p[(bFirst)?i:(width-1)-i] = ctrlAt(nIndex, i).m_vertex;
516 for (i=0; i<width; i++)
518 p[(bFirst)?i:(width-1)-i] = ctrlAt(i, nIndex).m_vertex;
522 patch->ConstructSeam(eType, p.data(), width);
526 void Patch::FlipTexture(int nAxis)
530 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
532 (*i).m_texcoord[nAxis] = -(*i).m_texcoord[nAxis];
535 controlPointsChanged();
538 void Patch::TranslateTexture(float s, float t)
542 s = -1 * s / m_state->getTexture().width;
543 t = t / m_state->getTexture().height;
545 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
547 (*i).m_texcoord[0] += s;
548 (*i).m_texcoord[1] += t;
551 controlPointsChanged();
554 void Patch::ScaleTexture(float s, float t)
558 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
560 (*i).m_texcoord[0] *= s;
561 (*i).m_texcoord[1] *= t;
564 controlPointsChanged();
567 void Patch::RotateTexture(float angle)
571 const float s = static_cast<float>(sin(degrees_to_radians(angle)));
572 const float c = static_cast<float>(cos(degrees_to_radians(angle)));
574 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
576 const float x = (*i).m_texcoord[0];
577 const float y = (*i).m_texcoord[1];
578 (*i).m_texcoord[0] = (x * c) - (y * s);
579 (*i).m_texcoord[1] = (y * c) + (x * s);
582 controlPointsChanged();
586 void Patch::SetTextureRepeat(float s, float t)
589 float si, ti, sc, tc;
594 si = s / (float)(m_width - 1);
595 ti = t / (float)(m_height - 1);
597 pDest = m_ctrl.data();
598 for (h=0, tc = 0.0f; h<m_height; h++, tc+=ti)
600 for (w=0, sc = 0.0f; w<m_width; w++, sc+=si)
602 pDest->m_texcoord[0] = sc;
603 pDest->m_texcoord[1] = tc;
608 controlPointsChanged();
612 void Patch::SetTextureInfo(texdef_t *pt)
614 if(pt->getShift()[0] || pt->getShift()[1])
615 TranslateTexture (pt->getShift()[0], pt->getShift()[1]);
616 else if(pt->getScale()[0] || pt->getScale()[1])
618 if(pt->getScale()[0] == 0.0f) pt->setScale(0, 1.0f);
619 if(pt->getScale()[1] == 0.0f) pt->setScale(1, 1.0f);
620 ScaleTexture (pt->getScale()[0], pt->getScale()[1]);
623 RotateTexture (pt->rotate);
627 inline int texture_axis(const Vector3& normal)
629 // axis dominance order: Z, X, Y
630 return (normal.x() >= normal.y()) ? (normal.x() > normal.z()) ? 0 : 2 : (normal.y() > normal.z()) ? 1 : 2;
633 void Patch::CapTexture()
635 const PatchControl& p1 = m_ctrl[m_width];
636 const PatchControl& p2 = m_ctrl[m_width*(m_height-1)];
637 const PatchControl& p3 = m_ctrl[(m_width*m_height)-1];
640 Vector3 normal(g_vector3_identity);
643 Vector3 tmp(vector3_cross(
644 vector3_subtracted(p2.m_vertex, m_ctrl[0].m_vertex),
645 vector3_subtracted(p3.m_vertex, m_ctrl[0].m_vertex)
647 if(!vector3_equal(tmp, g_vector3_identity))
649 vector3_add(normal, tmp);
653 Vector3 tmp(vector3_cross(
654 vector3_subtracted(p1.m_vertex, p3.m_vertex),
655 vector3_subtracted(m_ctrl[0].m_vertex, p3.m_vertex)
657 if(!vector3_equal(tmp, g_vector3_identity))
659 vector3_add(normal, tmp);
663 ProjectTexture(texture_axis(normal));
666 // uses longest parallel chord to calculate texture coords for each row/col
667 void Patch::NaturalTexture()
672 float fSize = (float)m_state->getTexture().width * Texdef_getDefaultTextureScale();
676 PatchControl* pWidth = m_ctrl.data();
677 for (std::size_t w=0; w<m_width; w++, pWidth++)
680 PatchControl* pHeight = pWidth;
681 for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
682 pHeight->m_texcoord[0] = static_cast<float>(tex);
689 PatchControl* pHeight = pWidth;
690 for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
692 Vector3 v(vector3_subtracted(pHeight->m_vertex, (pHeight+1)->m_vertex));
693 double length = tex + (vector3_length(v) / fSize);
694 if(fabs(length) > texBest) texBest = length;
703 float fSize = -(float)m_state->getTexture().height * Texdef_getDefaultTextureScale();
707 PatchControl* pHeight = m_ctrl.data();
708 for (std::size_t h=0; h<m_height; h++, pHeight+=m_width)
711 PatchControl* pWidth = pHeight;
712 for (std::size_t w=0; w<m_width; w++, pWidth++)
713 pWidth->m_texcoord[1] = static_cast<float>(tex);
720 PatchControl* pWidth = pHeight;
721 for (std::size_t w=0; w<m_width; w++, pWidth++)
723 Vector3 v(vector3_subtracted(pWidth->m_vertex, (pWidth+m_width)->m_vertex));
724 double length = tex + (vector3_length(v) / fSize);
725 if(fabs(length) > texBest) texBest = length;
733 controlPointsChanged();
740 void Patch::AccumulateBBox()
742 m_aabb_local = AABB();
744 for(PatchControlArray::iterator i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
746 aabb_extend_by_point_safe(m_aabb_local, (*i).m_vertex);
753 void Patch::InsertPoints(EMatrixMajor mt, bool bFirst)
755 std::size_t width, height, row_stride, col_stride;
761 row_stride = m_width;
766 col_stride = m_width;
772 ERROR_MESSAGE("neither row-major nor column-major");
778 PatchControl* p1 = m_ctrl.data();
780 if(GlobalSelectionSystem().countSelected() != 0)
782 scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
783 PatchInstance* patch = Instance_getPatch(instance);
784 patch->m_selectable.isSelected();
787 for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
790 PatchControl* p2 = p1;
791 for(std::size_t h = 1; h < height; h += 2, p2 += 2 * row_stride)
793 if(0)//p2->m_selectable.isSelected())
806 PatchControl* p2 = p1;
807 for(std::size_t h = 0; h < height; h += 2, p2 += 2 * row_stride)
809 if(0)//p2->m_selectable.isSelected())
823 Array<PatchControl> tmp(m_ctrl);
825 std::size_t row_stride2, col_stride2;
829 setDims(m_width, m_height+2);
831 row_stride2 = m_width;
834 setDims(m_width+2, m_height);
835 col_stride2 = m_width;
839 ERROR_MESSAGE("neither row-major nor column-major");
872 for(std::size_t w = 0; w != width; ++w)
874 PatchControl* p1 = tmp.data() + (w*col_stride);
875 PatchControl* p2 = m_ctrl.data() + (w*col_stride2);
876 for(std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride)
880 p2 += 2 * row_stride2;
885 p1 = tmp.data() + (w*col_stride+pos*row_stride);
886 p2 = m_ctrl.data() + (w*col_stride2+pos*row_stride2);
888 PatchControl* r2a = (p2+row_stride2);
889 PatchControl* r2b = (p2-row_stride2);
890 PatchControl* c2a = (p1-2*row_stride);
891 PatchControl* c2b = (p1-row_stride);
893 // set two new row points
894 *(p2+2*row_stride2) = *p1;
897 for(std::size_t i = 0; i != 3; ++i)
899 r2a->m_vertex[i] = float_mid(c2b->m_vertex[i], p1->m_vertex[i]);
901 r2b->m_vertex[i] = float_mid(c2a->m_vertex[i], c2b->m_vertex[i]);
903 p2->m_vertex[i] = float_mid(r2a->m_vertex[i], r2b->m_vertex[i]);
905 for(std::size_t i = 0; i != 2; ++i)
907 r2a->m_texcoord[i] = float_mid(c2b->m_texcoord[i], p1->m_texcoord[i]);
909 r2b->m_texcoord[i] = float_mid(c2a->m_texcoord[i], c2b->m_texcoord[i]);
911 p2->m_texcoord[i] = float_mid(r2a->m_texcoord[i], r2b->m_texcoord[i]);
916 void Patch::RemovePoints(EMatrixMajor mt, bool bFirst)
918 std::size_t width, height, row_stride, col_stride;
924 row_stride = m_width;
929 col_stride = m_width;
935 ERROR_MESSAGE("neither row-major nor column-major");
941 PatchControl* p1 = m_ctrl.data();
942 for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
945 PatchControl* p2 = p1;
946 for(std::size_t h=1; h < height; h += 2, p2 += 2 * row_stride)
948 if(0)//p2->m_selectable.isSelected())
961 PatchControl* p2 = p1;
962 for(std::size_t h=0; h < height; h += 2, p2 += 2 * row_stride)
964 if(0)//p2->m_selectable.isSelected())
978 Array<PatchControl> tmp(m_ctrl);
980 std::size_t row_stride2, col_stride2;
984 setDims(m_width, m_height-2);
986 row_stride2 = m_width;
989 setDims(m_width-2, m_height);
990 col_stride2 = m_width;
994 ERROR_MESSAGE("neither row-major nor column-major");
1020 else if(pos > height - 3)
1029 for(std::size_t w = 0; w != width; w++)
1031 PatchControl* p1 = tmp.data() + (w*col_stride);
1032 PatchControl* p2 = m_ctrl.data() + (w*col_stride2);
1033 for(std::size_t h = 0; h != height; ++h, p2 += row_stride2, p1 += row_stride)
1037 p1 += 2 * row_stride2; h += 2;
1042 p1 = tmp.data() + (w*col_stride+pos*row_stride);
1043 p2 = m_ctrl.data() + (w*col_stride2+pos*row_stride2);
1045 for(std::size_t i=0; i<3; i++)
1047 (p2-row_stride2)->m_vertex[i] = ((p1+2*row_stride)->m_vertex[i]+(p1-2*row_stride)->m_vertex[i]) * 0.5f;
1049 (p2-row_stride2)->m_vertex[i] = (p2-row_stride2)->m_vertex[i]+(2.0f * ((p1)->m_vertex[i]-(p2-row_stride2)->m_vertex[i]));
1051 for(std::size_t i=0; i<2; i++)
1053 (p2-row_stride2)->m_texcoord[i] = ((p1+2*row_stride)->m_texcoord[i]+(p1-2*row_stride)->m_texcoord[i]) * 0.5f;
1055 (p2-row_stride2)->m_texcoord[i] = (p2-row_stride2)->m_texcoord[i]+(2.0f * ((p1)->m_texcoord[i]-(p2-row_stride2)->m_texcoord[i]));
1060 void Patch::ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width)
1067 m_ctrl[0].m_vertex = p[0];
1068 m_ctrl[1].m_vertex = p[1];
1069 m_ctrl[2].m_vertex = p[1];
1070 m_ctrl[3].m_vertex = p[1];
1071 m_ctrl[4].m_vertex = p[1];
1072 m_ctrl[5].m_vertex = p[1];
1073 m_ctrl[6].m_vertex = p[2];
1074 m_ctrl[7].m_vertex = p[1];
1075 m_ctrl[8].m_vertex = p[1];
1081 Vector3 p3(vector3_added(p[2], vector3_subtracted(p[0], p[1])));
1082 m_ctrl[0].m_vertex = p3;
1083 m_ctrl[1].m_vertex = p3;
1084 m_ctrl[2].m_vertex = p[2];
1085 m_ctrl[3].m_vertex = p3;
1086 m_ctrl[4].m_vertex = p3;
1087 m_ctrl[5].m_vertex = p[1];
1088 m_ctrl[6].m_vertex = p3;
1089 m_ctrl[7].m_vertex = p3;
1090 m_ctrl[8].m_vertex = p[0];
1095 Vector3 p5(vector3_mid(p[0], p[4]));
1098 m_ctrl[0].m_vertex = p[0];
1099 m_ctrl[1].m_vertex = p5;
1100 m_ctrl[2].m_vertex = p[4];
1101 m_ctrl[3].m_vertex = p[1];
1102 m_ctrl[4].m_vertex = p[2];
1103 m_ctrl[5].m_vertex = p[3];
1104 m_ctrl[6].m_vertex = p[2];
1105 m_ctrl[7].m_vertex = p[2];
1106 m_ctrl[8].m_vertex = p[2];
1112 m_ctrl[0].m_vertex = p[4];
1113 m_ctrl[1].m_vertex = p[3];
1114 m_ctrl[2].m_vertex = p[2];
1115 m_ctrl[3].m_vertex = p[1];
1116 m_ctrl[4].m_vertex = p[0];
1117 m_ctrl[5].m_vertex = p[3];
1118 m_ctrl[6].m_vertex = p[3];
1119 m_ctrl[7].m_vertex = p[2];
1120 m_ctrl[8].m_vertex = p[1];
1121 m_ctrl[9].m_vertex = p[1];
1122 m_ctrl[10].m_vertex = p[3];
1123 m_ctrl[11].m_vertex = p[3];
1124 m_ctrl[12].m_vertex = p[2];
1125 m_ctrl[13].m_vertex = p[1];
1126 m_ctrl[14].m_vertex = p[1];
1131 std::size_t mid = (width - 1) >> 1;
1133 bool degenerate = (mid % 2) != 0;
1135 std::size_t newHeight = mid + (degenerate ? 2 : 1);
1137 setDims(3, newHeight);
1142 for(std::size_t i = width; i != width + 2; ++i)
1144 p[i] = p[width - 1];
1149 PatchControl* pCtrl = m_ctrl.data();
1150 for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
1152 pCtrl->m_vertex = p[i];
1156 PatchControl* pCtrl = m_ctrl.data() + 2;
1157 std::size_t h = m_height - 1;
1158 for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
1160 pCtrl->m_vertex = p[h + (h - i)];
1168 ERROR_MESSAGE("invalid patch-cap type");
1172 controlPointsChanged();
1175 void Patch::ProjectTexture(int nAxis)
1196 ERROR_MESSAGE("invalid axis");
1200 float fWidth = 1 / (m_state->getTexture().width * Texdef_getDefaultTextureScale());
1201 float fHeight = 1 / (m_state->getTexture().height * -Texdef_getDefaultTextureScale());
1203 for(PatchControlIter i = m_ctrl.data(); i != m_ctrl.data() + m_ctrl.size(); ++i)
1205 (*i).m_texcoord[0] = (*i).m_vertex[s] * fWidth;
1206 (*i).m_texcoord[1] = (*i).m_vertex[t] * fHeight;
1209 controlPointsChanged();
1212 void Patch::constructPlane(const AABB& aabb, int axis, std::size_t width, std::size_t height)
1214 setDims(width, height);
1219 case 2: x=0; y=1; z=2; break;
1220 case 1: x=0; y=2; z=1; break;
1221 case 0: x=1; y=2; z=0; break;
1223 ERROR_MESSAGE("invalid view-type");
1227 if(m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH) m_width = 3;
1228 if(m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT) m_height = 3;
1231 vStart[x] = aabb.origin[x] - aabb.extents[x];
1232 vStart[y] = aabb.origin[y] - aabb.extents[y];
1233 vStart[z] = aabb.origin[z];
1235 float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float)(m_width - 1));
1236 float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float)(m_height - 1));
1239 vTmp[z] = vStart[z];
1240 PatchControl* pCtrl = m_ctrl.data();
1243 for (std::size_t h=0; h<m_height; h++)
1246 for (std::size_t w=0; w<m_width; w++, ++pCtrl)
1248 pCtrl->m_vertex = vTmp;
1257 void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, int axis, std::size_t width, std::size_t height)
1263 vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1264 vPos[1] = aabb.origin;
1265 vPos[2] = vector3_added(aabb.origin, aabb.extents);
1270 constructPlane(aabb, axis, width, height);
1272 else if(eType == eSqCylinder
1273 || eType == eCylinder
1274 || eType == eDenseCylinder
1275 || eType == eVeryDenseCylinder
1277 || eType == eSphere)
1279 unsigned char *pIndex;
1280 unsigned char pCylIndex[] =
1294 PatchControl *pStart;
1297 case eSqCylinder: setDims(9, 3);
1298 pStart = m_ctrl.data();
1300 case eDenseCylinder:
1301 case eVeryDenseCylinder:
1304 pStart = m_ctrl.data() + 1;
1306 case eCone: setDims(9, 3);
1307 pStart = m_ctrl.data() + 1;
1311 pStart = m_ctrl.data() + (9+1);
1314 ERROR_MESSAGE("this should be unreachable");
1318 for(std::size_t h=0; h<3; h++, pStart+=9)
1321 PatchControl* pCtrl = pStart;
1322 for(std::size_t w=0; w<8; w++, pCtrl++)
1324 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1325 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1326 pCtrl->m_vertex[2] = vPos[h][2];
1335 PatchControl* pCtrl=m_ctrl.data();
1336 for(std::size_t h=0; h<3; h++, pCtrl+=9)
1338 pCtrl[8].m_vertex = pCtrl[0].m_vertex;
1342 case eDenseCylinder:
1343 case eVeryDenseCylinder:
1346 PatchControl* pCtrl=m_ctrl.data();
1347 for (std::size_t h=0; h<3; h++, pCtrl+=9)
1349 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1355 PatchControl* pCtrl=m_ctrl.data();
1356 for (std::size_t h=0; h<2; h++, pCtrl+=9)
1358 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1362 PatchControl* pCtrl=m_ctrl.data()+9*2;
1363 for (std::size_t w=0; w<9; w++, pCtrl++)
1365 pCtrl->m_vertex[0] = vPos[1][0];
1366 pCtrl->m_vertex[1] = vPos[1][1];
1367 pCtrl->m_vertex[2] = vPos[2][2];
1373 PatchControl* pCtrl=m_ctrl.data()+9;
1374 for (std::size_t h=0; h<3; h++, pCtrl+=9)
1376 pCtrl[0].m_vertex = pCtrl[8].m_vertex;
1380 PatchControl* pCtrl = m_ctrl.data();
1381 for (std::size_t w=0; w<9; w++, pCtrl++)
1383 pCtrl->m_vertex[0] = vPos[1][0];
1384 pCtrl->m_vertex[1] = vPos[1][1];
1385 pCtrl->m_vertex[2] = vPos[0][2];
1389 PatchControl* pCtrl = m_ctrl.data()+(9*4);
1390 for (std::size_t w=0; w<9; w++, pCtrl++)
1392 pCtrl->m_vertex[0] = vPos[1][0];
1393 pCtrl->m_vertex[1] = vPos[1][1];
1394 pCtrl->m_vertex[2] = vPos[2][2];
1399 ERROR_MESSAGE("this should be unreachable");
1403 else if (eType == eXactCylinder)
1405 int n = (width - 1) / 2; // n = number of segments
1406 setDims(width, height);
1408 // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1409 // vPos[1] = aabb.origin;
1410 // vPos[2] = vector3_added(aabb.origin, aabb.extents);
1413 float f = 1 / cos(M_PI / n);
1414 for(i = 0; i < width; ++i)
1416 float angle = (M_PI * i) / n; // 0 to 2pi
1417 float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * cos(angle) * ((i&1) ? f : 1.0f);
1418 float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle) * ((i&1) ? f : 1.0f);
1419 for(j = 0; j < height; ++j)
1421 float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float)(height - 1));
1423 v = &m_ctrl.data()[j*width+i];
1430 else if (eType == eXactCone)
1432 int n = (width - 1) / 2; // n = number of segments
1433 setDims(width, height);
1435 // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1436 // vPos[1] = aabb.origin;
1437 // vPos[2] = vector3_added(aabb.origin, aabb.extents);
1440 float f = 1 / cos(M_PI / n);
1441 for(i = 0; i < width; ++i)
1443 float angle = (M_PI * i) / n;
1444 for(j = 0; j < height; ++j)
1446 float x = vPos[1][0] + (1.0f - (j / (float)(height - 1))) * (vPos[2][0] - vPos[1][0]) * cos(angle) * ((i&1) ? f : 1.0f);
1447 float y = vPos[1][1] + (1.0f - (j / (float)(height - 1))) * (vPos[2][1] - vPos[1][1]) * sin(angle) * ((i&1) ? f : 1.0f);
1448 float z = vPos[0][2] + (vPos[2][2] - vPos[0][2]) * (j / (float)(height - 1));
1450 v = &m_ctrl.data()[j*width+i];
1457 else if (eType == eXactSphere)
1459 int n = (width - 1) / 2; // n = number of segments (yaw)
1460 int m = (height - 1) / 2; // m = number of segments (pitch)
1461 setDims(width, height);
1463 // vPos[0] = vector3_subtracted(aabb.origin, aabb.extents);
1464 // vPos[1] = aabb.origin;
1465 // vPos[2] = vector3_added(aabb.origin, aabb.extents);
1468 float f = 1 / cos(M_PI / n);
1469 float g = 1 / cos(M_PI / (2*m));
1470 for(i = 0; i < width; ++i)
1472 float angle = (M_PI * i) / n;
1473 for(j = 0; j < height; ++j)
1475 float angle2 = (M_PI * j) / (2*m);
1476 float x = vPos[1][0] + (vPos[2][0] - vPos[1][0]) * sin(angle2) * ((j&1) ? g : 1.0f) * cos(angle) * ((i&1) ? f : 1.0f);
1477 float y = vPos[1][1] + (vPos[2][1] - vPos[1][1]) * sin(angle2) * ((j&1) ? g : 1.0f) * sin(angle) * ((i&1) ? f : 1.0f);
1478 float z = vPos[1][2] + (vPos[2][2] - vPos[1][2]) * -cos(angle2) * ((j&1) ? g : 1.0f);
1480 v = &m_ctrl.data()[j*width+i];
1487 else if (eType == eBevel)
1489 unsigned char *pIndex;
1490 unsigned char pBevIndex[] =
1499 PatchControl* pCtrl = m_ctrl.data();
1500 for(std::size_t h=0; h<3; h++)
1503 for(std::size_t w=0; w<3; w++, pIndex+=2, pCtrl++)
1505 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1506 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1507 pCtrl->m_vertex[2] = vPos[h][2];
1511 else if(eType == eEndCap)
1513 unsigned char *pIndex;
1514 unsigned char pEndIndex[] =
1525 PatchControl* pCtrl = m_ctrl.data();
1526 for(std::size_t h=0; h<3; h++)
1529 for(std::size_t w=0; w<5; w++, pIndex+=2, pCtrl++)
1531 pCtrl->m_vertex[0] = vPos[pIndex[0]][0];
1532 pCtrl->m_vertex[1] = vPos[pIndex[1]][1];
1533 pCtrl->m_vertex[2] = vPos[h][2];
1538 if(eType == eDenseCylinder)
1540 InsertRemove(true, false, true);
1543 if(eType == eVeryDenseCylinder)
1545 InsertRemove(true, false, false);
1546 InsertRemove(true, false, true);
1552 void Patch::RenderDebug(RenderStateFlags state) const
1554 for (std::size_t i = 0; i<m_tess.m_numStrips; i++)
1556 glBegin(GL_QUAD_STRIP);
1557 for (std::size_t j = 0; j<m_tess.m_lenStrips; j++)
1559 glNormal3fv(normal3f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->normal));
1560 glTexCoord2fv(texcoord2f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->texcoord));
1561 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + m_tess.m_indices[i*m_tess.m_lenStrips+j])->vertex));
1567 void RenderablePatchSolid::RenderNormals() const
1569 const std::size_t width = m_tess.m_numStrips+1;
1570 const std::size_t height = m_tess.m_lenStrips>>1;
1572 for(std::size_t i=0;i<width;i++)
1574 for(std::size_t j=0;j<height;j++)
1579 vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
1580 vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->normal), 8)
1583 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
1584 glVertex3fv(&vNormal[0]);
1589 vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
1590 vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->tangent), 8)
1593 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
1594 glVertex3fv(&vNormal[0]);
1599 vertex3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->vertex),
1600 vector3_scaled(normal3f_to_vector3((m_tess.m_vertices.data() + (j*width+i))->bitangent), 8)
1603 glVertex3fv(vertex3f_to_array((m_tess.m_vertices.data() + (j*width+i))->vertex));
1604 glVertex3fv(&vNormal[0]);
1611 #define DEGEN_0a 0x01
1612 #define DEGEN_1a 0x02
1613 #define DEGEN_2a 0x04
1614 #define DEGEN_0b 0x08
1615 #define DEGEN_1b 0x10
1616 #define DEGEN_2b 0x20
1618 #define AVERAGE 0x80
1621 unsigned int subarray_get_degen(PatchControlIter subarray, std::size_t strideU, std::size_t strideV)
1623 unsigned int nDegen = 0;
1624 const PatchControl* p1;
1625 const PatchControl* p2;
1629 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1633 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1636 p1 = subarray + strideV;
1638 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1642 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1645 p1 = subarray + (strideV << 1);
1647 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1651 if(vector3_equal(p1->m_vertex, p2->m_vertex))
1658 inline void deCasteljau3(const Vector3& P0, const Vector3& P1, const Vector3& P2, Vector3& P01, Vector3& P12, Vector3& P012)
1660 P01 = vector3_mid(P0, P1);
1661 P12 = vector3_mid(P1, P2);
1662 P012 = vector3_mid(P01, P12);
1665 inline void BezierInterpolate3( const Vector3& start, Vector3& left, Vector3& mid, Vector3& right, const Vector3& end )
1667 left = vector3_mid(start, mid);
1668 right = vector3_mid(mid, end);
1669 mid = vector3_mid(left, right);
1672 inline void BezierInterpolate2( const Vector2& start, Vector2& left, Vector2& mid, Vector2& right, const Vector2& end )
1674 left[0]= float_mid(start[0], mid[0]);
1675 left[1] = float_mid(start[1], mid[1]);
1676 right[0] = float_mid(mid[0], end[0]);
1677 right[1] = float_mid(mid[1], end[1]);
1678 mid[0] = float_mid(left[0], right[0]);
1679 mid[1] = float_mid(left[1], right[1]);
1683 inline Vector2& texcoord_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1685 return reinterpret_cast<Vector2&>(vertices[index].texcoord);
1688 inline Vector3& vertex_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1690 return reinterpret_cast<Vector3&>(vertices[index].vertex);
1693 inline Vector3& normal_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1695 return reinterpret_cast<Vector3&>(vertices[index].normal);
1698 inline Vector3& tangent_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1700 return reinterpret_cast<Vector3&>(vertices[index].tangent);
1703 inline Vector3& bitangent_for_index(Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1705 return reinterpret_cast<Vector3&>(vertices[index].bitangent);
1708 inline const Vector2& texcoord_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1710 return reinterpret_cast<const Vector2&>(vertices[index].texcoord);
1713 inline const Vector3& vertex_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1715 return reinterpret_cast<const Vector3&>(vertices[index].vertex);
1718 inline const Vector3& normal_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1720 return reinterpret_cast<const Vector3&>(vertices[index].normal);
1723 inline const Vector3& tangent_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1725 return reinterpret_cast<const Vector3&>(vertices[index].tangent);
1728 inline const Vector3& bitangent_for_index(const Array<ArbitraryMeshVertex>& vertices, std::size_t index)
1730 return reinterpret_cast<const Vector3&>(vertices[index].bitangent);
1733 #include "math/curve.h"
1735 inline PatchControl QuadraticBezier_evaluate(const PatchControl* firstPoint, double t)
1737 PatchControl result = { Vector3(0, 0, 0), Vector2(0, 0) };
1738 double denominator = 0;
1741 double weight = BernsteinPolynomial<Zero, Two>::apply(t);
1742 vector3_add(result.m_vertex, vector3_scaled(firstPoint[0].m_vertex, weight));
1743 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[0].m_texcoord, weight));
1744 denominator += weight;
1747 double weight = BernsteinPolynomial<One, Two>::apply(t);
1748 vector3_add(result.m_vertex, vector3_scaled(firstPoint[1].m_vertex, weight));
1749 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[1].m_texcoord, weight));
1750 denominator += weight;
1753 double weight = BernsteinPolynomial<Two, Two>::apply(t);
1754 vector3_add(result.m_vertex, vector3_scaled(firstPoint[2].m_vertex, weight));
1755 vector2_add(result.m_texcoord, vector2_scaled(firstPoint[2].m_texcoord, weight));
1756 denominator += weight;
1759 vector3_divide(result.m_vertex, denominator);
1760 vector2_divide(result.m_texcoord, denominator);
1764 inline Vector3 vector3_linear_interpolated(const Vector3& a, const Vector3& b, double t)
1766 return vector3_added(vector3_scaled(a, 1.0 - t), vector3_scaled(b, t));
1769 inline Vector2 vector2_linear_interpolated(const Vector2& a, const Vector2& b, double t)
1771 return vector2_added(vector2_scaled(a, 1.0 - t), vector2_scaled(b, t));
1774 void normalise_safe(Vector3& normal)
1776 if(!vector3_equal(normal, g_vector3_identity))
1778 vector3_normalise(normal);
1782 inline void QuadraticBezier_evaluate(const PatchControl& a, const PatchControl& b, const PatchControl& c, double t, PatchControl& point, PatchControl& left, PatchControl& right)
1784 left.m_vertex = vector3_linear_interpolated(a.m_vertex, b.m_vertex, t);
1785 left.m_texcoord = vector2_linear_interpolated(a.m_texcoord, b.m_texcoord, t);
1786 right.m_vertex = vector3_linear_interpolated(b.m_vertex, c.m_vertex, t);
1787 right.m_texcoord = vector2_linear_interpolated(b.m_texcoord, c.m_texcoord, t);
1788 point.m_vertex = vector3_linear_interpolated(left.m_vertex, right.m_vertex, t);
1789 point.m_texcoord = vector2_linear_interpolated(left.m_texcoord, right.m_texcoord, t);
1792 void Patch::TesselateSubMatrixFixed(ArbitraryMeshVertex* vertices, std::size_t strideX, std::size_t strideY, unsigned int nFlagsX, unsigned int nFlagsY, PatchControl* subMatrix[3][3])
1794 double incrementU = 1.0 / m_subdivisions_x;
1795 double incrementV = 1.0 / m_subdivisions_y;
1796 const std::size_t width = m_subdivisions_x + 1;
1797 const std::size_t height = m_subdivisions_y + 1;
1799 for(std::size_t i = 0; i != width; ++i)
1801 double tU = (i + 1 == width) ? 1 : i * incrementU;
1802 PatchControl pointX[3];
1803 PatchControl leftX[3];
1804 PatchControl rightX[3];
1805 QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0], rightX[0]);
1806 QuadraticBezier_evaluate(*subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1], rightX[1]);
1807 QuadraticBezier_evaluate(*subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2], rightX[2]);
1809 ArbitraryMeshVertex* p = vertices + i * strideX;
1810 for(std::size_t j = 0; j != height; ++j)
1812 if((j == 0 || j + 1 == height) && (i == 0 || i + 1 == width))
1817 double tV = (j + 1 == height) ? 1 : j * incrementV;
1819 PatchControl pointY[3];
1820 PatchControl leftY[3];
1821 PatchControl rightY[3];
1822 QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0], rightY[0]);
1823 QuadraticBezier_evaluate(*subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1], rightY[1]);
1824 QuadraticBezier_evaluate(*subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2], rightY[2]);
1829 QuadraticBezier_evaluate(pointX[0], pointX[1], pointX[2], tV, point, left, right);
1832 QuadraticBezier_evaluate(pointY[0], pointY[1], pointY[2], tU, point, up, down);
1834 vertex3f_to_vector3(p->vertex) = point.m_vertex;
1835 texcoord2f_to_vector2(p->texcoord) = point.m_texcoord;
1837 ArbitraryMeshVertex a, b, c;
1839 a.vertex = vertex3f_for_vector3(left.m_vertex);
1840 a.texcoord = texcoord2f_for_vector2(left.m_texcoord);
1841 b.vertex = vertex3f_for_vector3(right.m_vertex);
1842 b.texcoord = texcoord2f_for_vector2(right.m_texcoord);
1846 c.vertex = vertex3f_for_vector3(up.m_vertex);
1847 c.texcoord = texcoord2f_for_vector2(up.m_texcoord);
1851 c.vertex = vertex3f_for_vector3(down.m_vertex);
1852 c.texcoord = texcoord2f_for_vector2(down.m_texcoord);
1855 Vector3 normal = vector3_normalised(vector3_cross(right.m_vertex - left.m_vertex, up.m_vertex - down.m_vertex));
1857 Vector3 tangent, bitangent;
1858 ArbitraryMeshTriangle_calcTangents(a, b, c, tangent, bitangent);
1859 vector3_normalise(tangent);
1860 vector3_normalise(bitangent);
1862 if(((nFlagsX & AVERAGE) != 0 && i == 0) || ((nFlagsY & AVERAGE) != 0 && j == 0))
1864 normal3f_to_vector3(p->normal) = vector3_normalised(vector3_added(normal3f_to_vector3(p->normal), normal));
1865 normal3f_to_vector3(p->tangent) = vector3_normalised(vector3_added(normal3f_to_vector3(p->tangent), tangent));
1866 normal3f_to_vector3(p->bitangent) = vector3_normalised(vector3_added(normal3f_to_vector3(p->bitangent), bitangent));
1870 normal3f_to_vector3(p->normal) = normal;
1871 normal3f_to_vector3(p->tangent) = tangent;
1872 normal3f_to_vector3(p->bitangent) = bitangent;
1881 void Patch::TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
1882 std::size_t offStartX, std::size_t offStartY,
1883 std::size_t offEndX, std::size_t offEndY,
1884 std::size_t nFlagsX, std::size_t nFlagsY,
1885 Vector3& left, Vector3& mid, Vector3& right,
1886 Vector2& texLeft, Vector2& texMid, Vector2& texRight,
1889 int newFlagsX, newFlagsY;
1892 Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1;
1894 Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1;
1899 BezierInterpolate2( texcoord_for_index(m_tess.m_vertices, offStartX + offStartY),
1901 texcoord_for_index(m_tess.m_vertices, BX->index + offStartY),
1903 texcoord_for_index(m_tess.m_vertices, offEndX + offStartY) );
1906 BezierInterpolate2( texcoord_for_index(m_tess.m_vertices, offStartX + offEndY),
1908 texcoord_for_index(m_tess.m_vertices, BX->index + offEndY),
1910 texcoord_for_index(m_tess.m_vertices, offEndX + offEndY) );
1914 BezierInterpolate2(texLeft,
1920 if(!BezierCurveTree_isLeaf(BY))
1922 texcoord_for_index(m_tess.m_vertices, BX->index + BY->index) = texTmp;
1926 if(!BezierCurveTree_isLeaf(BX->left))
1928 texcoord_for_index(m_tess.m_vertices, BX->left->index + offStartY) = texcoord_0_0;
1929 texcoord_for_index(m_tess.m_vertices, BX->left->index + offEndY) = texcoord_2_0;
1931 if(!BezierCurveTree_isLeaf(BY))
1933 texcoord_for_index(m_tess.m_vertices, BX->left->index + BY->index) = texcoord_1_0;
1936 if(!BezierCurveTree_isLeaf(BX->right))
1938 texcoord_for_index(m_tess.m_vertices, BX->right->index + offStartY) = texcoord_0_1;
1939 texcoord_for_index(m_tess.m_vertices, BX->right->index + offEndY) = texcoord_2_1;
1941 if(!BezierCurveTree_isLeaf(BY))
1943 texcoord_for_index(m_tess.m_vertices, BX->right->index + BY->index) = texcoord_1_1;
1950 BezierInterpolate3( vertex_for_index(m_tess.m_vertices, offStartX + offStartY),
1952 vertex_for_index(m_tess.m_vertices, BX->index + offStartY),
1954 vertex_for_index(m_tess.m_vertices, offEndX + offStartY) );
1957 BezierInterpolate3( vertex_for_index(m_tess.m_vertices, offStartX + offEndY),
1959 vertex_for_index(m_tess.m_vertices, BX->index + offEndY),
1961 vertex_for_index(m_tess.m_vertices, offEndX + offEndY) );
1966 BezierInterpolate3( left,
1972 if(!BezierCurveTree_isLeaf(BY))
1974 vertex_for_index(m_tess.m_vertices, BX->index + BY->index) = tmp;
1978 if(!BezierCurveTree_isLeaf(BX->left))
1980 vertex_for_index(m_tess.m_vertices, BX->left->index + offStartY) = vertex_0_0;
1981 vertex_for_index(m_tess.m_vertices, BX->left->index + offEndY) = vertex_2_0;
1983 if(!BezierCurveTree_isLeaf(BY))
1985 vertex_for_index(m_tess.m_vertices, BX->left->index + BY->index) = vertex_1_0;
1988 if(!BezierCurveTree_isLeaf(BX->right))
1990 vertex_for_index(m_tess.m_vertices, BX->right->index + offStartY) = vertex_0_1;
1991 vertex_for_index(m_tess.m_vertices, BX->right->index + offEndY) = vertex_2_1;
1993 if(!BezierCurveTree_isLeaf(BY))
1995 vertex_for_index(m_tess.m_vertices, BX->right->index + BY->index) = vertex_1_1;
2003 ArbitraryMeshVertex a, b, c;
2006 if(!(nFlagsX & DEGEN_0a) || !(nFlagsX & DEGEN_0b))
2008 tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
2009 a.vertex = vertex3f_for_vector3(vertex_0_0);
2010 a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
2011 c.vertex = vertex3f_for_vector3(vertex_0_1);
2012 c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
2014 else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
2016 tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
2017 a.vertex = vertex3f_for_vector3(vertex_1_0);
2018 a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
2019 c.vertex = vertex3f_for_vector3(vertex_1_1);
2020 c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
2024 tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
2025 a.vertex = vertex3f_for_vector3(vertex_2_0);
2026 a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
2027 c.vertex = vertex3f_for_vector3(vertex_2_1);
2028 c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
2033 if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
2035 tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
2036 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offEndY].vertex;
2037 b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offEndY].texcoord;
2041 tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
2042 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offStartY].vertex;
2043 b.texcoord = texcoord2f_for_vector2(texTmp); //m_tess.m_vertices[BX->index + offStartY].texcoord;
2047 Vector3 normal, s, t;
2048 ArbitraryMeshVertex& v = m_tess.m_vertices[offStartY + BX->index];
2049 Vector3& p = normal3f_to_vector3(v.normal);
2050 Vector3& ps = normal3f_to_vector3(v.tangent);
2051 Vector3& pt = normal3f_to_vector3(v.bitangent);
2055 normal = vector3_cross(tangentV, tangentU);
2059 normal = vector3_cross(tangentU, tangentV);
2061 normalise_safe(normal);
2063 ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
2067 if(nFlagsX & AVERAGE)
2069 p = vector3_normalised(vector3_added(p, normal));
2070 ps = vector3_normalised(vector3_added(ps, s));
2071 pt = vector3_normalised(vector3_added(pt, t));
2082 ArbitraryMeshVertex a, b, c;
2085 if(!(nFlagsX & DEGEN_2a) || !(nFlagsX & DEGEN_2b))
2087 tangentU = vector3_subtracted(vertex_2_1, vertex_2_0);
2088 a.vertex = vertex3f_for_vector3(vertex_2_0);
2089 a.texcoord = texcoord2f_for_vector2(texcoord_2_0);
2090 c.vertex = vertex3f_for_vector3(vertex_2_1);
2091 c.texcoord = texcoord2f_for_vector2(texcoord_2_1);
2093 else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
2095 tangentU = vector3_subtracted(vertex_1_1, vertex_1_0);
2096 a.vertex = vertex3f_for_vector3(vertex_1_0);
2097 a.texcoord = texcoord2f_for_vector2(texcoord_1_0);
2098 c.vertex = vertex3f_for_vector3(vertex_1_1);
2099 c.texcoord = texcoord2f_for_vector2(texcoord_1_1);
2103 tangentU = vector3_subtracted(vertex_0_1, vertex_0_0);
2104 a.vertex = vertex3f_for_vector3(vertex_0_0);
2105 a.texcoord = texcoord2f_for_vector2(texcoord_0_0);
2106 c.vertex = vertex3f_for_vector3(vertex_0_1);
2107 c.texcoord = texcoord2f_for_vector2(texcoord_0_1);
2112 if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
2114 tangentV = vector3_subtracted(tmp, vertex_for_index(m_tess.m_vertices, BX->index + offStartY));
2115 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offStartY].vertex;
2116 b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offStartY].texcoord;
2120 tangentV = vector3_subtracted(vertex_for_index(m_tess.m_vertices, BX->index + offEndY), tmp);
2121 b.vertex = vertex3f_for_vector3(tmp);//m_tess.m_vertices[BX->index + offEndY].vertex;
2122 b.texcoord = texcoord2f_for_vector2(texTmp);//m_tess.m_vertices[BX->index + offEndY].texcoord;
2125 ArbitraryMeshVertex& v = m_tess.m_vertices[offEndY+BX->index];
2126 Vector3& p = normal3f_to_vector3(v.normal);
2127 Vector3& ps = normal3f_to_vector3(v.tangent);
2128 Vector3& pt = normal3f_to_vector3(v.bitangent);
2132 p = vector3_cross(tangentV, tangentU);
2136 p = vector3_cross(tangentU, tangentV);
2140 ArbitraryMeshTriangle_calcTangents(a, b, c, ps, pt);
2147 newFlagsX = newFlagsY = 0;
2149 if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_0b))
2151 newFlagsX |= DEGEN_0a;
2152 newFlagsX |= DEGEN_0b;
2154 if((nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_1b))
2156 newFlagsX |= DEGEN_1a;
2157 newFlagsX |= DEGEN_1b;
2159 if((nFlagsX & DEGEN_2a) && (nFlagsX & DEGEN_2b))
2161 newFlagsX |= DEGEN_2a;
2162 newFlagsX |= DEGEN_2b;
2164 if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
2166 newFlagsY |= DEGEN_0a;
2167 newFlagsY |= DEGEN_1a;
2168 newFlagsY |= DEGEN_2a;
2170 if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
2172 newFlagsY |= DEGEN_0b;
2173 newFlagsY |= DEGEN_1b;
2174 newFlagsY |= DEGEN_2b;
2178 //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; }
2179 //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; }
2181 newFlagsX |= (nFlagsX & SPLIT);
2182 newFlagsX |= (nFlagsX & AVERAGE);
2184 if(!BezierCurveTree_isLeaf(BY))
2187 int nTemp = newFlagsY;
2189 if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_0b))
2191 newFlagsY |= DEGEN_0a;
2192 newFlagsY |= DEGEN_0b;
2194 newFlagsY |= (nFlagsY & SPLIT);
2195 newFlagsY |= (nFlagsY & AVERAGE);
2197 Vector3& p = vertex_for_index(m_tess.m_vertices, BX->index+BY->index);
2200 Vector2& p2 = texcoord_for_index(m_tess.m_vertices, BX->index+BY->index);
2203 TesselateSubMatrix( BY, BX->left,
2204 offStartY, offStartX,
2206 newFlagsY, newFlagsX,
2207 vertex_0_0, vertex_1_0, vertex_2_0,
2208 texcoord_0_0, texcoord_1_0, texcoord_2_0,
2216 if((nFlagsY & DEGEN_2a) && (nFlagsY & DEGEN_2b)) { newFlagsY |= DEGEN_2a; newFlagsY |= DEGEN_2b; }
2218 TesselateSubMatrix( BY, BX->right,
2219 offStartY, BX->index,
2221 newFlagsY, newFlagsX,
2222 vertex_0_1, vertex_1_1, vertex_2_1,
2223 texcoord_0_1, texcoord_1_1, texcoord_2_1,
2228 if(!BezierCurveTree_isLeaf(BX->left))
2230 TesselateSubMatrix( BX->left, BY,
2231 offStartX, offStartY,
2233 newFlagsX, newFlagsY,
2234 left, vertex_1_0, tmp,
2235 texLeft, texcoord_1_0, texTmp,
2239 if(!BezierCurveTree_isLeaf(BX->right))
2241 TesselateSubMatrix( BX->right, BY,
2242 BX->index, offStartY,
2244 newFlagsX, newFlagsY,
2245 tmp, vertex_1_1, right,
2246 texTmp, texcoord_1_1, texRight,
2253 void Patch::BuildTesselationCurves(EMatrixMajor major)
2255 std::size_t nArrayStride, length, cross, strideU, strideV;
2260 length = (m_width - 1) >> 1;
2267 BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeU);
2272 nArrayStride = m_tess.m_nArrayWidth;
2273 length = (m_height - 1) >> 1;
2280 BezierCurveTreeArray_deleteAll(m_tess.m_curveTreeV);
2285 ERROR_MESSAGE("neither row-major nor column-major");
2289 Array<std::size_t> arrayLength(length);
2290 Array<BezierCurveTree*> pCurveTree(length);
2292 std::size_t nArrayLength = 1;
2296 for(Array<std::size_t>::iterator i = arrayLength.begin(); i != arrayLength.end(); ++i)
2298 *i = Array<std::size_t>::value_type((major == ROW) ? m_subdivisions_x : m_subdivisions_y);
2304 // create a list of the horizontal control curves in each column of sub-patches
2305 // adaptively tesselate each horizontal control curve in the list
2306 // create a binary tree representing the combined tesselation of the list
2307 for(std::size_t i = 0; i != length; ++i)
2309 PatchControl* p1 = m_ctrlTransformed.data() + (i * 2 * strideU);
2310 GSList* pCurveList = 0;
2311 for(std::size_t j = 0; j < cross; j += 2)
2313 PatchControl* p2 = p1+strideV;
2314 PatchControl* p3 = p2+strideV;
2316 // directly taken from one row of control points
2318 BezierCurve* pCurve = new BezierCurve;
2319 pCurve->crd = (p1+strideU)->m_vertex;
2320 pCurve->left = p1->m_vertex;
2321 pCurve->right = (p1+(strideU<<1))->m_vertex;
2322 pCurveList = g_slist_prepend(pCurveList, pCurve);
2330 // interpolated from three columns of control points
2332 BezierCurve* pCurve = new BezierCurve;
2333 pCurve->crd = vector3_mid((p1+strideU)->m_vertex, (p3+strideU)->m_vertex);
2334 pCurve->left = vector3_mid(p1->m_vertex, p3->m_vertex);
2335 pCurve->right = vector3_mid((p1+(strideU<<1))->m_vertex, (p3+(strideU<<1))->m_vertex);
2337 pCurve->crd = vector3_mid(pCurve->crd, (p2+strideU)->m_vertex);
2338 pCurve->left = vector3_mid(pCurve->left, p2->m_vertex);
2339 pCurve->right = vector3_mid(pCurve->right, (p2+(strideU<<1))->m_vertex);
2340 pCurveList = g_slist_prepend(pCurveList, pCurve);
2346 pCurveTree[i] = new BezierCurveTree;
2347 BezierCurveTree_FromCurveList(pCurveTree[i], pCurveList);
2348 for(GSList* l = pCurveList; l != 0; l = g_slist_next(l))
2350 delete static_cast<BezierCurve*>((*l).data);
2352 g_slist_free(pCurveList);
2354 // set up array indices for binary tree
2355 // accumulate subarray width
2356 arrayLength[i] = Array<std::size_t>::value_type(BezierCurveTree_Setup(pCurveTree[i], nArrayLength, nArrayStride) - (nArrayLength - 1));
2357 // accumulate total array width
2358 nArrayLength += arrayLength[i];
2365 m_tess.m_nArrayWidth = nArrayLength;
2366 std::swap(m_tess.m_arrayWidth, arrayLength);
2370 std::swap(m_tess.m_curveTreeU, pCurveTree);
2374 m_tess.m_nArrayHeight = nArrayLength;
2375 std::swap(m_tess.m_arrayHeight, arrayLength);
2379 std::swap(m_tess.m_curveTreeV, pCurveTree);
2385 inline void vertex_assign_ctrl(ArbitraryMeshVertex& vertex, const PatchControl& ctrl)
2387 vertex.vertex = vertex3f_for_vector3(ctrl.m_vertex);
2388 vertex.texcoord = texcoord2f_for_vector2(ctrl.m_texcoord);
2391 inline void vertex_clear_normal(ArbitraryMeshVertex& vertex)
2393 vertex.normal = Normal3f(0, 0, 0);
2394 vertex.tangent = Normal3f(0, 0, 0);
2395 vertex.bitangent = Normal3f(0, 0, 0);
2398 inline void tangents_remove_degenerate(Vector3 tangents[6], Vector2 textureTangents[6], unsigned int flags)
2400 if(flags & DEGEN_0a)
2402 const std::size_t i =
2404 ? (flags & DEGEN_1a)
2405 ? (flags & DEGEN_1b)
2406 ? (flags & DEGEN_2a)
2412 tangents[0] = tangents[i];
2413 textureTangents[0] = textureTangents[i];
2415 if(flags & DEGEN_0b)
2417 const std::size_t i =
2419 ? (flags & DEGEN_1b)
2420 ? (flags & DEGEN_1a)
2421 ? (flags & DEGEN_2b)
2427 tangents[1] = tangents[i];
2428 textureTangents[1] = textureTangents[i];
2430 if(flags & DEGEN_2a)
2432 const std::size_t i =
2434 ? (flags & DEGEN_1a)
2435 ? (flags & DEGEN_1b)
2436 ? (flags & DEGEN_0a)
2442 tangents[4] = tangents[i];
2443 textureTangents[4] = textureTangents[i];
2445 if(flags & DEGEN_2b)
2447 const std::size_t i =
2449 ? (flags & DEGEN_1b)
2450 ? (flags & DEGEN_1a)
2451 ? (flags & DEGEN_0b)
2457 tangents[5] = tangents[i];
2458 textureTangents[5] = textureTangents[i];
2462 void bestTangents00(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2464 if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2466 if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
2471 else if(!(degenerateFlags & DEGEN_0b))
2482 else if(fabs(dot - length) < 0.001) // same direction = degenerate
2484 if(degenerateFlags & DEGEN_0b)
2497 void bestTangents01(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2499 if(fabs(dot - length) < 0.001) // same direction = degenerate
2501 if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
2506 else if(!(degenerateFlags & DEGEN_2b))
2517 else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2519 if(degenerateFlags & DEGEN_2b)
2532 void bestTangents10(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2534 if(fabs(dot - length) < 0.001) // same direction = degenerate
2536 if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
2541 else if(!(degenerateFlags & DEGEN_0a))
2552 else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2554 if(degenerateFlags & DEGEN_0a)
2567 void bestTangents11(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
2569 if(fabs(dot + length) < 0.001) // opposing direction = degenerate
2571 if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
2576 else if(!(degenerateFlags & DEGEN_2a))
2587 else if(fabs(dot - length) < 0.001) // same direction = degenerate
2589 if(degenerateFlags & DEGEN_2a)
2602 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)
2605 Vector3 normal(vector3_cross(tangentX[index0], tangentY[index1]));
2606 if(!vector3_equal(normal, g_vector3_identity))
2608 vector3_add(normal_for_index(m_tess.m_vertices, index), vector3_normalised(normal));
2613 ArbitraryMeshVertex a, b, c;
2614 a.vertex = Vertex3f(0, 0, 0);
2615 a.texcoord = TexCoord2f(0, 0);
2616 b.vertex = vertex3f_for_vector3(tangentX[index0]);
2617 b.texcoord = texcoord2f_for_vector2(tangentS[index0]);
2618 c.vertex = vertex3f_for_vector3(tangentY[index1]);
2619 c.texcoord = texcoord2f_for_vector2(tangentT[index1]);
2622 ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
2623 if(!vector3_equal(s, g_vector3_identity))
2625 vector3_add(tangent_for_index(m_tess.m_vertices, index), vector3_normalised(s));
2627 if(!vector3_equal(t, g_vector3_identity))
2629 vector3_add(bitangent_for_index(m_tess.m_vertices, index), vector3_normalised(t));
2634 const std::size_t PATCH_MAX_VERTEX_ARRAY = 1048576;
2636 void Patch::BuildVertexArray()
2638 const std::size_t strideU = 1;
2639 const std::size_t strideV = m_width;
2641 const std::size_t numElems = m_tess.m_nArrayWidth*m_tess.m_nArrayHeight; // total number of elements in vertex array
2643 const bool bWidthStrips = (m_tess.m_nArrayWidth >= m_tess.m_nArrayHeight); // decide if horizontal strips are longer than vertical
2646 // allocate vertex, normal, texcoord and primitive-index arrays
2647 m_tess.m_vertices.resize(numElems);
2648 m_tess.m_indices.resize(m_tess.m_nArrayWidth *2 * (m_tess.m_nArrayHeight - 1));
2650 // set up strip indices
2653 m_tess.m_numStrips = m_tess.m_nArrayHeight-1;
2654 m_tess.m_lenStrips = m_tess.m_nArrayWidth*2;
2656 for(std::size_t i=0; i<m_tess.m_nArrayWidth; i++)
2658 for(std::size_t j=0; j<m_tess.m_numStrips; j++)
2660 m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(j*m_tess.m_nArrayWidth+i);
2661 m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
2662 // reverse because radiant uses CULL_FRONT
2663 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(j*m_tess.m_nArrayWidth+i);
2664 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex((j+1)*m_tess.m_nArrayWidth+i);
2670 m_tess.m_numStrips = m_tess.m_nArrayWidth-1;
2671 m_tess.m_lenStrips = m_tess.m_nArrayHeight*2;
2673 for(std::size_t i=0; i<m_tess.m_nArrayHeight; i++)
2675 for(std::size_t j=0; j<m_tess.m_numStrips; j++)
2677 m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
2678 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);
2679 // reverse because radiant uses CULL_FRONT
2680 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2+1] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j);
2681 //m_tess.m_indices[(j*m_tess.m_lenStrips)+i*2] = RenderIndex(((m_tess.m_nArrayHeight-1)-i)*m_tess.m_nArrayWidth+j+1);
2688 PatchControlIter pCtrl = m_ctrlTransformed.data();
2689 for(std::size_t j = 0, offStartY = 0; j+1 < m_height; j += 2, pCtrl += (strideU + strideV))
2691 // set up array offsets for this sub-patch
2692 const bool leafY = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeV[j>>1]);
2693 const std::size_t offMidY = (m_patchDef3) ? 0 : m_tess.m_curveTreeV[j>>1]->index;
2694 const std::size_t widthY = m_tess.m_arrayHeight[j>>1] * m_tess.m_nArrayWidth;
2695 const std::size_t offEndY = offStartY + widthY;
2697 for(std::size_t i = 0, offStartX = 0; i+1 < m_width; i += 2, pCtrl += (strideU << 1))
2699 const bool leafX = (m_patchDef3) ? false : BezierCurveTree_isLeaf(m_tess.m_curveTreeU[i>>1]);
2700 const std::size_t offMidX = (m_patchDef3) ? 0 : m_tess.m_curveTreeU[i>>1]->index;
2701 const std::size_t widthX = m_tess.m_arrayWidth[i>>1];
2702 const std::size_t offEndX = offStartX + widthX;
2704 PatchControl *subMatrix[3][3];
2705 subMatrix[0][0] = pCtrl;
2706 subMatrix[0][1] = subMatrix[0][0]+strideU;
2707 subMatrix[0][2] = subMatrix[0][1]+strideU;
2708 subMatrix[1][0] = subMatrix[0][0]+strideV;
2709 subMatrix[1][1] = subMatrix[1][0]+strideU;
2710 subMatrix[1][2] = subMatrix[1][1]+strideU;
2711 subMatrix[2][0] = subMatrix[1][0]+strideV;
2712 subMatrix[2][1] = subMatrix[2][0]+strideU;
2713 subMatrix[2][2] = subMatrix[2][1]+strideU;
2715 // assign on-patch control points to vertex array
2716 if(i == 0 && j == 0)
2718 vertex_clear_normal(m_tess.m_vertices[offStartX + offStartY]);
2720 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offStartY], *subMatrix[0][0]);
2723 vertex_clear_normal(m_tess.m_vertices[offEndX + offStartY]);
2725 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offStartY], *subMatrix[0][2]);
2728 vertex_clear_normal(m_tess.m_vertices[offStartX + offEndY]);
2730 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offEndY], *subMatrix[2][0]);
2732 vertex_clear_normal(m_tess.m_vertices[offEndX + offEndY]);
2733 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offEndY], *subMatrix[2][2]);
2737 // assign remaining control points to vertex array
2740 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offStartY], *subMatrix[0][1]);
2741 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offEndY], *subMatrix[2][1]);
2745 vertex_assign_ctrl(m_tess.m_vertices[offStartX + offMidY], *subMatrix[1][0]);
2746 vertex_assign_ctrl(m_tess.m_vertices[offEndX + offMidY], *subMatrix[1][2]);
2750 vertex_assign_ctrl(m_tess.m_vertices[offMidX + offMidY], *subMatrix[1][1]);
2755 // test all 12 edges for degeneracy
2756 unsigned int nFlagsX = subarray_get_degen(pCtrl, strideU, strideV);
2757 unsigned int nFlagsY = subarray_get_degen(pCtrl, strideV, strideU);
2758 Vector3 tangentX[6], tangentY[6];
2759 Vector2 tangentS[6], tangentT[6];
2761 // set up tangents for each of the 12 edges if they were not degenerate
2762 if(!(nFlagsX & DEGEN_0a))
2764 tangentX[0] = vector3_subtracted(subMatrix[0][1]->m_vertex, subMatrix[0][0]->m_vertex);
2765 tangentS[0] = vector2_subtracted(subMatrix[0][1]->m_texcoord, subMatrix[0][0]->m_texcoord);
2767 if(!(nFlagsX & DEGEN_0b))
2769 tangentX[1] = vector3_subtracted(subMatrix[0][2]->m_vertex, subMatrix[0][1]->m_vertex);
2770 tangentS[1] = vector2_subtracted(subMatrix[0][2]->m_texcoord, subMatrix[0][1]->m_texcoord);
2772 if(!(nFlagsX & DEGEN_1a))
2774 tangentX[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[1][0]->m_vertex);
2775 tangentS[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[1][0]->m_texcoord);
2777 if(!(nFlagsX & DEGEN_1b))
2779 tangentX[3] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[1][1]->m_vertex);
2780 tangentS[3] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[1][1]->m_texcoord);
2782 if(!(nFlagsX & DEGEN_2a))
2784 tangentX[4] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[2][0]->m_vertex);
2785 tangentS[4] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[2][0]->m_texcoord);
2787 if(!(nFlagsX & DEGEN_2b))
2789 tangentX[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[2][1]->m_vertex);
2790 tangentS[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[2][1]->m_texcoord);
2793 if(!(nFlagsY & DEGEN_0a))
2795 tangentY[0] = vector3_subtracted(subMatrix[1][0]->m_vertex, subMatrix[0][0]->m_vertex);
2796 tangentT[0] = vector2_subtracted(subMatrix[1][0]->m_texcoord, subMatrix[0][0]->m_texcoord);
2798 if(!(nFlagsY & DEGEN_0b))
2800 tangentY[1] = vector3_subtracted(subMatrix[2][0]->m_vertex, subMatrix[1][0]->m_vertex);
2801 tangentT[1] = vector2_subtracted(subMatrix[2][0]->m_texcoord, subMatrix[1][0]->m_texcoord);
2803 if(!(nFlagsY & DEGEN_1a))
2805 tangentY[2] = vector3_subtracted(subMatrix[1][1]->m_vertex, subMatrix[0][1]->m_vertex);
2806 tangentT[2] = vector2_subtracted(subMatrix[1][1]->m_texcoord, subMatrix[0][1]->m_texcoord);
2808 if(!(nFlagsY & DEGEN_1b))
2810 tangentY[3] = vector3_subtracted(subMatrix[2][1]->m_vertex, subMatrix[1][1]->m_vertex);
2811 tangentT[3] = vector2_subtracted(subMatrix[2][1]->m_texcoord, subMatrix[1][1]->m_texcoord);
2813 if(!(nFlagsY & DEGEN_2a))
2815 tangentY[4] = vector3_subtracted(subMatrix[1][2]->m_vertex, subMatrix[0][2]->m_vertex);
2816 tangentT[4] = vector2_subtracted(subMatrix[1][2]->m_texcoord, subMatrix[0][2]->m_texcoord);
2818 if(!(nFlagsY & DEGEN_2b))
2820 tangentY[5] = vector3_subtracted(subMatrix[2][2]->m_vertex, subMatrix[1][2]->m_vertex);
2821 tangentT[5] = vector2_subtracted(subMatrix[2][2]->m_texcoord, subMatrix[1][2]->m_texcoord);
2824 // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge
2825 tangents_remove_degenerate(tangentX, tangentS, nFlagsX);
2826 tangents_remove_degenerate(tangentY, tangentT, nFlagsY);
2830 std::size_t index = offStartX + offStartY;
2831 std::size_t index0 = 0;
2832 std::size_t index1 = 0;
2834 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2835 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2837 bestTangents00(nFlagsX, dot, length, index0, index1);
2839 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2844 std::size_t index = offEndX + offStartY;
2845 std::size_t index0 = 1;
2846 std::size_t index1 = 4;
2848 double dot = vector3_dot(tangentX[index0],tangentY[index1]);
2849 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2851 bestTangents10(nFlagsX, dot, length, index0, index1);
2853 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2858 std::size_t index = offStartX + offEndY;
2859 std::size_t index0 = 4;
2860 std::size_t index1 = 1;
2862 double dot = vector3_dot(tangentX[index0], tangentY[index1]);
2863 double length = vector3_length(tangentX[index1]) * vector3_length(tangentY[index1]);
2865 bestTangents01(nFlagsX, dot, length, index0, index1);
2867 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2872 std::size_t index = offEndX + offEndY;
2873 std::size_t index0 = 5;
2874 std::size_t index1 = 5;
2876 double dot = vector3_dot(tangentX[index0],tangentY[index1]);
2877 double length = vector3_length(tangentX[index0]) * vector3_length(tangentY[index1]);
2879 bestTangents11(nFlagsX, dot, length, index0, index1);
2881 accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
2884 //normalise normals that won't be accumulated again
2887 normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offStartY));
2888 normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offStartY));
2889 normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offStartY));
2893 normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offStartY));
2894 normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offStartY));
2895 normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offStartY));
2899 normalise_safe(normal_for_index(m_tess.m_vertices, offStartX + offEndY));
2900 normalise_safe(tangent_for_index(m_tess.m_vertices, offStartX + offEndY));
2901 normalise_safe(bitangent_for_index(m_tess.m_vertices, offStartX + offEndY));
2903 if(i+3 == m_width && j+3 == m_height)
2905 normalise_safe(normal_for_index(m_tess.m_vertices, offEndX + offEndY));
2906 normalise_safe(tangent_for_index(m_tess.m_vertices, offEndX + offEndY));
2907 normalise_safe(bitangent_for_index(m_tess.m_vertices, offEndX + offEndY));
2910 // set flags to average normals between shared edges
2919 // set flags to save evaluating shared edges twice
2923 // if the patch is curved.. tesselate recursively
2924 // use the relevant control curves for this sub-patch
2927 TesselateSubMatrixFixed(m_tess.m_vertices.data() + offStartX + offStartY, 1, m_tess.m_nArrayWidth, nFlagsX, nFlagsY, subMatrix);
2933 TesselateSubMatrix( m_tess.m_curveTreeU[i>>1], m_tess.m_curveTreeV[j>>1],
2934 offStartX, offStartY, offEndX, offEndY, // array offsets
2936 subMatrix[1][0]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[1][2]->m_vertex,
2937 subMatrix[1][0]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[1][2]->m_texcoord,
2942 TesselateSubMatrix( m_tess.m_curveTreeV[j>>1], m_tess.m_curveTreeU[i>>1],
2943 offStartY, offStartX, offEndY, offEndX, // array offsets
2945 subMatrix[0][1]->m_vertex, subMatrix[1][1]->m_vertex, subMatrix[2][1]->m_vertex,
2946 subMatrix[0][1]->m_texcoord, subMatrix[1][1]->m_texcoord, subMatrix[2][1]->m_texcoord,
2951 offStartX = offEndX;
2953 offStartY = offEndY;
2960 class PatchFilterWrapper : public Filter
2964 PatchFilter& m_filter;
2966 PatchFilterWrapper(PatchFilter& filter, bool invert) : m_invert(invert), m_filter(filter)
2969 void setActive(bool active)
2977 bool filter(const Patch& patch)
2979 return m_invert ^ m_filter.filter(patch);
2984 typedef std::list<PatchFilterWrapper> PatchFilters;
2985 PatchFilters g_patchFilters;
2987 void add_patch_filter(PatchFilter& filter, int mask, bool invert)
2989 g_patchFilters.push_back(PatchFilterWrapper(filter, invert));
2990 GlobalFilterSystem().addFilter(g_patchFilters.back(), mask);
2993 bool patch_filtered(Patch& patch)
2995 for(PatchFilters::iterator i = g_patchFilters.begin(); i != g_patchFilters.end(); ++i)
2997 if((*i).active() && (*i).filter(patch))