Merge branch 'release/1.10.x'

This commit is contained in:
rdb 2021-11-28 16:14:18 +01:00
commit 78fb565f2b
15 changed files with 343 additions and 123 deletions

View File

@ -2769,7 +2769,7 @@ def SetupVisualStudioEnviron():
elif not win_kit.endswith('\\'):
win_kit += '\\'
for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763, 18362:
for vnum in 10150, 10240, 10586, 14393, 15063, 16299, 17134, 17763, 18362, 19041:
version = "10.0.{0}.0".format(vnum)
if os.path.isfile(win_kit + "Include\\" + version + "\\ucrt\\assert.h"):
print("Using Universal CRT %s" % (version))

View File

@ -3,7 +3,7 @@ THE PHILOSOPHY OF EGG FILES (vs. bam files)
Egg files are used by Panda3D to describe many properties of a scene:
simple geometry, including special effects and collision surfaces,
characters including skeletons, morphs, and multiple-joint
assignments, and character animation tables.
assignments, and character animation tables.
Egg files are designed to be the lingua franca of model manipulation
for Panda tools. A number of utilities are provided that read and
@ -168,8 +168,9 @@ appear before they are referenced.
The remaining formats are generic and specify only the semantic
meaning of the channels. The size of the texels is determined by
the width of the components in the image file. RGBA is the most
general; RGB is the same, but without any alpha channel. RGBM is
like RGBA, except that it requests only one bit of alpha, if the
general; RGB is the same, but without any alpha channel.
RGBM is like RGBA, except that it requests only one bit of alpha, if the
graphics card can provide that, to leave more room for the RGB
components, which is especially important for older 16-bit
graphics cards (the "M" stands for "mask", as in a cutout).
@ -211,7 +212,7 @@ appear before they are referenced.
Although less often used, for 3-d textures wrapw may also be
specified, and it behaves similarly to wrapu and wrapv.
There are other legal values in addtional to REPEAT and CLAMP.
There are other legal values in additional to REPEAT and CLAMP.
The full list is:
CLAMP
@ -278,7 +279,7 @@ appear before they are referenced.
/ (number of views).
<Scalar> read-mipmaps { flag }
If this flag is nonzero, then pre-generated mipmap levels will be
loaded along with the texture. In this case, the filename should
contain a sequence of one or more hash mark ("#") characters,
@ -413,7 +414,7 @@ appear before they are referenced.
<Scalar> combine-alpha-operand2 { src-alpha }
<Scalar> saved-result { flag }
If flag is nonzero, then it indicates that this particular texture
stage will be supplied as the "last_saved_result" source for any
future texture stages.
@ -704,7 +705,7 @@ appear before they are referenced.
<UV> [name] { u v [w] [tangent] [binormal] [morph-list] }
This gives the texture coordinates of the vertex. This must be
specified if a texture is to be mapped onto this geometry.
specified if a texture is to be mapped onto this geometry.
The texture coordinates are usually two-dimensional, with two
component values (u v), but they may also be three-dimensional,
@ -739,7 +740,7 @@ appear before they are referenced.
meaning to custom code or a custom shader. Like named UV's, there
may be multiple Aux entries for a given vertex, each with a
different name.
<DynamicVertexPool> name { vertices }
@ -758,18 +759,18 @@ appear before they are referenced.
At the present time, the DynamicVertexPool is not implemented in
Panda3D.
GEOMETRY ENTRIES
<Polygon> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
<Polygon> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
}
A polygon consists of a sequence of vertices from a single vertex
@ -822,7 +823,7 @@ GEOMETRY ENTRIES
used unless all vertices also have a normal. If no normal is
defined, none will be supplied. The polygon normal, like the
vertex normal, may be morphed by specifying a series of <DNormal>
entries.
entries.
The polygon normal is used only for lighting and environment
mapping calculations, and is not related to the implicit normal
@ -844,7 +845,7 @@ GEOMETRY ENTRIES
disabled, and polygons are one-sided; specifying a nonzero value
disables backface culling for this particular polygon and allows
it to be viewed from either side.
<Scalar> bin { bin-name }
@ -916,12 +917,12 @@ GEOMETRY ENTRIES
or even within a texture.
<Patch> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
<Patch> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
}
A patch is similar to a polygon, but it is a special primitive that
@ -936,12 +937,12 @@ GEOMETRY ENTRIES
specified for Patch.
<PointLight> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
<PointLight> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
}
A PointLight is a set of single points. One point is drawn for each
@ -964,12 +965,12 @@ GEOMETRY ENTRIES
viewer normally.
<Line> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
<Line> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
[component attributes]
}
@ -985,11 +986,11 @@ GEOMETRY ENTRIES
line segment, as in TriangleStrip, below.
<TriangleStrip> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
<TriangleStrip> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
[component attributes]
}
@ -1013,7 +1014,7 @@ GEOMETRY ENTRIES
It is possible for the individual triangles of a triangle strip to
have a separate normal and/or color. If so, a <Component> entry
should be given for each so-modified triangle:
<Component> index {
<RGBA> { r g b a [morph-list] }
<Normal> { x y z [morph-list] }
@ -1024,11 +1025,11 @@ GEOMETRY ENTRIES
must always follow the vertex list.
<TriangleFan> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
<TriangleFan> name {
[attributes]
<VertexRef> {
indices
<Ref> { pool-name }
}
[component attributes]
}
@ -1057,7 +1058,7 @@ itself doesn't support them and will always create static curves and
surfaces. External tools like egg-qtess, however, may respect them.
<NURBSCurve> {
[attributes]
[attributes]
<Order> { order }
<Knots> { knot-list }
@ -1083,7 +1084,7 @@ surfaces. External tools like egg-qtess, however, may respect them.
<Scalar> type { curve-type }
This defines the semanting meaning of this curve, either XYZ, HPR,
This defines the semantic meaning of this curve, either XYZ, HPR,
or T. If the type is XYZ, the curve will automatically be
transformed between Y-up and Z-up if necessary; otherwise, it will
be left alone.
@ -1107,16 +1108,16 @@ surfaces. External tools like egg-qtess, however, may respect them.
<NURBSSurface> name {
[attributes]
[attributes]
<Order> { u-order v-order }
<U-knots> { u-knot-list }
<V-knots> { v-knot-list }
<VertexRef> {
indices
<Ref> { pool-name }
}
<VertexRef> {
indices
<Ref> { pool-name }
}
}
A NURBS surface is an extension of a NURBS curve into two parametric
@ -1137,7 +1138,7 @@ surfaces. External tools like egg-qtess, however, may respect them.
These define the number of subdivisions to make in the U and V
directions to represent the surface. A uniform subdivision is
always made, and trim curves are not respected (though they will
be drawn in if the trim curves themselves also have a subiv
be drawn in if the trim curves themselves also have a subdiv
parameter). This is only intended as a cheesy visualization.
@ -1194,7 +1195,7 @@ surfaces. External tools like egg-qtess, however, may respect them.
Although the egg syntax supports trim curves, there are at present
no egg processing tools that respect them. For instance, egg-qtess
ignores trim curves and always tesselates the entire NURBS surface.
ignores trim curves and always tessellates the entire NURBS surface.
MORPH DESCRIPTION ENTRIES
@ -1267,7 +1268,7 @@ GROUPING ENTRIES
attributes of the group:
GROUP BINARY ATTRIBUTES
These attributes may be either on or off; they are off by default.
They are turned on by specifying a non-zero "boolean-value".
@ -1310,6 +1311,15 @@ GROUPING ENTRIES
vertices; joints and morphs appearing outside of a hierarchy
identified with a <Dart> flag are undefined.
<Dart> { structured }
This is an optional alternative for the <Dart> flag.
By default, Panda will collapse all of the geometry in a group (with the <Dart> { 1 } flag)
a single node. While this is optimal for conditions such as characters moving around
a scene, it may be suboptimal for larger or more complex characters.
This entry is typically generated by the egg-optchar program with the "-dart structured" flag.
<Dart> { structured } implies <Dart> { 1 }.
<Switch> { boolean-value }
This attribute indicates that the child nodes of this group
@ -1446,7 +1456,7 @@ GROUPING ENTRIES
of the billboard, not at the origin of the scene.
<SwitchCondition> {
<Distance> {
<Distance> {
in out [fade] <Vertex> { x y z }
}
}
@ -1483,7 +1493,7 @@ GROUPING ENTRIES
Valid types so far are:
Plane
The geometry represents an infinite plane. The first polygon
found in the group will define the plane.
@ -1550,7 +1560,7 @@ GROUPING ENTRIES
most compatibility.
keep
Don't discard the visible geometry after using it to define a
collision surface; create both an invisible collision surface
and the visible geometry.
@ -1619,7 +1629,8 @@ GROUPING ENTRIES
There may also be additional predefined egg object types not
listed here; see the *.pp files that are installed into the etc
directory for a complete list.
directory for a complete list. Additionally, you can reference
the file located in $PANDA/src/doc/howto.MultiGenModelFlags
<Transform> { transform-definition }
@ -1683,9 +1694,9 @@ GROUPING ENTRIES
current group, regardless of the group in which the geometry is
actually defined. See the <Joint> description, below.
<AnimPreload> {
<AnimPreload> {
<Scalar> fps { float-value }
<Scalar> num-frames { integer-value }
<Scalar> num-frames { integer-value }
}
One or more AnimPreload entries may appear within the <Group> that
@ -1720,7 +1731,7 @@ GROUPING ENTRIES
geometry in the scene graph. The syntax is:
<Instance> name {
<Ref> { group-name }
<Ref> { group-name }
[ <Ref> { group-name } ... ]
}
@ -1746,8 +1757,8 @@ GROUPING ENTRIES
and it may contain other joints.
A tree of <Joint> nodes only makes sense within a character
definition, which is created by applying the <DART> flag to a group.
See <DART>, above.
definition, which is created by applying the <Dart> flag to a group.
See <Dart>, above.
The vertex assignment is crucial. This is how the geometry of a
character is made to move with the joints. The character's geometry
@ -1790,7 +1801,7 @@ GROUPING ENTRIES
bundles, or any one of the following (<Scalar> entries are optional,
and default as shown):
<S$Anim> name {
<S$Anim> name {
<Scalar> fps { 24 }
<V> { values }
}
@ -1844,7 +1855,7 @@ GROUPING ENTRIES
an animation sequence.
<VertexAnim> name {
<VertexAnim> name {
<Scalar> width { table-width }
<Scalar> fps { 24 }
<V> { values }
@ -1913,6 +1924,10 @@ ANIMATION STRUCTURE
animated model description. Without the <Dart> flag, joints will be
treated as ordinary groups, and morphs will be ignored.
It is important to note that utilizing <Dart> { 1 } will collapse all of the
model's geometry into a single node. To omit this, use <Dart> { structured } instead.
(See <Dart> above.)
In the above, UPPERCASE NAMES represent an arbitrary name that you
may choose. The name of the enclosing group, CHARACTER_NAME, is
taken as the name of the animated model. It should generally match

View File

@ -3,7 +3,7 @@
This document describes the different kinds of model flags one can place in
the comment field of MultiGen group beads. The general format for a model
flag is:
flag is:
<egg> { <FLAGNAME> {value} }
The most up-to-date version of this document can be found in:
@ -30,7 +30,7 @@ The most up-to-date version of this document can be found in:
<egg> { <ObjectType> {camera-barrier} } Invisible collision surface for camera and colliders
<egg> { <ObjectType> {camera-barrier-sphere} } Invisible sphere collision surface for camera and colliders
<egg> { <ObjectType> {backstage} } Modeling reference object
<egg> { <Decal> {1} } Decal the node below to me
<egg> { <Decal> {1} } Decal the node below to me
(like a window on a wall)
<egg> { <Scalar> fps { # } } Set rate of animation for a pfSequence
@ -52,12 +52,12 @@ common flag/value pairs and describes what they are used for.
which one places the flag (so names like red-hut are more useful than
names like o34).
<egg> { <Model> {1} }
<egg> { <Model> {1} }
Used to show/hide, change the color, or change the collision properties
Used to show/hide, change the color, or change the collision properties
of a chunk.
<egg> { <DCS> {1} }
<egg> { <DCS> {1} }
Used to move, rotate, or scale a chunk of the model. Also can be used
(like the <Model> flag) to show/hide, change the color, and change the
@ -91,7 +91,7 @@ common flag/value pairs and describes what they are used for.
a door, for example, so the player can tell when the avatar has
moved through the door.
- BACKSTAGE objects are not translated over to the player. Modelers
should use this flag on reference objects that they include to help
should use this flag on reference objects that they include to help
in the modeling task (such as scale references)
IMPORTANT NOTE:
@ -108,7 +108,7 @@ common flag/value pairs and describes what they are used for.
********** PROPERTIES **********
These are used to control properties of selected chunks.
These are used to control properties of selected chunks.
<egg> { <Scalar> fps { frame-rate } }
@ -124,7 +124,7 @@ These are used to control properties of selected chunks.
Multiple Flag/value pairs can be combined within an single <egg> field.
For example:
<egg> { <Model> {1}
<egg> { <Model> {1}
<ObjectType> {barrier} }
Generally, the <Model> flag can be combined with most other flags
@ -134,7 +134,7 @@ These are used to control properties of selected chunks.
could also be written as:
<egg>{<model>{1}<objecttype>{barrier}}
3) Where to place the flags
All model flags except <Normal> flags are generally placed in the
@ -154,6 +154,6 @@ These are used to control properties of selected chunks.
4) Flags at different levels in the model
Flags in lower level beads generally override flags in upper level
beads.
beads.
5) For more detailed information see $PANDA/src/doc/eggSyntax.txt.

View File

@ -36,10 +36,6 @@
using std::string;
/**
*
*/
@ -589,16 +585,15 @@ determine_bin_home(EggBin *egg_bin) {
// ahead and make an implicit node for the joint.
if (egg_group->get_dcs_type() == EggGroup::DC_none) {
/*
* Unless the user specifically forbade exposing the joint by putting an
* explicit "<DCS> { none }" entry in the joint. In this case, we return NULL
* to treat the geometry as dynamic (and animate it by animating its
* vertices), but display lists and vertex buffers will perform better if more
* geometry is rigid. There's a tradeoff, though, since the cull traverser
* will have to do more work with additional transforms in the scene graph,
* and this may also break up the geometry into more individual pieces, which
* is the biggest limiting factor on modern PC graphics cards.
*/
// Unless the user specifically forbade exposing the joint by putting an
// explicit "<DCS> { none }" entry in the joint. In this case, we return
// nullptr to treat the geometry as dynamic (and animate it by animating
// its vertices), but display lists and vertex buffers will perform better
// if more geometry is rigid. There's a tradeoff, though, since the cull
// traverser will have to do more work with additional transforms in the
// scene graph, and this may also break up the geometry into more
// individual pieces, which is the biggest limiting factor on modern PC
// graphics cards.
return nullptr;
}

View File

@ -149,3 +149,35 @@ update_mods(ModifierButtons &mods) const {
return false;
}
}
/**
*
*/
INLINE ButtonHandle ButtonEvent::
get_button() const {
return _button;
}
/**
*
*/
INLINE int ButtonEvent::
get_keycode() const {
return _keycode;
}
/**
*
*/
INLINE ButtonEvent::Type ButtonEvent::
get_type() const {
return _type;
}
/**
*
*/
INLINE double ButtonEvent::
get_time() const {
return _time;
}

View File

@ -44,19 +44,20 @@ class DatagramIterator;
* character set.
*/
class EXPCL_PANDA_EVENT ButtonEvent {
public:
PUBLISHED:
enum Type {
/*
* T_down and T_up represent a button changing state correspondingly.
* T_resume_down is a special event that is only thrown when focus is returned
* to a window and a button is detected as being held down at that point; it
* indicates that the button should be considered down now (if it wasn't
* already), but it didn't just get pressed down at this moment, it was
* depressed some time ago. It's mainly used for correct tracking of modifier
* keys like shift and control, and can be ignored for other keys.
*/
// T_down is sent when a button was just pressed.
T_down,
// T_resume_down is a special event that is only thrown when focus is
// returned to a window and a button is detected as being held down at that
// point; it indicates that the button should be considered down now (if it
// wasn't already), but it didn't just get pressed down at this moment, it
// was depressed some time ago. It's mainly used for correct tracking of
// modifier keys like shift and control, and can be ignored for other keys.
T_resume_down,
// T_down is sent when a button is released.
T_up,
// T_repeat is sent for each a keyrepeat event generated by the system,
@ -84,6 +85,7 @@ public:
T_raw_up,
};
public:
INLINE ButtonEvent();
INLINE ButtonEvent(ButtonHandle button, Type type, double time = ClockObject::get_global_clock()->get_frame_time());
INLINE ButtonEvent(int keycode, double time = ClockObject::get_global_clock()->get_frame_time());
@ -92,17 +94,30 @@ public:
INLINE ButtonEvent(const ButtonEvent &copy);
INLINE void operator = (const ButtonEvent &copy);
PUBLISHED:
INLINE bool operator == (const ButtonEvent &other) const;
INLINE bool operator != (const ButtonEvent &other) const;
INLINE bool operator < (const ButtonEvent &other) const;
public:
INLINE bool update_mods(ModifierButtons &mods) const;
INLINE ButtonHandle get_button() const;
INLINE int get_keycode() const;
INLINE Type get_type() const;
INLINE double get_time() const;
void output(std::ostream &out) const;
void write_datagram(Datagram &dg) const;
void read_datagram(DatagramIterator &scan);
PUBLISHED:
MAKE_PROPERTY(button, get_button);
MAKE_PROPERTY(keycode, get_keycode);
MAKE_PROPERTY(type, get_type);
MAKE_PROPERTY(time, get_time);
public:
// _button will be filled in if type is T_down, T_resume_down, or T_up.
ButtonHandle _button;

View File

@ -47,6 +47,8 @@ PUBLISHED:
virtual void output(std::ostream &out) const;
void write(std::ostream &out, int indent_level = 0) const;
MAKE_SEQ_PROPERTY(events, get_num_events, get_event);
private:
typedef pvector<ButtonEvent> Events;
Events _events;

View File

@ -14190,7 +14190,8 @@ upload_simple_texture(CLP(TextureContext) *gtc) {
#endif
GLenum external_format = GL_BGRA;
const unsigned char *image_ptr = tex->get_simple_ram_image();
CPTA_uchar image = tex->get_simple_ram_image();
const unsigned char *image_ptr = image.p();
if (image_ptr == nullptr) {
return false;
}

View File

@ -2911,10 +2911,13 @@ update_shader_texture_bindings(ShaderContext *prev) {
// Bindless texturing wasn't supported or didn't work, so let's just bind
// the texture normally.
// Note that simple RAM images are always 2-D for now, so to avoid errors,
// we must load the real texture if this is not for a sampler2D.
bool force = (spec._desired_type != Texture::TT_2d_texture);
#ifndef OPENGLES
if (multi_bind) {
// Multi-bind case.
if (!_glgsg->update_texture(gtc, false)) {
if (!_glgsg->update_texture(gtc, force)) {
textures[i] = 0;
} else {
gtc->set_active(true);
@ -2934,7 +2937,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
{
// Non-multibind case.
_glgsg->set_active_texture_stage(i);
if (!_glgsg->update_texture(gtc, false)) {
if (!_glgsg->update_texture(gtc, force)) {
continue;
}
_glgsg->apply_texture(gtc);

View File

@ -10351,10 +10351,12 @@ make_this_from_bam(const FactoryParams &params) {
// object to read all of the attributes from the bam stream.
Texture *dummy = this;
AutoTextureScale auto_texture_scale = ATS_unspecified;
bool has_simple_ram_image = false;
{
CDWriter cdata_dummy(dummy->_cycler, true);
dummy->do_fillin_body(cdata_dummy, scan, manager);
auto_texture_scale = cdata_dummy->_auto_texture_scale;
has_simple_ram_image = !cdata_dummy->_simple_ram_image._image.empty();
}
if (filename.empty()) {
@ -10387,6 +10389,61 @@ make_this_from_bam(const FactoryParams &params) {
case TT_1d_texture:
case TT_2d_texture:
case TT_1d_texture_array:
// If we don't want to preload textures, and we already have a simple
// RAM image (or don't need one), we don't need to load it from disk.
// We do check for it in the texture pool first, though, in case it has
// already been loaded.
if ((options.get_texture_flags() & LoaderOptions::TF_preload) == 0 &&
(has_simple_ram_image || (options.get_texture_flags() & LoaderOptions::TF_preload_simple) == 0)) {
if (alpha_filename.empty()) {
me = TexturePool::get_texture(filename, primary_file_num_channels,
has_read_mipmaps);
} else {
me = TexturePool::get_texture(filename, alpha_filename,
primary_file_num_channels,
alpha_file_channel,
has_read_mipmaps);
}
if (me != nullptr && me->get_texture_type() == texture_type) {
// We can use this.
break;
}
// We don't have a texture, but we didn't need to preload it, so we
// can just use this one. We just need to know where we can find it
// when we do need to reload it.
Filename fullpath = filename;
Filename alpha_fullpath = alpha_filename;
const DSearchPath &model_path = get_model_path();
if (vfs->resolve_filename(fullpath, model_path) &&
(alpha_fullpath.empty() || vfs->resolve_filename(alpha_fullpath, model_path))) {
me = dummy;
me->set_name(name);
{
CDWriter cdata_me(me->_cycler, true);
cdata_me->_filename = filename;
cdata_me->_alpha_filename = alpha_filename;
cdata_me->_fullpath = fullpath;
cdata_me->_alpha_fullpath = alpha_fullpath;
cdata_me->_primary_file_num_channels = primary_file_num_channels;
cdata_me->_alpha_file_channel = alpha_file_channel;
cdata_me->_texture_type = texture_type;
cdata_me->_loaded_from_image = true;
cdata_me->_has_read_mipmaps = has_read_mipmaps;
}
// To manage the reference count, explicitly ref it now, then unref
// it in the finalize callback.
me->ref();
manager->register_finalize(me);
// Do add it to the cache now, so that future uses of this same
// texture are unified.
TexturePool::add_texture(me);
return me;
}
}
if (alpha_filename.empty()) {
me = TexturePool::load_texture(filename, primary_file_num_channels,
has_read_mipmaps, options);

View File

@ -33,6 +33,29 @@ verify_texture(const Filename &filename) {
return load_texture(filename) != nullptr;
}
/**
* Returns the texture that has already been previously loaded, or NULL
* otherwise.
*/
INLINE Texture *TexturePool::
get_texture(const Filename &filename, int primary_file_num_channels,
bool read_mipmaps) {
return get_global_ptr()->ns_get_texture(filename, primary_file_num_channels,
read_mipmaps);
}
/**
* Returns the texture that has already been previously loaded, or NULL
* otherwise.
*/
INLINE Texture *TexturePool::
get_texture(const Filename &filename, const Filename &alpha_filename,
int primary_file_num_channels, int alpha_file_channel,
bool read_mipmaps) {
return get_global_ptr()->ns_get_texture(filename, primary_file_num_channels,
read_mipmaps);
}
/**
* Loads the given filename up into a texture, if it has not already been
* loaded, and returns the new texture. If a texture with the same filename

View File

@ -273,6 +273,62 @@ ns_has_texture(const Filename &orig_filename) {
return false;
}
/**
* The nonstatic implementation of get_texture().
*/
Texture *TexturePool::
ns_get_texture(const Filename &orig_filename, int primary_file_num_channels,
bool read_mipmaps) {
LookupKey key;
key._primary_file_num_channels = primary_file_num_channels;
{
MutexHolder holder(_lock);
resolve_filename(key._fullpath, orig_filename, read_mipmaps, LoaderOptions());
Textures::const_iterator ti;
ti = _textures.find(key);
if (ti != _textures.end()) {
// This texture was previously loaded.
Texture *tex = (*ti).second;
nassertr(!tex->get_fullpath().empty(), tex);
return tex;
}
}
return nullptr;
}
/**
* The nonstatic implementation of get_texture().
*/
Texture *TexturePool::
ns_get_texture(const Filename &orig_filename,
const Filename &orig_alpha_filename,
int primary_file_num_channels,
int alpha_file_channel,
bool read_mipmaps) {
LookupKey key;
key._primary_file_num_channels = primary_file_num_channels;
key._alpha_file_channel = alpha_file_channel;
{
MutexHolder holder(_lock);
LoaderOptions options;
resolve_filename(key._fullpath, orig_filename, read_mipmaps, options);
resolve_filename(key._alpha_fullpath, orig_alpha_filename, read_mipmaps, options);
Textures::const_iterator ti;
ti = _textures.find(key);
if (ti != _textures.end()) {
// This texture was previously loaded.
Texture *tex = (*ti).second;
nassertr(!tex->get_fullpath().empty(), tex);
return tex;
}
}
return nullptr;
}
/**
* The nonstatic implementation of load_texture().
*/

View File

@ -38,6 +38,14 @@ class EXPCL_PANDA_GOBJ TexturePool {
PUBLISHED:
INLINE static bool has_texture(const Filename &filename);
INLINE static bool verify_texture(const Filename &filename);
INLINE static Texture *get_texture(const Filename &filename,
int primary_file_num_channels = 0,
bool read_mipmaps = false);
INLINE static Texture *get_texture(const Filename &filename,
const Filename &alpha_filename,
int primary_file_num_channels = 0,
int alpha_file_channel = 0,
bool read_mipmaps = false);
BLOCKING INLINE static Texture *load_texture(const Filename &filename,
int primary_file_num_channels = 0,
bool read_mipmaps = false,
@ -109,6 +117,14 @@ private:
TexturePool();
bool ns_has_texture(const Filename &orig_filename);
Texture *ns_get_texture(const Filename &filename,
int primary_file_num_channels = 0,
bool read_mipmaps = false);
Texture *ns_get_texture(const Filename &filename,
const Filename &alpha_filename,
int primary_file_num_channels = 0,
int alpha_file_channel = 0,
bool read_mipmaps = false);
Texture *ns_load_texture(const Filename &orig_filename,
int primary_file_num_channels,
bool read_mipmaps,

View File

@ -22,28 +22,34 @@ TypeHandle TextureReloadRequest::_type_handle;
AsyncTask::DoneStatus TextureReloadRequest::
do_task() {
// Don't reload the texture if it doesn't need it.
if (_texture->was_image_modified(_pgo)) {
double delay = async_load_delay;
if (delay != 0.0) {
Thread::sleep(delay);
}
if (!_texture->was_image_modified(_pgo) &&
(_allow_compressed ? _texture->has_ram_image() : _texture->has_uncompressed_ram_image())) {
return DS_done;
}
if (_texture->was_image_modified(_pgo)) {
if (_allow_compressed) {
_texture->get_ram_image();
} else {
_texture->get_uncompressed_ram_image();
}
double delay = async_load_delay;
if (delay != 0.0) {
Thread::sleep(delay);
// Now that we've loaded the texture, we should ensure it actually gets
// prepared--even if it's no longer visible in the frame--or it may
// become a kind of a leak (if the texture is never rendered again on
// this GSG, we'll just end up carrying the texture memory in RAM
// forever, instead of dumping it as soon as it gets prepared).
_pgo->enqueue_texture(_texture);
if (!_texture->was_image_modified(_pgo) &&
(_allow_compressed ? _texture->has_ram_image() : _texture->has_uncompressed_ram_image())) {
return DS_done;
}
}
if (_allow_compressed) {
_texture->get_ram_image();
} else {
_texture->get_uncompressed_ram_image();
}
// Now that we've loaded the texture, we should ensure it actually gets
// prepared--even if it's no longer visible in the frame--or it may become a
// kind of a leak (if the texture is never rendered again on this GSG, we'll
// just end up carrying the texture memory in RAM forever, instead of dumping
// it as soon as it gets prepared).
_pgo->enqueue_texture(_texture);
// Don't continue the task; we're done.
return DS_done;
}

View File

@ -106,7 +106,6 @@ set_hpr(const FLOATNAME(LVecBase3) &hpr, CoordinateSystem cs) {
v = FLOATNAME(LVector3)::right(cs);
a = deg_2_rad(hpr[1] * 0.5f);
csincos(a, &s, &c);
s = csin(a);
quat_p.set(c, v[0] * s, v[1] * s, v[2] * s);
v = FLOATNAME(LVector3)::forward(cs);
a = deg_2_rad(hpr[2] * 0.5f);