2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/blenkernel/intern/displist.c
37 #include "MEM_guardedalloc.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_material_types.h"
45 #include "BLI_blenlib.h"
47 #include "BLI_scanfill.h"
48 #include "BLI_utildefines.h"
50 #include "BKE_global.h"
51 #include "BKE_displist.h"
52 #include "BKE_cdderivedmesh.h"
53 #include "BKE_object.h"
54 #include "BKE_mball.h"
55 #include "BKE_material.h"
56 #include "BKE_curve.h"
60 #include "BKE_lattice.h"
61 #include "BKE_modifier.h"
63 #include "BLO_sys_types.h" // for intptr_t support
65 static void boundbox_displist(Object *ob);
67 void BKE_displist_elem_free(DispList *dl)
70 if (dl->verts) MEM_freeN(dl->verts);
71 if (dl->nors) MEM_freeN(dl->nors);
72 if (dl->index) MEM_freeN(dl->index);
73 if (dl->col1) MEM_freeN(dl->col1);
74 if (dl->col2) MEM_freeN(dl->col2);
75 if (dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag);
80 void BKE_displist_free(ListBase *lb)
87 BKE_displist_elem_free(dl);
92 DispList *BKE_displist_find_or_create(ListBase *lb, int type)
103 dl = MEM_callocN(sizeof(DispList), "find_disp");
110 DispList *BKE_displist_find(ListBase *lb, int type)
116 if (dl->type == type)
124 int BKE_displist_has_faces(ListBase *lb)
128 for (dl = lb->first; dl; dl = dl->next) {
129 if (ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
137 void BKE_displist_copy(ListBase *lbn, ListBase *lb)
141 BKE_displist_free(lbn);
145 dln = MEM_dupallocN(dl);
146 BLI_addtail(lbn, dln);
147 dln->verts = MEM_dupallocN(dl->verts);
148 dln->nors = MEM_dupallocN(dl->nors);
149 dln->index = MEM_dupallocN(dl->index);
150 dln->col1 = MEM_dupallocN(dl->col1);
151 dln->col2 = MEM_dupallocN(dl->col2);
153 if (dl->bevelSplitFlag)
154 dln->bevelSplitFlag = MEM_dupallocN(dl->bevelSplitFlag);
160 void BKE_displist_normals_add(ListBase *lb)
163 float *vdata, *ndata, nor[3];
164 float *v1, *v2, *v3, *v4;
165 float *n1, *n2, *n3, *n4;
166 int a, b, p1, p2, p3, p4;
171 if (dl->type == DL_INDEX3) {
172 if (dl->nors == NULL) {
173 dl->nors = MEM_callocN(sizeof(float) * 3, "dlnors");
175 if (dl->verts[2] < 0.0f)
181 else if (dl->type == DL_SURF) {
182 if (dl->nors == NULL) {
183 dl->nors = MEM_callocN(sizeof(float) * 3 * dl->nr * dl->parts, "dlnors");
188 for (a = 0; a < dl->parts; a++) {
190 if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4) == 0)
202 for (; b < dl->nr; b++) {
203 normal_quad_v3(nor, v1, v3, v4, v2);
216 a = dl->parts * dl->nr;
228 void BKE_displist_count(ListBase *lb, int *totvert, int *totface)
236 *totvert += dl->nr * dl->parts;
237 *totface += (dl->nr - 1) * (dl->parts - 1);
242 *totface += dl->parts;
246 *totvert += dl->nr * dl->parts;
254 int BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
256 if ((dl->flag & DL_CYCL_V) == 0 && a == (dl->parts) - 1) {
260 if (dl->flag & DL_CYCL_U) {
262 (*p2) = (*p1) + dl->nr - 1;
263 (*p3) = (*p1) + dl->nr;
264 (*p4) = (*p2) + dl->nr;
270 (*p4) = (*p2) + dl->nr;
271 (*p3) = (*p1) + dl->nr;
275 if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
276 (*p3) -= dl->nr * dl->parts;
277 (*p4) -= dl->nr * dl->parts;
283 /* ****************** make displists ********************* */
285 static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender)
289 BezTriple *bezt, *prevbezt;
297 if (forRender && cu->resolu_ren != 0)
298 resolu = cu->resolu_ren;
302 if (!BKE_nurb_check_valid_u(nu)) ;
303 else if (nu->type == CU_BEZIER) {
307 if (nu->flagu & CU_NURB_CYCLIC) a++;
312 if (a == 0 && (nu->flagu & CU_NURB_CYCLIC))
315 if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT)
320 if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) == 0)
327 dl = MEM_callocN(sizeof(DispList), "makeDispListbez");
328 /* len+1 because of 'forward_diff_bezier' function */
329 dl->verts = MEM_callocN((len + 1) * 3 * sizeof(float), "dlverts");
330 BLI_addtail(dispbase, dl);
333 dl->col = nu->mat_nr;
334 dl->charidx = nu->charidx;
338 if (nu->flagu & CU_NURB_CYCLIC) {
351 if (a == 0 && dl->type == DL_POLY)
354 if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
355 copy_v3_v3(data, prevbezt->vec[1]);
360 for (j = 0; j < 3; j++) {
361 BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
365 data + j, resolu, 3 * sizeof(float));
371 if (a == 0 && dl->type == DL_SEGM) {
372 copy_v3_v3(data, bezt->vec[1]);
379 else if (nu->type == CU_NURBS) {
380 len = (resolu * SEGMENTSU(nu));
382 dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
383 dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts");
384 BLI_addtail(dispbase, dl);
388 dl->col = nu->mat_nr;
389 dl->charidx = nu->charidx;
392 if (nu->flagu & CU_NURB_CYCLIC)
394 else dl->type = DL_SEGM;
395 BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float));
397 else if (nu->type == CU_POLY) {
399 dl = MEM_callocN(sizeof(DispList), "makeDispListpoly");
400 dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts");
401 BLI_addtail(dispbase, dl);
404 dl->col = nu->mat_nr;
405 dl->charidx = nu->charidx;
408 if (nu->flagu & CU_NURB_CYCLIC) dl->type = DL_POLY;
409 else dl->type = DL_SEGM;
414 copy_v3_v3(data, bp->vec);
425 void BKE_displist_fill(ListBase *dispbase, ListBase *to, int flipnormal)
427 ScanFillContext sf_ctx;
428 ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last;
429 ScanFillFace *sf_tri;
430 DispList *dlnew = NULL, *dl;
432 int colnr = 0, charidx = 0, cont = 1, tot, a, *index, nextcol = 0;
435 if (dispbase == NULL)
437 if (dispbase->first == NULL)
445 BLI_scanfill_begin(&sf_ctx);
447 dl = dispbase->first;
449 if (dl->type == DL_POLY) {
450 if (charidx < dl->charidx)
452 else if (charidx == dl->charidx) { /* character with needed index */
453 if (colnr == dl->col) {
454 /* make editverts and edges */
457 sf_vert = sf_vert_new = NULL;
460 sf_vert_last = sf_vert;
462 sf_vert = BLI_scanfill_vert_add(&sf_ctx, f1);
465 if (sf_vert_last == NULL)
466 sf_vert_new = sf_vert;
468 BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
473 if (sf_vert != NULL && sf_vert_new != NULL) {
474 BLI_scanfill_edge_add(&sf_ctx, sf_vert, sf_vert_new);
477 else if (colnr < dl->col) {
478 /* got poly with next material at current char */
487 /* XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) { */
488 if (totvert && (tot = BLI_scanfill_calc(&sf_ctx, FALSE))) {
490 dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
491 dlnew->type = DL_INDEX3;
496 dlnew->index = MEM_mallocN(tot * 3 * sizeof(int), "dlindex");
497 dlnew->verts = MEM_mallocN(totvert * 3 * sizeof(float), "dlverts");
502 sf_vert = sf_ctx.fillvertbase.first;
504 copy_v3_v3(f1, sf_vert->co);
508 sf_vert->tmp.l = totvert;
511 sf_vert = sf_vert->next;
515 sf_tri = sf_ctx.fillfacebase.first;
516 index = dlnew->index;
518 index[0] = (intptr_t)sf_tri->v1->tmp.l;
519 index[1] = (intptr_t)sf_tri->v2->tmp.l;
520 index[2] = (intptr_t)sf_tri->v3->tmp.l;
523 SWAP(int, index[0], index[2]);
526 sf_tri = sf_tri->next;
530 BLI_addhead(to, dlnew);
532 BLI_scanfill_end(&sf_ctx);
535 /* stay at current char but fill polys with next material */
539 /* switch to next char and start filling from first material */
545 /* do not free polys, needed for wireframe display */
548 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
550 ListBase front, back;
551 DispList *dl, *dlnew;
555 front.first = front.last = back.first = back.last = NULL;
557 dl = dispbase->first;
559 if (dl->type == DL_SURF) {
560 if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U) == 0) {
561 if ( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE)) {
562 dlnew = MEM_callocN(sizeof(DispList), "filldisp");
563 BLI_addtail(&front, dlnew);
564 dlnew->verts = fp1 = MEM_mallocN(sizeof(float) * 3 * dl->parts, "filldisp1");
565 dlnew->nr = dl->parts;
567 dlnew->type = DL_POLY;
568 dlnew->col = dl->col;
569 dlnew->charidx = dl->charidx;
581 if ((cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE)) {
582 dlnew = MEM_callocN(sizeof(DispList), "filldisp");
583 BLI_addtail(&back, dlnew);
584 dlnew->verts = fp1 = MEM_mallocN(sizeof(float) * 3 * dl->parts, "filldisp1");
585 dlnew->nr = dl->parts;
587 dlnew->type = DL_POLY;
588 dlnew->col = dl->col;
589 dlnew->charidx = dl->charidx;
591 fp = dl->verts + 3 * (dl->nr - 1);
606 BKE_displist_fill(&front, dispbase, 1);
607 BKE_displist_fill(&back, dispbase, 0);
609 BKE_displist_free(&front);
610 BKE_displist_free(&back);
612 BKE_displist_fill(dispbase, dispbase, 0);
615 static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
617 if (cu->flag & CU_3D)
620 if (dispbase->first && ((DispList *) dispbase->first)->type == DL_SURF) {
621 bevels_to_filledpoly(cu, dispbase);
624 BKE_displist_fill(dispbase, dispbase, 0);
630 * - first point left, last point right
631 * - based on subdivided points in original curve, not on points in taper curve (still)
633 float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
637 if (taperobj == NULL || taperobj->type != OB_CURVE)
640 dl = taperobj->disp.first;
642 BKE_displist_make_curveTypes(scene, taperobj, 0);
643 dl = taperobj->disp.first;
646 float fac = ((float)cur) / (float)(tot - 1);
650 /* horizontal size */
652 dx = dl->verts[3 * (dl->nr - 1)] - minx;
655 for (a = 0; a < dl->nr; a++, fp += 3) {
656 if ((fp[0] - minx) / dx >= fac) {
657 /* interpolate with prev */
659 float fac1 = (fp[-3] - minx) / dx;
660 float fac2 = (fp[0] - minx) / dx;
662 return fp[1] * (fac1 - fac) / (fac1 - fac2) + fp[-2] * (fac - fac2) / (fac1 - fac2);
667 return fp[-2]; // last y coord
674 void BKE_displist_make_mball(Scene *scene, Object *ob)
676 if (!ob || ob->type != OB_MBALL)
679 /* XXX: mball stuff uses plenty of global variables
680 * while this is unchanged updating during render is unsafe
685 BKE_displist_free(&(ob->disp));
687 if (ob->type == OB_MBALL) {
688 if (ob == BKE_mball_basis_find(scene, ob)) {
689 BKE_mball_polygonize(scene, ob, &ob->disp);
690 BKE_mball_texspace_calc(ob);
692 object_deform_mball(ob, &ob->disp);
696 boundbox_displist(ob);
699 void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispbase)
701 BKE_mball_polygonize(scene, ob, dispbase);
702 BKE_mball_texspace_calc(ob);
704 object_deform_mball(ob, dispbase);
707 static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int forRender, int editmode)
709 ModifierData *md = modifiers_getVirtualModifierList(ob);
710 ModifierData *pretessellatePoint;
714 required_mode = eModifierMode_Render;
716 required_mode = eModifierMode_Realtime;
719 required_mode |= eModifierMode_Editmode;
721 pretessellatePoint = NULL;
722 for (; md; md = md->next) {
723 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
725 if (!modifier_isEnabled(scene, md, required_mode))
727 if (mti->type == eModifierTypeType_Constructive)
728 return pretessellatePoint;
730 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
731 pretessellatePoint = md;
733 /* this modifiers are moving point of tessellation automatically
734 * (some of them even can't be applied on tessellated curve), set flag
735 * for incformation button in modifier's header
737 md->mode |= eModifierMode_ApplyOnSpline;
739 else if (md->mode & eModifierMode_ApplyOnSpline) {
740 pretessellatePoint = md;
744 return pretessellatePoint;
747 static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, float (**originalVerts_r)[3],
748 float (**deformedVerts_r)[3], int *numVerts_r)
750 ModifierData *md = modifiers_getVirtualModifierList(ob);
751 ModifierData *pretessellatePoint;
752 Curve *cu = ob->data;
753 ListBase *nurb = BKE_curve_nurbs_get(cu);
755 const int editmode = (!forRender && cu->editnurb);
756 ModifierApplyFlag app_flag = 0;
757 float (*originalVerts)[3] = NULL;
758 float (*deformedVerts)[3] = NULL;
759 float *keyVerts = NULL;
763 app_flag |= MOD_APPLY_USECACHE;
765 app_flag |= MOD_APPLY_RENDER;
766 required_mode = eModifierMode_Render;
769 required_mode = eModifierMode_Realtime;
771 pretessellatePoint = curve_get_tessellate_point(scene, ob, forRender, editmode);
774 required_mode |= eModifierMode_Editmode;
776 if (cu->editnurb == NULL) {
777 keyVerts = do_ob_key(scene, ob);
780 /* split coords from key data, the latter also includes
781 * tilts, which is passed through in the modifier stack.
782 * this is also the reason curves do not use a virtual
783 * shape key modifier yet. */
784 deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts);
785 originalVerts = MEM_dupallocN(deformedVerts);
786 numVerts = BKE_nurbList_verts_count(nurb);
790 if (pretessellatePoint) {
791 for (; md; md = md->next) {
792 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
796 if ((md->mode & required_mode) != required_mode)
798 if (mti->isDisabled && mti->isDisabled(md, forRender))
800 if (mti->type != eModifierTypeType_OnlyDeform)
803 if (!deformedVerts) {
804 deformedVerts = BKE_curve_vertexCos_get(cu, nurb, &numVerts);
805 originalVerts = MEM_dupallocN(deformedVerts);
808 mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag);
810 if (md == pretessellatePoint)
816 BK_curve_vertexCos_apply(cu, nurb, deformedVerts);
817 if (keyVerts) /* these are not passed through modifier stack */
818 BKE_curve_keyVertexTilts_apply(cu, nurb, keyVerts);
823 *originalVerts_r = originalVerts;
824 *deformedVerts_r = deformedVerts;
825 *numVerts_r = numVerts;
828 static float (*displist_get_allverts(ListBase * dispbase, int *totvert))[3]
831 float (*allverts)[3], *fp;
835 for (dl = dispbase->first; dl; dl = dl->next)
836 *totvert += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr;
838 allverts = MEM_mallocN((*totvert) * sizeof(float) * 3, "displist_get_allverts allverts");
839 fp = (float *)allverts;
840 for (dl = dispbase->first; dl; dl = dl->next) {
841 int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
842 memcpy(fp, dl->verts, sizeof(float) * offs);
849 static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
854 fp = (float *)allverts;
855 for (dl = dispbase->first; dl; dl = dl->next) {
856 int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
857 memcpy(dl->verts, fp, sizeof(float) * offs);
862 static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal,
863 int forRender, float (*originalVerts)[3], float (*deformedVerts)[3])
865 ModifierData *md = modifiers_getVirtualModifierList(ob);
866 ModifierData *pretessellatePoint;
867 Curve *cu = ob->data;
868 ListBase *nurb = BKE_curve_nurbs_get(cu);
869 int required_mode = 0, totvert = 0;
870 int editmode = (!forRender && cu->editnurb);
871 DerivedMesh *dm = NULL, *ndm;
872 float (*vertCos)[3] = NULL;
873 int useCache = !forRender;
874 ModifierApplyFlag app_flag = 0;
877 app_flag |= MOD_APPLY_RENDER;
878 required_mode = eModifierMode_Render;
881 required_mode = eModifierMode_Realtime;
883 pretessellatePoint = curve_get_tessellate_point(scene, ob, forRender, editmode);
886 required_mode |= eModifierMode_Editmode;
888 if (pretessellatePoint) {
889 md = pretessellatePoint->next;
892 if (derivedFinal && *derivedFinal) {
893 (*derivedFinal)->release(*derivedFinal);
896 for (; md; md = md->next) {
897 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
898 ModifierApplyFlag appf = app_flag;
902 if ((md->mode & required_mode) != required_mode)
904 if (mti->isDisabled && mti->isDisabled(md, forRender))
907 if (mti->type == eModifierTypeType_OnlyDeform ||
908 (mti->type == eModifierTypeType_DeformOrConstruct && !dm)) {
910 appf |= MOD_APPLY_USECACHE;
913 totvert = dm->getNumVerts(dm);
914 vertCos = MEM_mallocN(sizeof(*vertCos) * totvert, "dfmv");
915 dm->getVertCos(dm, vertCos);
918 mti->deformVerts(md, ob, dm, vertCos, totvert, appf);
922 vertCos = displist_get_allverts(dispbase, &totvert);
925 mti->deformVerts(md, ob, NULL, vertCos, totvert, appf);
930 /* makeDisplistCurveTypes could be used for beveling, where derived mesh
931 * is totally unnecessary, so we could stop modifiers applying
932 * when we found constructive modifier but derived mesh is unwanted result
939 DerivedMesh *tdm = CDDM_copy(dm);
943 CDDM_apply_vert_coords(dm, vertCos);
944 CDDM_calc_normals_mapping(dm);
949 displist_apply_allverts(dispbase, vertCos);
952 if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
953 curve_to_filledpoly(cu, nurb, dispbase);
956 dm = CDDM_from_curve_customDB(ob, dispbase);
958 CDDM_calc_normals_mapping(dm);
962 /* Vertex coordinates were applied to necessary data, could free it */
968 appf |= MOD_APPLY_USECACHE;
969 ndm = mti->applyModifier(md, ob, dm, appf);
972 /* Modifier returned a new derived mesh */
974 if (dm && dm != ndm) /* Modifier */
983 DerivedMesh *tdm = CDDM_copy(dm);
987 CDDM_apply_vert_coords(dm, vertCos);
988 CDDM_calc_normals_mapping(dm);
992 displist_apply_allverts(dispbase, vertCos);
1000 DM_ensure_tessface(dm); /* needed for drawing */
1001 (*derivedFinal) = dm;
1004 if (deformedVerts) {
1005 BK_curve_vertexCos_apply(ob->data, nurb, originalVerts);
1006 MEM_freeN(originalVerts);
1007 MEM_freeN(deformedVerts);
1011 static void displist_surf_indices(DispList *dl)
1013 int a, b, p1, p2, p3, p4;
1018 index = dl->index = MEM_mallocN(4 * sizeof(int) * (dl->parts + 1) * (dl->nr + 1), "index array nurbs");
1020 for (a = 0; a < dl->parts; a++) {
1022 if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4) == 0)
1025 for (; b < dl->nr; b++, index += 4) {
1039 static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
1042 ListBase disp = {NULL, NULL};
1044 /* OrcoDM should be created from underformed disp lists */
1045 BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
1046 dm = CDDM_from_curve_customDB(ob, &disp);
1048 BKE_displist_free(&disp);
1053 static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
1055 float (*orco)[3], (*layerorco)[3];
1057 Curve *cu = ob->data;
1059 totvert = dm->getNumVerts(dm);
1062 orco = MEM_callocN(sizeof(float) * 3 * totvert, "dm orco");
1064 if (orcodm->getNumVerts(orcodm) == totvert)
1065 orcodm->getVertCos(orcodm, orco);
1067 dm->getVertCos(dm, orco);
1070 orco = (float(*)[3])BKE_curve_make_orco(scene, ob);
1073 for (a = 0; a < totvert; a++) {
1074 float *co = orco[a];
1075 co[0] = (co[0] - cu->loc[0]) / cu->size[0];
1076 co[1] = (co[1] - cu->loc[1]) / cu->size[1];
1077 co[2] = (co[2] - cu->loc[2]) / cu->size[2];
1080 if ((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
1081 memcpy(layerorco, orco, sizeof(float) * totvert);
1085 DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
1088 static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender)
1090 /* this function represents logic of mesh's orcodm calculation
1091 * for displist-based objects
1094 ModifierData *md = modifiers_getVirtualModifierList(ob);
1095 ModifierData *pretessellatePoint;
1096 Curve *cu = ob->data;
1098 int editmode = (!forRender && cu->editnurb);
1099 DerivedMesh *ndm, *orcodm = NULL;
1100 const ModifierApplyFlag app_flag = forRender ? MOD_APPLY_RENDER : 0;
1103 required_mode = eModifierMode_Render;
1105 required_mode = eModifierMode_Realtime;
1107 pretessellatePoint = curve_get_tessellate_point(scene, ob, forRender, editmode);
1110 required_mode |= eModifierMode_Editmode;
1112 if (pretessellatePoint) {
1113 md = pretessellatePoint->next;
1116 for (; md; md = md->next) {
1117 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1121 if ((md->mode & required_mode) != required_mode)
1123 if (mti->isDisabled && mti->isDisabled(md, forRender))
1125 if (mti->type != eModifierTypeType_Constructive)
1129 orcodm = create_orco_dm(scene, ob);
1131 ndm = mti->applyModifier(md, ob, orcodm, app_flag);
1134 /* if the modifier returned a new dm, release the old one */
1135 if (orcodm && orcodm != ndm) {
1136 orcodm->release(orcodm);
1142 /* add an orco layer if needed */
1143 add_orco_dm(scene, ob, derivedFinal, orcodm);
1146 orcodm->release(orcodm);
1149 void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
1150 DerivedMesh **derivedFinal, int forRender, int forOrco)
1154 Curve *cu = ob->data;
1159 float (*originalVerts)[3];
1160 float (*deformedVerts)[3];
1162 if (!forRender && cu->editnurb)
1163 nubase = BKE_curve_editNurbs_get(cu);
1168 curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
1170 for (nu = nubase->first; nu; nu = nu->next) {
1171 if (forRender || nu->hide == 0) {
1172 int resolu = nu->resolu, resolv = nu->resolv;
1176 resolu = cu->resolu_ren;
1178 resolv = cu->resolv_ren;
1181 if (nu->pntsv == 1) {
1182 len = SEGMENTSU(nu) * resolu;
1184 dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
1185 dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts");
1187 BLI_addtail(dispbase, dl);
1190 dl->col = nu->mat_nr;
1191 dl->charidx = nu->charidx;
1193 /* dl->rt will be used as flag for render face and */
1194 /* CU_2D conflicts with R_NOPUNOFLIP */
1195 dl->rt = nu->flag & ~CU_2D;
1198 if (nu->flagu & CU_NURB_CYCLIC) dl->type = DL_POLY;
1199 else dl->type = DL_SEGM;
1201 BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float));
1204 len = (nu->pntsu * resolu) * (nu->pntsv * resolv);
1206 dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
1207 dl->verts = MEM_callocN(len * 3 * sizeof(float), "dlverts");
1208 BLI_addtail(dispbase, dl);
1210 dl->col = nu->mat_nr;
1211 dl->charidx = nu->charidx;
1213 /* dl->rt will be used as flag for render face and */
1214 /* CU_2D conflicts with R_NOPUNOFLIP */
1215 dl->rt = nu->flag & ~CU_2D;
1220 dl->parts = (nu->pntsu * resolu); /* in reverse, because makeNurbfaces works that way */
1221 dl->nr = (nu->pntsv * resolv);
1222 if (nu->flagv & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_U; /* reverse too! */
1223 if (nu->flagu & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_V;
1225 BKE_nurb_makeFaces(nu, data, 0, resolu, resolv);
1227 /* gl array drawing: using indices */
1228 displist_surf_indices(dl);
1233 /* make copy of 'undeformed" displist for texture space calculation
1234 * actually, it's not totally undeformed -- pre-tessellation modifiers are
1235 * already applied, thats how it worked for years, so keep for compatibility (sergey) */
1236 BKE_displist_copy(&cu->disp, dispbase);
1239 BKE_curve_texspace_calc(cu);
1243 curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal,
1244 forRender, originalVerts, deformedVerts);
1248 static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float widfac, float fac, float **data_r)
1250 float *fp, *data = *data_r;
1254 for (b = 0; b < dlb->nr; b++, fp += 3, data += 3) {
1255 if (cu->flag & CU_3D) {
1258 vec[0] = fp[1] + widfac;
1262 mul_qt_v3(bevp->quat, vec);
1264 data[0] = bevp->vec[0] + fac * vec[0];
1265 data[1] = bevp->vec[1] + fac * vec[1];
1266 data[2] = bevp->vec[2] + fac * vec[2];
1269 data[0] = bevp->vec[0] + fac * (widfac + fp[1]) * bevp->sina;
1270 data[1] = bevp->vec[1] + fac * (widfac + fp[1]) * bevp->cosa;
1271 data[2] = bevp->vec[2] + fac * fp[2];
1278 static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *dispbase)
1284 dl = MEM_callocN(sizeof(DispList), "makeDispListbev2");
1285 dl->verts = data = MEM_callocN(3 * sizeof(float) * dlb->nr, "dlverts");
1291 dl->col = nu->mat_nr;
1292 dl->charidx = nu->charidx;
1294 /* dl->rt will be used as flag for render face and */
1295 /* CU_2D conflicts with R_NOPUNOFLIP */
1296 dl->rt = nu->flag & ~CU_2D;
1298 for (b = 0; b < dlb->nr; b++, prev_fp += 3, data += 3)
1299 copy_v3_v3(data, prev_fp);
1301 BLI_addtail(dispbase, dl);
1304 static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
1305 DerivedMesh **derivedFinal, int forRender, int forOrco)
1307 Curve *cu = ob->data;
1309 /* we do allow duplis... this is only displist on curve level */
1310 if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1312 if (ob->type == OB_SURF) {
1313 BKE_displist_make_surf(scene, ob, dispbase, derivedFinal, forRender, forOrco);
1315 else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
1318 float (*originalVerts)[3];
1319 float (*deformedVerts)[3];
1322 nubase = BKE_curve_nurbs_get(cu);
1324 BLI_freelistN(&(cu->bev));
1326 if (cu->path) free_path(cu->path);
1329 if (ob->type == OB_FONT)
1330 BKE_vfont_to_curve(G.main, scene, ob, 0);
1333 curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
1335 BKE_curve_bevelList_make(ob);
1337 /* If curve has no bevel will return nothing */
1338 BKE_curve_bevel_make(scene, ob, &dlbev, forRender);
1340 /* no bevel or extrude, and no width correction? */
1341 if (!dlbev.first && cu->width == 1.0f) {
1342 curve_to_displist(cu, nubase, dispbase, forRender);
1345 float widfac = cu->width - 1.0f;
1346 BevList *bl = cu->bev.first;
1347 Nurb *nu = nubase->first;
1349 for (; bl && nu; bl = bl->next, nu = nu->next) {
1355 if (bl->nr) { /* blank bevel lists can happen */
1357 /* exception handling; curve without bevel or extrude, with width correction */
1358 if (dlbev.first == NULL) {
1359 dl = MEM_callocN(sizeof(DispList), "makeDispListbev");
1360 dl->verts = MEM_callocN(3 * sizeof(float) * bl->nr, "dlverts");
1361 BLI_addtail(dispbase, dl);
1363 if (bl->poly != -1) dl->type = DL_POLY;
1364 else dl->type = DL_SEGM;
1366 if (dl->type == DL_SEGM) dl->flag = (DL_FRONT_CURVE | DL_BACK_CURVE);
1370 dl->col = nu->mat_nr;
1371 dl->charidx = nu->charidx;
1373 /* dl->rt will be used as flag for render face and */
1374 /* CU_2D conflicts with R_NOPUNOFLIP */
1375 dl->rt = nu->flag & ~CU_2D;
1378 bevp = (BevPoint *)(bl + 1);
1381 data[0] = bevp->vec[0] + widfac * bevp->sina;
1382 data[1] = bevp->vec[1] + widfac * bevp->cosa;
1383 data[2] = bevp->vec[2];
1390 ListBase bottom_capbase = {NULL, NULL};
1391 ListBase top_capbase = {NULL, NULL};
1393 for (dlb = dlbev.first; dlb; dlb = dlb->next) {
1394 int i, start, steps;
1395 float bevfac1 = MIN2(cu->bevfac1, cu->bevfac2), bevfac2 = MAX2(cu->bevfac1, cu->bevfac2);
1396 float firstblend = 0.0f, lastblend = 0.0f;
1398 if (cu->bevfac1 - cu->bevfac2 == 0.0f)
1401 start = (int)(bevfac1 * (bl->nr - 1));
1402 steps = 2 + (int)((bevfac2) * (bl->nr - 1)) - start;
1403 firstblend = 1.0f - ((float)bevfac1 * (bl->nr - 1) - (int)((float)bevfac1 * (bl->nr - 1)));
1404 lastblend = (float)bevfac2 * (bl->nr - 1) - (int)((float)bevfac2 * (bl->nr - 1));
1406 if (steps > bl->nr) {
1411 /* for each part of the bevel use a separate displblock */
1412 dl = MEM_callocN(sizeof(DispList), "makeDispListbev1");
1413 dl->verts = data = MEM_callocN(3 * sizeof(float) * dlb->nr * steps, "dlverts");
1414 BLI_addtail(dispbase, dl);
1418 dl->flag = dlb->flag & (DL_FRONT_CURVE | DL_BACK_CURVE);
1419 if (dlb->type == DL_POLY) dl->flag |= DL_CYCL_U;
1420 if (bl->poly >= 0) dl->flag |= DL_CYCL_V;
1424 dl->col = nu->mat_nr;
1425 dl->charidx = nu->charidx;
1427 /* dl->rt will be used as flag for render face and */
1428 /* CU_2D conflicts with R_NOPUNOFLIP */
1429 dl->rt = nu->flag & ~CU_2D;
1431 dl->bevelSplitFlag = MEM_callocN(sizeof(*dl->col2) * ((steps + 0x1F) >> 5),
1434 /* for each point of poly make a bevel piece */
1435 bevp = (BevPoint *)(bl + 1) + start;
1436 for (i = start, a = 0; a < steps; i++, bevp++, a++) {
1438 float *cur_data = data;
1440 if (cu->taperobj == NULL) {
1441 if ( (cu->bevobj != NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
1445 fac = BKE_displist_calc_taper(scene, cu->taperobj, i, bl->nr);
1448 if (bevp->split_tag) {
1449 dl->bevelSplitFlag[a >> 5] |= 1 << (a & 0x1F);
1452 /* rotate bevel piece and write in data */
1453 rotateBevelPiece(cu, bevp, dlb, widfac, fac, &data);
1455 if (a == 1 || a == steps - 1) {
1456 float *cur_fp = cur_data, *prev_fp = cur_data - 3 * dlb->nr;
1459 for (b = 0; b < dlb->nr; b++, prev_fp += 3, cur_fp += 3) {
1460 float cur[3], prev[3];
1462 copy_v3_v3(cur, cur_fp);
1463 copy_v3_v3(prev, prev_fp);
1466 interp_v3_v3v3(prev, cur_fp, prev_fp, firstblend);
1468 interp_v3_v3v3(cur, prev_fp, cur_fp, lastblend);
1470 copy_v3_v3(cur_fp, cur);
1471 copy_v3_v3(prev_fp, prev);
1475 if (cu->bevobj && (cu->flag & CU_FILL_CAPS)) {
1477 fillBevelCap(nu, dlb, cur_data - 3 * dlb->nr, &bottom_capbase);
1479 fillBevelCap(nu, dlb, cur_data, &top_capbase);
1483 /* gl array drawing: using indices */
1484 displist_surf_indices(dl);
1487 if (bottom_capbase.first) {
1488 BKE_displist_fill(&bottom_capbase, dispbase, 1);
1489 BKE_displist_fill(&top_capbase, dispbase, 0);
1490 BKE_displist_free(&bottom_capbase);
1491 BKE_displist_free(&top_capbase);
1497 BKE_displist_free(&dlbev);
1500 if (!(cu->flag & CU_DEFORM_FILL)) {
1501 curve_to_filledpoly(cu, nubase, dispbase);
1504 if ((cu->flag & CU_PATH) && !forOrco)
1507 /* make copy of 'undeformed" displist for texture space calculation
1508 * actually, it's not totally undeformed -- pre-tessellation modifiers are
1509 * already applied, thats how it worked for years, so keep for compatibility (sergey) */
1510 BKE_displist_copy(&cu->disp, dispbase);
1513 BKE_curve_texspace_calc(cu);
1517 curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, originalVerts, deformedVerts);
1519 if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
1520 curve_to_filledpoly(cu, nubase, dispbase);
1525 void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
1527 Curve *cu = ob->data;
1530 /* The same check for duplis as in do_makeDispListCurveTypes.
1531 * Happens when curve used for constraint/bevel was converted to mesh.
1532 * check there is still needed for render displist and orco displists. */
1533 if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
1536 BKE_displist_free(&(ob->disp));
1537 dispbase = &(ob->disp);
1538 BKE_displist_free(dispbase);
1540 /* free displist used for textspace */
1541 BKE_displist_free(&cu->disp);
1543 do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco);
1545 if (ob->derivedFinal) {
1546 DM_set_object_boundbox(ob, ob->derivedFinal);
1549 boundbox_displist(ob);
1551 /* if there is no derivedMesh, object's boundbox is unneeded */
1559 void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
1560 DerivedMesh **derivedFinal, int forOrco)
1562 do_makeDispListCurveTypes(scene, ob, dispbase, derivedFinal, 1, forOrco);
1565 void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
1567 do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1);
1570 /* add Orco layer to the displist object which has got derived mesh and return orco */
1571 float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender)
1575 if (derivedFinal == NULL)
1576 derivedFinal = ob->derivedFinal;
1578 if (!derivedFinal->getVertDataArray(derivedFinal, CD_ORCO)) {
1579 curve_calc_orcodm(scene, ob, derivedFinal, forRender);
1582 orco = derivedFinal->getVertDataArray(derivedFinal, CD_ORCO);
1585 orco = MEM_dupallocN(orco);
1591 /* this is confusing, there's also min_max_object, appplying the obmat... */
1592 static void boundbox_displist(Object *ob)
1594 BoundBox *bb = NULL;
1595 float min[3], max[3];
1600 INIT_MINMAX(min, max);
1602 if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1603 Curve *cu = ob->data;
1606 if (cu->bb == NULL) cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
1609 for (dl = ob->disp.first; dl; dl = dl->next) {
1610 tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
1612 for (a = 0; a < tot; a++, vert += 3) {
1613 minmax_v3v3_v3(min, max, vert);
1619 /* there's no geometry in displist, use zero-sized boundbox */
1627 BKE_boundbox_init_from_minmax(bb, min, max);