mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 00:06:44 -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('\\'):
|
||||
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))
|
||||
|
@ -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
|
||||
@ -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.
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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 }
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ©);
|
||||
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;
|
||||
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -10351,10 +10351,12 @@ make_this_from_bam(const FactoryParams ¶ms) {
|
||||
// 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 ¶ms) {
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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().
|
||||
*/
|
||||
|
@ -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,
|
||||
|
@ -22,13 +22,21 @@ 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)) {
|
||||
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;
|
||||
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 {
|
||||
@ -36,13 +44,11 @@ do_task() {
|
||||
}
|
||||
|
||||
// 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).
|
||||
// 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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user