mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 16:20:11 -04:00
Merge branch 'release/1.10.x'
This commit is contained in:
commit
78fb565f2b
@ -2769,7 +2769,7 @@ def SetupVisualStudioEnviron():
|
|||||||
elif not win_kit.endswith('\\'):
|
elif not win_kit.endswith('\\'):
|
||||||
win_kit += '\\'
|
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)
|
version = "10.0.{0}.0".format(vnum)
|
||||||
if os.path.isfile(win_kit + "Include\\" + version + "\\ucrt\\assert.h"):
|
if os.path.isfile(win_kit + "Include\\" + version + "\\ucrt\\assert.h"):
|
||||||
print("Using Universal CRT %s" % (version))
|
print("Using Universal CRT %s" % (version))
|
||||||
|
@ -168,8 +168,9 @@ appear before they are referenced.
|
|||||||
The remaining formats are generic and specify only the semantic
|
The remaining formats are generic and specify only the semantic
|
||||||
meaning of the channels. The size of the texels is determined by
|
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
|
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
|
general; RGB is the same, but without any alpha channel.
|
||||||
like RGBA, except that it requests only one bit of alpha, if the
|
|
||||||
|
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
|
graphics card can provide that, to leave more room for the RGB
|
||||||
components, which is especially important for older 16-bit
|
components, which is especially important for older 16-bit
|
||||||
graphics cards (the "M" stands for "mask", as in a cutout).
|
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
|
Although less often used, for 3-d textures wrapw may also be
|
||||||
specified, and it behaves similarly to wrapu and wrapv.
|
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:
|
The full list is:
|
||||||
|
|
||||||
CLAMP
|
CLAMP
|
||||||
@ -1083,7 +1084,7 @@ surfaces. External tools like egg-qtess, however, may respect them.
|
|||||||
|
|
||||||
<Scalar> type { curve-type }
|
<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
|
or T. If the type is XYZ, the curve will automatically be
|
||||||
transformed between Y-up and Z-up if necessary; otherwise, it will
|
transformed between Y-up and Z-up if necessary; otherwise, it will
|
||||||
be left alone.
|
be left alone.
|
||||||
@ -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
|
These define the number of subdivisions to make in the U and V
|
||||||
directions to represent the surface. A uniform subdivision is
|
directions to represent the surface. A uniform subdivision is
|
||||||
always made, and trim curves are not respected (though they will
|
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.
|
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
|
Although the egg syntax supports trim curves, there are at present
|
||||||
no egg processing tools that respect them. For instance, egg-qtess
|
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
|
MORPH DESCRIPTION ENTRIES
|
||||||
@ -1310,6 +1311,15 @@ GROUPING ENTRIES
|
|||||||
vertices; joints and morphs appearing outside of a hierarchy
|
vertices; joints and morphs appearing outside of a hierarchy
|
||||||
identified with a <Dart> flag are undefined.
|
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 }
|
<Switch> { boolean-value }
|
||||||
|
|
||||||
This attribute indicates that the child nodes of this group
|
This attribute indicates that the child nodes of this group
|
||||||
@ -1619,7 +1629,8 @@ GROUPING ENTRIES
|
|||||||
|
|
||||||
There may also be additional predefined egg object types not
|
There may also be additional predefined egg object types not
|
||||||
listed here; see the *.pp files that are installed into the etc
|
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 }
|
<Transform> { transform-definition }
|
||||||
|
|
||||||
@ -1746,8 +1757,8 @@ GROUPING ENTRIES
|
|||||||
and it may contain other joints.
|
and it may contain other joints.
|
||||||
|
|
||||||
A tree of <Joint> nodes only makes sense within a character
|
A tree of <Joint> nodes only makes sense within a character
|
||||||
definition, which is created by applying the <DART> flag to a group.
|
definition, which is created by applying the <Dart> flag to a group.
|
||||||
See <DART>, above.
|
See <Dart>, above.
|
||||||
|
|
||||||
The vertex assignment is crucial. This is how the geometry of a
|
The vertex assignment is crucial. This is how the geometry of a
|
||||||
character is made to move with the joints. The character's geometry
|
character is made to move with the joints. The character's geometry
|
||||||
@ -1913,6 +1924,10 @@ ANIMATION STRUCTURE
|
|||||||
animated model description. Without the <Dart> flag, joints will be
|
animated model description. Without the <Dart> flag, joints will be
|
||||||
treated as ordinary groups, and morphs will be ignored.
|
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
|
In the above, UPPERCASE NAMES represent an arbitrary name that you
|
||||||
may choose. The name of the enclosing group, CHARACTER_NAME, is
|
may choose. The name of the enclosing group, CHARACTER_NAME, is
|
||||||
taken as the name of the animated model. It should generally match
|
taken as the name of the animated model. It should generally match
|
||||||
|
@ -36,10 +36,6 @@
|
|||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -589,16 +585,15 @@ determine_bin_home(EggBin *egg_bin) {
|
|||||||
// ahead and make an implicit node for the joint.
|
// ahead and make an implicit node for the joint.
|
||||||
|
|
||||||
if (egg_group->get_dcs_type() == EggGroup::DC_none) {
|
if (egg_group->get_dcs_type() == EggGroup::DC_none) {
|
||||||
/*
|
// Unless the user specifically forbade exposing the joint by putting an
|
||||||
* Unless the user specifically forbade exposing the joint by putting an
|
// explicit "<DCS> { none }" entry in the joint. In this case, we return
|
||||||
* explicit "<DCS> { none }" entry in the joint. In this case, we return NULL
|
// nullptr to treat the geometry as dynamic (and animate it by animating
|
||||||
* to treat the geometry as dynamic (and animate it by animating its
|
// its vertices), but display lists and vertex buffers will perform better
|
||||||
* vertices), but display lists and vertex buffers will perform better if more
|
// if more geometry is rigid. There's a tradeoff, though, since the cull
|
||||||
* geometry is rigid. There's a tradeoff, though, since the cull traverser
|
// traverser will have to do more work with additional transforms in the
|
||||||
* will have to do more work with additional transforms in the scene graph,
|
// scene graph, and this may also break up the geometry into more
|
||||||
* and this may also break up the geometry into more individual pieces, which
|
// individual pieces, which is the biggest limiting factor on modern PC
|
||||||
* is the biggest limiting factor on modern PC graphics cards.
|
// graphics cards.
|
||||||
*/
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,3 +149,35 @@ update_mods(ModifierButtons &mods) const {
|
|||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
@ -44,19 +44,20 @@ class DatagramIterator;
|
|||||||
* character set.
|
* character set.
|
||||||
*/
|
*/
|
||||||
class EXPCL_PANDA_EVENT ButtonEvent {
|
class EXPCL_PANDA_EVENT ButtonEvent {
|
||||||
public:
|
PUBLISHED:
|
||||||
enum Type {
|
enum Type {
|
||||||
/*
|
// T_down is sent when a button was just pressed.
|
||||||
* 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,
|
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_resume_down,
|
||||||
|
|
||||||
|
// T_down is sent when a button is released.
|
||||||
T_up,
|
T_up,
|
||||||
|
|
||||||
// T_repeat is sent for each a keyrepeat event generated by the system,
|
// T_repeat is sent for each a keyrepeat event generated by the system,
|
||||||
@ -84,6 +85,7 @@ public:
|
|||||||
T_raw_up,
|
T_raw_up,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
INLINE ButtonEvent();
|
INLINE ButtonEvent();
|
||||||
INLINE ButtonEvent(ButtonHandle button, Type type, double time = ClockObject::get_global_clock()->get_frame_time());
|
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());
|
INLINE ButtonEvent(int keycode, double time = ClockObject::get_global_clock()->get_frame_time());
|
||||||
@ -92,17 +94,30 @@ public:
|
|||||||
INLINE ButtonEvent(const ButtonEvent ©);
|
INLINE ButtonEvent(const ButtonEvent ©);
|
||||||
INLINE void operator = (const ButtonEvent ©);
|
INLINE void operator = (const ButtonEvent ©);
|
||||||
|
|
||||||
|
PUBLISHED:
|
||||||
INLINE bool operator == (const ButtonEvent &other) const;
|
INLINE bool operator == (const ButtonEvent &other) const;
|
||||||
INLINE bool operator != (const ButtonEvent &other) const;
|
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 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 output(std::ostream &out) const;
|
||||||
|
|
||||||
void write_datagram(Datagram &dg) const;
|
void write_datagram(Datagram &dg) const;
|
||||||
void read_datagram(DatagramIterator &scan);
|
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:
|
public:
|
||||||
// _button will be filled in if type is T_down, T_resume_down, or T_up.
|
// _button will be filled in if type is T_down, T_resume_down, or T_up.
|
||||||
ButtonHandle _button;
|
ButtonHandle _button;
|
||||||
|
@ -47,6 +47,8 @@ PUBLISHED:
|
|||||||
virtual void output(std::ostream &out) const;
|
virtual void output(std::ostream &out) const;
|
||||||
void write(std::ostream &out, int indent_level = 0) const;
|
void write(std::ostream &out, int indent_level = 0) const;
|
||||||
|
|
||||||
|
MAKE_SEQ_PROPERTY(events, get_num_events, get_event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef pvector<ButtonEvent> Events;
|
typedef pvector<ButtonEvent> Events;
|
||||||
Events _events;
|
Events _events;
|
||||||
|
@ -14190,7 +14190,8 @@ upload_simple_texture(CLP(TextureContext) *gtc) {
|
|||||||
#endif
|
#endif
|
||||||
GLenum external_format = GL_BGRA;
|
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) {
|
if (image_ptr == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2911,10 +2911,13 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
|
|
||||||
// Bindless texturing wasn't supported or didn't work, so let's just bind
|
// Bindless texturing wasn't supported or didn't work, so let's just bind
|
||||||
// the texture normally.
|
// 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
|
#ifndef OPENGLES
|
||||||
if (multi_bind) {
|
if (multi_bind) {
|
||||||
// Multi-bind case.
|
// Multi-bind case.
|
||||||
if (!_glgsg->update_texture(gtc, false)) {
|
if (!_glgsg->update_texture(gtc, force)) {
|
||||||
textures[i] = 0;
|
textures[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
gtc->set_active(true);
|
gtc->set_active(true);
|
||||||
@ -2934,7 +2937,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
|
|||||||
{
|
{
|
||||||
// Non-multibind case.
|
// Non-multibind case.
|
||||||
_glgsg->set_active_texture_stage(i);
|
_glgsg->set_active_texture_stage(i);
|
||||||
if (!_glgsg->update_texture(gtc, false)) {
|
if (!_glgsg->update_texture(gtc, force)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_glgsg->apply_texture(gtc);
|
_glgsg->apply_texture(gtc);
|
||||||
|
@ -10351,10 +10351,12 @@ make_this_from_bam(const FactoryParams ¶ms) {
|
|||||||
// object to read all of the attributes from the bam stream.
|
// object to read all of the attributes from the bam stream.
|
||||||
Texture *dummy = this;
|
Texture *dummy = this;
|
||||||
AutoTextureScale auto_texture_scale = ATS_unspecified;
|
AutoTextureScale auto_texture_scale = ATS_unspecified;
|
||||||
|
bool has_simple_ram_image = false;
|
||||||
{
|
{
|
||||||
CDWriter cdata_dummy(dummy->_cycler, true);
|
CDWriter cdata_dummy(dummy->_cycler, true);
|
||||||
dummy->do_fillin_body(cdata_dummy, scan, manager);
|
dummy->do_fillin_body(cdata_dummy, scan, manager);
|
||||||
auto_texture_scale = cdata_dummy->_auto_texture_scale;
|
auto_texture_scale = cdata_dummy->_auto_texture_scale;
|
||||||
|
has_simple_ram_image = !cdata_dummy->_simple_ram_image._image.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename.empty()) {
|
if (filename.empty()) {
|
||||||
@ -10387,6 +10389,61 @@ make_this_from_bam(const FactoryParams ¶ms) {
|
|||||||
case TT_1d_texture:
|
case TT_1d_texture:
|
||||||
case TT_2d_texture:
|
case TT_2d_texture:
|
||||||
case TT_1d_texture_array:
|
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()) {
|
if (alpha_filename.empty()) {
|
||||||
me = TexturePool::load_texture(filename, primary_file_num_channels,
|
me = TexturePool::load_texture(filename, primary_file_num_channels,
|
||||||
has_read_mipmaps, options);
|
has_read_mipmaps, options);
|
||||||
|
@ -33,6 +33,29 @@ verify_texture(const Filename &filename) {
|
|||||||
return load_texture(filename) != nullptr;
|
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
|
* 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
|
* loaded, and returns the new texture. If a texture with the same filename
|
||||||
|
@ -273,6 +273,62 @@ ns_has_texture(const Filename &orig_filename) {
|
|||||||
return false;
|
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().
|
* The nonstatic implementation of load_texture().
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +38,14 @@ class EXPCL_PANDA_GOBJ TexturePool {
|
|||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
INLINE static bool has_texture(const Filename &filename);
|
INLINE static bool has_texture(const Filename &filename);
|
||||||
INLINE static bool verify_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,
|
BLOCKING INLINE static Texture *load_texture(const Filename &filename,
|
||||||
int primary_file_num_channels = 0,
|
int primary_file_num_channels = 0,
|
||||||
bool read_mipmaps = false,
|
bool read_mipmaps = false,
|
||||||
@ -109,6 +117,14 @@ private:
|
|||||||
TexturePool();
|
TexturePool();
|
||||||
|
|
||||||
bool ns_has_texture(const Filename &orig_filename);
|
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,
|
Texture *ns_load_texture(const Filename &orig_filename,
|
||||||
int primary_file_num_channels,
|
int primary_file_num_channels,
|
||||||
bool read_mipmaps,
|
bool read_mipmaps,
|
||||||
|
@ -22,13 +22,21 @@ TypeHandle TextureReloadRequest::_type_handle;
|
|||||||
AsyncTask::DoneStatus TextureReloadRequest::
|
AsyncTask::DoneStatus TextureReloadRequest::
|
||||||
do_task() {
|
do_task() {
|
||||||
// Don't reload the texture if it doesn't need it.
|
// Don't reload the texture if it doesn't need it.
|
||||||
if (_texture->was_image_modified(_pgo)) {
|
if (!_texture->was_image_modified(_pgo) &&
|
||||||
|
(_allow_compressed ? _texture->has_ram_image() : _texture->has_uncompressed_ram_image())) {
|
||||||
|
return DS_done;
|
||||||
|
}
|
||||||
|
|
||||||
double delay = async_load_delay;
|
double delay = async_load_delay;
|
||||||
if (delay != 0.0) {
|
if (delay != 0.0) {
|
||||||
Thread::sleep(delay);
|
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) {
|
if (_allow_compressed) {
|
||||||
_texture->get_ram_image();
|
_texture->get_ram_image();
|
||||||
} else {
|
} else {
|
||||||
@ -36,13 +44,11 @@ do_task() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now that we've loaded the texture, we should ensure it actually gets
|
// 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
|
// prepared--even if it's no longer visible in the frame--or it may become a
|
||||||
// become a kind of a leak (if the texture is never rendered again on
|
// kind of a leak (if the texture is never rendered again on this GSG, we'll
|
||||||
// this GSG, we'll just end up carrying the texture memory in RAM
|
// just end up carrying the texture memory in RAM forever, instead of dumping
|
||||||
// forever, instead of dumping it as soon as it gets prepared).
|
// it as soon as it gets prepared).
|
||||||
_pgo->enqueue_texture(_texture);
|
_pgo->enqueue_texture(_texture);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't continue the task; we're done.
|
// Don't continue the task; we're done.
|
||||||
return DS_done;
|
return DS_done;
|
||||||
|
@ -106,7 +106,6 @@ set_hpr(const FLOATNAME(LVecBase3) &hpr, CoordinateSystem cs) {
|
|||||||
v = FLOATNAME(LVector3)::right(cs);
|
v = FLOATNAME(LVector3)::right(cs);
|
||||||
a = deg_2_rad(hpr[1] * 0.5f);
|
a = deg_2_rad(hpr[1] * 0.5f);
|
||||||
csincos(a, &s, &c);
|
csincos(a, &s, &c);
|
||||||
s = csin(a);
|
|
||||||
quat_p.set(c, v[0] * s, v[1] * s, v[2] * s);
|
quat_p.set(c, v[0] * s, v[1] * s, v[2] * s);
|
||||||
v = FLOATNAME(LVector3)::forward(cs);
|
v = FLOATNAME(LVector3)::forward(cs);
|
||||||
a = deg_2_rad(hpr[2] * 0.5f);
|
a = deg_2_rad(hpr[2] * 0.5f);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user