diff --git a/.travis.yml b/.travis.yml index 64cc557d5b..2c4efe8a65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ script: notifications: irc: channels: - - "chat.freenode.net#panda3d" + - secure: "jfwHT9RHAVOGRGTMY8TpYKJI6rq8nFoIj41Y0soZdJQNWtSSFEK9AyzZeMY+2dHga7cR/X+/0NWZ2ehhedTnd9FvlzOnMWWC3K0I/b3XWbEdVEqIZnggFkKGqs82Gy3omguRC63yWupeJCcSCckIhoWbLzWy6xV8lF5WC80iXi8=" on_success: change on_failure: always use_notice: true diff --git a/direct/src/showbase/Transitions.py b/direct/src/showbase/Transitions.py index 9e05daad3e..54d7bd2baa 100644 --- a/direct/src/showbase/Transitions.py +++ b/direct/src/showbase/Transitions.py @@ -89,6 +89,8 @@ class Transitions: self.fade.setBin('unsorted', 0) self.fade.setColor(0,0,0,0) + self.fade.setScale(max(base.a2dRight, base.a2dTop)) + def getFadeInIval(self, t=0.5, finishIval=None, blendType='noBlend'): """ Returns an interval without starting it. This is particularly useful in @@ -97,8 +99,7 @@ class Transitions: #self.noTransitions() masad: this creates a one frame pop, is it necessary? self.loadFade() - parent = aspect2d if self.fadeModel else render2d - transitionIval = Sequence(Func(self.fade.reparentTo, parent, DGG.FADE_SORT_INDEX), + transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough), # in case aspect2d is hidden for some reason self.lerpFunc(self.fade, t, self.alphaOff, @@ -120,8 +121,7 @@ class Transitions: self.noTransitions() self.loadFade() - parent = aspect2d if self.fadeModel else render2d - transitionIval = Sequence(Func(self.fade.reparentTo, parent, DGG.FADE_SORT_INDEX), + transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX), Func(self.fade.showThrough), # in case aspect2d is hidden for some reason self.lerpFunc(self.fade, t, self.alphaOn, @@ -181,8 +181,7 @@ class Transitions: self.noTransitions() self.loadFade() - parent = aspect2d if self.fadeModel else render2d - self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX) + self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn) elif ConfigVariableBool('no-loading-screen', False): if finishIval: @@ -215,8 +214,7 @@ class Transitions: self.noTransitions() self.loadFade() - parent = aspect2d if self.fadeModel else render2d - self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX) + self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(self.alphaOn[0], self.alphaOn[1], self.alphaOn[2], @@ -232,8 +230,7 @@ class Transitions: self.noTransitions() self.loadFade() - parent = aspect2d if self.fadeModel else render2d - self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX) + self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX) self.fade.setColor(color) def noFade(self): diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 58e7e99ad8..7ae33f9ac5 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -52,10 +52,11 @@ builtinInitFuncs = { '__builtin__': None, 'sys': None, 'exceptions': None, - '_imp': 'PyInit_imp', '_warnings': '_PyWarnings_Init', 'marshal': 'PyMarshal_Init', } +if sys.version_info < (3, 7): + builtinInitFuncs['_imp'] = 'PyInit_imp' # These are modules that are not found normally for these modules. Add them # to an include list so users do not have to do this manually. @@ -325,7 +326,7 @@ frozenMainCode = """ extern void PyWinFreeze_ExeInit(void); extern void PyWinFreeze_ExeTerm(void); -extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab); +extern PyAPI_FUNC(int) PyImport_ExtendInittab(struct _inittab *newtab); #endif /* Main program */ @@ -1522,7 +1523,7 @@ class Freezer: libName = module.split('.')[-1] initFunc = builtinInitFuncs.get(module, 'PyInit_' + libName) if initFunc: - text += 'extern DL_IMPORT(PyObject) *%s(void);\n' % (initFunc) + text += 'extern PyAPI_FUNC(PyObject) *%s(void);\n' % (initFunc) text += '\n' if sys.platform == "win32": @@ -1545,7 +1546,7 @@ class Freezer: libName = module.split('.')[-1] initFunc = builtinInitFuncs.get(module, 'init' + libName) if initFunc: - text += 'extern DL_IMPORT(void) %s(void);\n' % (initFunc) + text += 'extern PyAPI_FUNC(void) %s(void);\n' % (initFunc) text += '\n' if sys.platform == "win32": diff --git a/dtool/src/interrogatedb/dtool_super_base.cxx b/dtool/src/interrogatedb/dtool_super_base.cxx index 01dcdef077..9422084299 100644 --- a/dtool/src/interrogatedb/dtool_super_base.cxx +++ b/dtool/src/interrogatedb/dtool_super_base.cxx @@ -15,6 +15,16 @@ #ifdef HAVE_PYTHON +static PyMemberDef standard_type_members[] = { + {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"}, + {(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"}, + {(char *)"this_const", T_BOOL, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"}, +// {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature), +// READONLY, (char *)"A type check signature"}, + {(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"}, + {nullptr} /* Sentinel */ +}; + static PyObject *GetSuperBase(PyObject *self) { Dtool_PyTypedObject *super_base = Dtool_GetSuperBase(); Py_XINCREF((PyTypeObject *)super_base); // order is important .. this is used for static functions diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index 234a41b873..5c984cec82 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -12,16 +12,6 @@ using std::string; -PyMemberDef standard_type_members[] = { - {(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"}, - {(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"}, - {(char *)"this_const", T_BOOL, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"}, -// {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature), -// READONLY, (char *)"A type check signature"}, - {(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"}, - {nullptr} /* Sentinel */ -}; - /** */ diff --git a/dtool/src/interrogatedb/py_panda.h b/dtool/src/interrogatedb/py_panda.h index fa7981697b..ec2765e77a 100644 --- a/dtool/src/interrogatedb/py_panda.h +++ b/dtool/src/interrogatedb/py_panda.h @@ -67,9 +67,6 @@ struct Dtool_PyInstDef { bool _is_const; }; -// A Offset Dictionary Defining How to read the Above Object.. -extern PyMemberDef standard_type_members[]; - // The Class Definition Structor For a Dtool python type. struct Dtool_PyTypedObject { // Standard Python Features.. diff --git a/panda/src/gobj/geom.cxx b/panda/src/gobj/geom.cxx index 8bede7327b..3b6dee026a 100644 --- a/panda/src/gobj/geom.cxx +++ b/panda/src/gobj/geom.cxx @@ -1338,7 +1338,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const { // Now actually compute the bounding volume. We do this by using // calc_tight_bounds to determine our box first. LPoint3 pmin, pmax; - PN_stdfloat sq_center_dist; + PN_stdfloat sq_center_dist = 0.0f; bool found_any = false; do_calc_tight_bounds(pmin, pmax, sq_center_dist, found_any, vertex_data, false, LMatrix4::ident_mat(), @@ -1379,7 +1379,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const { LPoint3 aabb_center = (pmin + pmax) * 0.5f; PN_stdfloat best_sq_radius = (pmax - aabb_center).length_squared(); - if (btype != BoundingVolume::BT_fastest && + if (btype != BoundingVolume::BT_fastest && best_sq_radius > 0.0f && aabb_center.length_squared() / best_sq_radius >= (0.2f * 0.2f)) { // Hmm, this is an off-center model. Maybe we can do a better job // by calculating the bounding sphere from the AABB center. @@ -1389,7 +1389,8 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const { do_calc_sphere_radius(aabb_center, better_sq_radius, found_any, vertex_data, cdata, current_thread); - if (found_any && better_sq_radius <= best_sq_radius) { + if (found_any && better_sq_radius > 0.0f && + better_sq_radius <= best_sq_radius) { // Great. This is as good a sphere as we're going to get. if (btype == BoundingVolume::BT_best && avg_box_area < better_sq_radius * MathNumbers::pi) { @@ -1409,7 +1410,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const { cdata->_internal_bounds = new BoundingBox(pmin, pmax); break; - } else if (sq_center_dist <= best_sq_radius) { + } else if (sq_center_dist >= 0.0f && sq_center_dist <= best_sq_radius) { // No, but a sphere centered on the origin is apparently still // better than a sphere around the bounding box. cdata->_internal_bounds = @@ -1420,7 +1421,8 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const { // This is the worst sphere we can make, which is why we will only // do it when the user specifically requests a sphere. cdata->_internal_bounds = - new BoundingSphere(aabb_center, csqrt(best_sq_radius)); + new BoundingSphere(aabb_center, + (best_sq_radius > 0.0f) ? csqrt(best_sq_radius) : 0.0f); break; } } diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index 2cd5e2739a..6fa66329ba 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -1607,13 +1607,16 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, } if (got_mat) { - if (!found_any) { - reader.set_row_unsafe(cdata->_first_vertex); + // Find the first non-NaN vertex. + while (!found_any && i < cdata->_num_vertices) { + reader.set_row(cdata->_first_vertex + i); LPoint3 first_vertex = mat.xform_point(reader.get_data3()); - min_point = first_vertex; - max_point = first_vertex; - sq_center_dist = first_vertex.length_squared(); - found_any = true; + if (!first_vertex.is_nan()) { + min_point = first_vertex; + max_point = first_vertex; + sq_center_dist = first_vertex.length_squared(); + found_any = true; + } ++i; } @@ -1630,13 +1633,16 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, sq_center_dist = max(sq_center_dist, vertex.length_squared()); } } else { - if (!found_any) { - reader.set_row_unsafe(cdata->_first_vertex); - const LVecBase3 &first_vertex = reader.get_data3(); - min_point = first_vertex; - max_point = first_vertex; - sq_center_dist = first_vertex.length_squared(); - found_any = true; + // Find the first non-NaN vertex. + while (!found_any && i < cdata->_num_vertices) { + reader.set_row(cdata->_first_vertex + i); + LPoint3 first_vertex = reader.get_data3(); + if (!first_vertex.is_nan()) { + min_point = first_vertex; + max_point = first_vertex; + sq_center_dist = first_vertex.length_squared(); + found_any = true; + } ++i; } @@ -1664,15 +1670,19 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, int strip_cut_index = get_strip_cut_index(cdata->_index_type); if (got_mat) { - if (!found_any) { - int first_index = index.get_data1i(); - nassertv(first_index != strip_cut_index); - reader.set_row_unsafe(first_index); - LPoint3 first_vertex = mat.xform_point(reader.get_data3()); - min_point = first_vertex; - max_point = first_vertex; - sq_center_dist = first_vertex.length_squared(); - found_any = true; + // Find the first non-NaN vertex. + while (!found_any && !index.is_at_end()) { + int ii = index.get_data1i(); + if (ii != strip_cut_index) { + reader.set_row(ii); + LPoint3 first_vertex = mat.xform_point(reader.get_data3()); + if (!first_vertex.is_nan()) { + min_point = first_vertex; + max_point = first_vertex; + sq_center_dist = first_vertex.length_squared(); + found_any = true; + } + } } while (!index.is_at_end()) { @@ -1692,15 +1702,19 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, sq_center_dist = max(sq_center_dist, vertex.length_squared()); } } else { - if (!found_any) { - int first_index = index.get_data1i(); - nassertv(first_index != strip_cut_index); - reader.set_row_unsafe(first_index); - const LVecBase3 &first_vertex = reader.get_data3(); - min_point = first_vertex; - max_point = first_vertex; - sq_center_dist = first_vertex.length_squared(); - found_any = true; + // Find the first non-NaN vertex. + while (!found_any && !index.is_at_end()) { + int ii = index.get_data1i(); + if (ii != strip_cut_index) { + reader.set_row(ii); + LVecBase3 first_vertex = reader.get_data3(); + if (!first_vertex.is_nan()) { + min_point = first_vertex; + max_point = first_vertex; + sq_center_dist = first_vertex.length_squared(); + found_any = true; + } + } } while (!index.is_at_end()) { diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 4a1092eb9c..fde084aa18 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -2750,6 +2750,7 @@ r_preprocess_source(ostream &out, istream &in, const Filename &fn, int ext_google_include = 0; // 1 = warn, 2 = enable int ext_google_line = 0; bool had_include = false; + bool had_version = false; int lineno = 0; bool write_line_directive = (fileno != 0); @@ -2920,6 +2921,9 @@ r_preprocess_source(ostream &out, istream &in, const Filename &fn, write_line_directive = true; } + } else if (strcmp(directive, "version") == 0) { + had_version = true; + } else if (strcmp(directive, "extension") == 0) { // Check for special preprocessing extensions. char extension[256]; @@ -3047,6 +3051,11 @@ r_preprocess_source(ostream &out, istream &in, const Filename &fn, out << line << "\n"; } + if (fileno == 0 && !had_version) { + shader_cat.warning() + << "GLSL shader " << fn << " does not contain a #version line!\n"; + } + return true; } diff --git a/panda/src/mathutil/boundingSphere.h b/panda/src/mathutil/boundingSphere.h index 8c105daa01..2e63fb3396 100644 --- a/panda/src/mathutil/boundingSphere.h +++ b/panda/src/mathutil/boundingSphere.h @@ -47,6 +47,8 @@ PUBLISHED: INLINE_MATHUTIL void set_center(const LPoint3 ¢er); INLINE_MATHUTIL void set_radius(PN_stdfloat radius); + MAKE_PROPERTY(center, get_center, set_center); + MAKE_PROPERTY(radius, get_radius, set_radius); public: virtual const BoundingSphere *as_bounding_sphere() const; diff --git a/panda/src/mathutil/finiteBoundingVolume.h b/panda/src/mathutil/finiteBoundingVolume.h index e344151685..e527faa88b 100644 --- a/panda/src/mathutil/finiteBoundingVolume.h +++ b/panda/src/mathutil/finiteBoundingVolume.h @@ -30,6 +30,10 @@ PUBLISHED: virtual LPoint3 get_max() const=0; virtual PN_stdfloat get_volume() const; + MAKE_PROPERTY(min, get_min); + MAKE_PROPERTY(max, get_max); + MAKE_PROPERTY(volume, get_volume); + public: virtual const FiniteBoundingVolume *as_finite_bounding_volume() const; diff --git a/tests/gobj/test_geom.py b/tests/gobj/test_geom.py index 2a5a462659..24eeab852f 100644 --- a/tests/gobj/test_geom.py +++ b/tests/gobj/test_geom.py @@ -40,3 +40,45 @@ def test_geom_decompose(): # Old primitive should still be unchanged assert prim == geom.get_primitive(0) + + +def test_geom_calc_sphere_bounds(): + # Ensure that it ignores NaN + data = core.GeomVertexData("", core.GeomVertexFormat.get_v3(), core.Geom.UH_static) + vertex = core.GeomVertexWriter(data, "vertex") + vertex.add_data3((float("NaN"), 0, 0)) + vertex.add_data3((1, 1, 1)) + vertex.add_data3((1, 1, 2)) + + prim = core.GeomPoints(core.Geom.UH_static) + prim.add_next_vertices(3) + + geom = core.Geom(data) + geom.add_primitive(prim) + geom.set_bounds_type(core.BoundingVolume.BT_sphere) + + bounds = geom.get_bounds() + assert isinstance(bounds, core.BoundingSphere) + assert bounds.get_center() == (1, 1, 1.5) + assert bounds.get_radius() == 0.5 + + +def test_geom_calc_box_bounds(): + # Ensure that it ignores NaN + data = core.GeomVertexData("", core.GeomVertexFormat.get_v3(), core.Geom.UH_static) + vertex = core.GeomVertexWriter(data, "vertex") + vertex.add_data3((float("NaN"), 0, 0)) + vertex.add_data3((1, 1, 1)) + vertex.add_data3((1, 1, 2)) + + prim = core.GeomPoints(core.Geom.UH_static) + prim.add_next_vertices(3) + + geom = core.Geom(data) + geom.add_primitive(prim) + geom.set_bounds_type(core.BoundingVolume.BT_box) + + bounds = geom.get_bounds() + assert isinstance(bounds, core.BoundingBox) + assert bounds.get_min() == (1, 1, 1) + assert bounds.get_max() == (1, 1, 2)