Merge branch 'master' into cmake

This commit is contained in:
Sam Edwards 2015-03-05 09:46:52 -08:00
commit 25e2e0221d
98 changed files with 4030 additions and 742 deletions

View File

@ -7,6 +7,8 @@
//
///////////////////////////////////////////////////////////////////////
#include "dtoolbase.h"
#include <Python.h>
#if PY_MAJOR_VERSION >= 3
#include <wchar.h>
@ -71,7 +73,7 @@ int main(int argc, char *argv[]) {
char *path = getenv("PATH");
char *result = strtok(path, ";");
while (result != NULL) {
struct stat st;
struct stat st;
char *ppython = (char*) malloc(strlen(result) + 13);
strcpy(ppython, result);
strcat(ppython, "\\ppython.exe");
@ -79,13 +81,13 @@ int main(int argc, char *argv[]) {
Py_SetPythonHome(result);
free(ppython);
break;
}
}
result = strtok(NULL, ";");
free(ppython);
}
#endif
#endif
Py_Initialize();
if (Py_VerboseFlag) {

View File

@ -9,15 +9,15 @@
##############################################################################
import os,sys,gc
from pandac.PandaModules import *
from panda3d.core import *
class EggCacher:
def __init__(self, args):
maindir = Filename.fromOsSpecific(os.getcwd()).getFullpath()
ExecutionEnvironment.setEnvironmentVariable("MAIN_DIR", maindir)
self.bamcache = BamCache.getGlobalPtr()
self.pandaloader = PandaLoader()
self.loaderopts = LoaderOptions()
self.pandaloader = Loader()
self.loaderopts = LoaderOptions(LoaderOptions.LF_no_ram_cache)
if (self.bamcache.getActive() == 0):
print "The model cache is not currently active."
print "You must set a model-cache-dir in your config file."
@ -69,12 +69,12 @@ class EggCacher:
def processFiles(self, files):
total = 0
for (path,size) in files:
for (path, size) in files:
total += size
progress = 0
for (path,size) in files:
fn = Filename.fromOsSpecific(path)
cached = self.bamcache.lookup(fn,"bam")
cached = self.bamcache.lookup(fn, "bam")
percent = (progress * 100) / total
report = path
if (self.concise): report = os.path.basename(report)
@ -87,6 +87,4 @@ class EggCacher:
TexturePool.releaseAllTextures()
progress += size
cacher = EggCacher(sys.argv[1:])

View File

@ -94,8 +94,9 @@ class DirectDialog(DirectFrame):
('text', '', None),
('text_align', TextNode.ALeft, None),
('text_scale', 0.06, None),
('image', DGG.getDefaultDialogGeom(), None),
('relief', None, None),
('image', None, None),
('relief', DGG.RAISED, None),
('borderWidth', (0.01, 0.01), None),
('buttonTextList', [], DGG.INITOPT),
('buttonGeomList', [], DGG.INITOPT),
('buttonImageList', [], DGG.INITOPT),
@ -210,10 +211,16 @@ class DirectDialog(DirectFrame):
bounds = self.stateNodePath[0].getTightBounds()
if image:
image.reparentTo(self.stateNodePath[0])
l = bounds[0][0]
r = bounds[1][0]
b = bounds[0][2]
t = bounds[1][2]
if bounds is None:
l = 0
r = 0
b = 0
t = 0
else:
l = bounds[0][0]
r = bounds[1][0]
b = bounds[0][2]
t = bounds[1][2]
# Center text and geom around origin
# How far is center of text from origin?
xOffset = -(l+r)*0.5
@ -246,10 +253,16 @@ class DirectDialog(DirectFrame):
bl = br = bb = bt = 0
for button in self.buttonList:
bounds = button.stateNodePath[0].getTightBounds()
bl = min(bl, bounds[0][0])
br = max(br, bounds[1][0])
bb = min(bb, bounds[0][2])
bt = max(bt, bounds[1][2])
if bounds is None:
bl = 0
br = 0
bb = 0
bt = 0
else:
bl = min(bl, bounds[0][0])
br = max(br, bounds[1][0])
bb = min(bb, bounds[0][2])
bt = max(bt, bounds[1][2])
bl -= bpad[0]
br += bpad[0]
bb -= bpad[1]
@ -303,6 +316,7 @@ class DirectDialog(DirectFrame):
# reduce bottom by pad, button height and 2*button pad
b = min(b - self['midPad'] - bpad[1] - bHeight - bpad[1], b) - pad[1]
t = t + self['topPad'] + pad[1]
self['frameSize'] = (l, r, b, t)
self['image_scale'] = (r - l, 1, t - b)
# Center frame about text and buttons
self['image_pos'] = ((l+r)*0.5, 0.0, (b+t)*0.5)

View File

@ -43,7 +43,7 @@ class DirectRadioButton(DirectButton):
('boxGeom', None, None),
('boxGeomColor', None, None),
('boxGeomScale', 1.0, None),
('boxImage', loader.loadModel('models/gui/radio_button_gui'), None),
('boxImage', None, None),
('boxImageScale', 1.0, None),
('boxImageColor', VBase4(1, 1, 1, 1), None),
('boxRelief', None, None),
@ -69,9 +69,11 @@ class DirectRadioButton(DirectButton):
# Call option initialization functions
self.initialiseoptions(DirectRadioButton)
# After initialization with X giving it the correct size, put back space
if self['boxGeom'] == None:
if self['boxGeom'] is None:
if not 'boxRelief' in kw and self['boxImage'] is None:
self.indicator['relief'] = DGG.SUNKEN
self.indicator['text'] = (' ', '*')
self.indicator['text_pos'] = (0, -.5)
self.indicator['text_pos'] = (0, -.25)
else:
self.indicator['text'] = (' ', ' ')

View File

@ -59,15 +59,12 @@ class Transitions:
# Reload fade if its already been created
if self.fade:
del self.fade
self.fade.destroy()
self.fade = None
self.loadFade()
def loadFade(self):
if not self.fadeModel:
self.fadeModel = loader.loadModel(self.FadeModelName)
if self.fade == None:
if self.fade is None:
# We create a DirectFrame for the fade polygon, instead of
# simply loading the polygon model and using it directly,
# so that it will also obscure mouse events for objects
@ -80,10 +77,15 @@ class Transitions:
image_scale = (4, 2, 2),
state = DGG.NORMAL,
)
if not self.fadeModel:
# No fade model was given, so we make this the fade model.
self.fade["relief"] = DGG.FLAT
self.fade["frameSize"] = (-2, 2, -1, 1)
self.fade["frameColor"] = (0, 0, 0, 1)
self.fade.setTransparency(TransparencyAttrib.MAlpha)
self.fade.setBin('unsorted', 0)
self.fade.setColor(0,0,0,0)
def getFadeInIval(self, t=0.5, finishIval=None):
"""
Returns an interval without starting it. This is particularly useful in

View File

@ -60,7 +60,7 @@ extern char **environ;
#include <sys/sysctl.h>
#endif
#if defined(IS_LINUX) || defined(IS_OSX)
#if defined(IS_LINUX) || defined(IS_OSX) || defined(IS_FREEBSD)
// For link_map and dlinfo.
#include <link.h>
#include <dlfcn.h>

View File

@ -64,6 +64,39 @@ Filename(const Filename &copy) :
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Filename::Move Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE Filename::
Filename(string &&filename) NOEXCEPT {
_flags = 0;
(*this) = move(filename);
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Filename::Move Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE Filename::
Filename(Filename &&from) NOEXCEPT :
_filename(move(from._filename)),
_dirname_end(from._dirname_end),
_basename_start(from._basename_start),
_basename_end(from._basename_end),
_extension_start(from._extension_start),
_hash_start(from._hash_start),
_hash_end(from._hash_end),
_flags(from._flags)
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Filename::text_filename named constructor
// Access: Published
@ -216,6 +249,42 @@ operator = (const Filename &copy) {
return *this;
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Filename::Move assignment operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE Filename &Filename::
operator = (string &&filename) NOEXCEPT {
_filename = move(filename);
locate_basename();
locate_extension();
locate_hash();
return *this;
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Filename::Move assignment operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE Filename &Filename::
operator = (Filename &&from) NOEXCEPT {
_filename = MOVE(from._filename);
_dirname_end = from._dirname_end;
_basename_start = from._basename_start;
_basename_end = from._basename_end;
_extension_start = from._extension_start;
_hash_start = from._hash_start;
_hash_end = from._hash_end;
_flags = from._flags;
return *this;
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Filename::string typecast operator

View File

@ -68,6 +68,11 @@ PUBLISHED:
Filename(const Filename &dirname, const Filename &basename);
INLINE ~Filename();
#ifdef USE_MOVE_SEMANTICS
INLINE Filename(string &&filename) NOEXCEPT;
INLINE Filename(Filename &&from) NOEXCEPT;
#endif
#ifdef HAVE_PYTHON
PyObject *__reduce__(PyObject *self) const;
#endif
@ -88,7 +93,7 @@ PUBLISHED:
Type type = T_general);
static Filename from_os_specific_w(const wstring &os_specific,
Type type = T_general);
static Filename expand_from(const string &user_string,
static Filename expand_from(const string &user_string,
Type type = T_general);
static Filename temporary(const string &dirname, const string &prefix,
const string &suffix = string(),
@ -105,6 +110,11 @@ PUBLISHED:
INLINE Filename &operator = (const char *filename);
INLINE Filename &operator = (const Filename &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE Filename &operator = (string &&filename) NOEXCEPT;
INLINE Filename &operator = (Filename &&from) NOEXCEPT;
#endif
// And retrieval is by any of the classic string operations.
INLINE operator const string & () const;
INLINE const char *c_str() const;

View File

@ -3204,7 +3204,8 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
}
extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
extra_param_check += " && " + param_name + "_long != NULL";
pexpr_string = "PyLong_AsUnsignedLongLong(" + param_name + "_long)";
pexpr_string = "(" + type->get_local_name(&parser) + ")" +
"PyLong_AsUnsignedLongLong(" + param_name + "_long)";
extra_cleanup += "Py_XDECREF(" + param_name + "_long);";
expected_params += "unsigned long long";
++num_params;
@ -3219,7 +3220,8 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
}
extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
extra_param_check += " && " + param_name + "_long != NULL";
pexpr_string = "PyLong_AsLongLong(" + param_name + "_long)";
pexpr_string = "(" + type->get_local_name(&parser) + ")" +
"PyLong_AsLongLong(" + param_name + "_long)";
extra_cleanup += "Py_XDECREF(" + param_name + "_long);";
expected_params += "long long";
++num_params;
@ -3234,7 +3236,8 @@ write_function_instance(ostream &out, InterfaceMaker::Object *obj,
}
extra_convert += "PyObject *" + param_name + "_long = PyNumber_Long(" + param_name + ");";
extra_param_check += " && " + param_name + "_long != NULL";
pexpr_string = "PyLong_AsUnsignedLong(" + param_name + "_long)";
pexpr_string = "(" + type->get_local_name(&parser) + ")" +
"PyLong_AsUnsignedLong(" + param_name + "_long)";
extra_cleanup += "Py_XDECREF(" + param_name + "_long);";
expected_params += "unsigned int";
++num_params;

1276
makepanda/installer.nsi Executable file

File diff suppressed because it is too large Load Diff

View File

@ -949,7 +949,7 @@ def CompileCxx(obj,src,opts):
if PkgSkip("TOUCHINPUT") == 0:
cmd += "/DWINVER=0x601 "
cmd += "/Fo" + obj + " /nologo /c"
if (GetTargetArch() != 'x64' and PkgSkip("SSE2") == 0):
if GetTargetArch() != 'x64' and (not PkgSkip("SSE2") or 'SSE2' in opts):
cmd += " /arch:SSE2"
for x in ipath: cmd += " /I" + x
for (opt,dir) in INCDIRECTORIES:
@ -1160,7 +1160,7 @@ def CompileCxx(obj,src,opts):
if optlevel >= 4 or GetTarget() == "android":
cmd += " -fno-rtti"
if PkgSkip("SSE2") == 0 and not arch.startswith("arm"):
if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm"):
cmd += " -msse2"
if optlevel >= 3:
@ -1705,7 +1705,7 @@ def RunGenPyCode(target, inputs, opts):
if (PkgSkip("PYTHON") != 0):
return
cmdstr = sys.executable + " "
cmdstr = BracketNameWithQuotes(SDK["PYTHONEXEC"]) + " "
if sys.version_info >= (2, 6):
cmdstr += "-B "
@ -1729,7 +1729,7 @@ def RunGenPyCode(target, inputs, opts):
def FreezePy(target, inputs, opts):
assert len(inputs) > 0
# Make sure this function isn't called before genpycode is run.
cmdstr = sys.executable + " "
cmdstr = BracketNameWithQuotes(SDK["PYTHONEXEC"]) + " "
if sys.version_info >= (2, 6):
cmdstr += "-B "
@ -1757,7 +1757,7 @@ def FreezePy(target, inputs, opts):
def Package(target, inputs, opts):
assert len(inputs) == 1
# Invoke the ppackage script.
command = sys.executable + " "
command = BracketNameWithQuotes(SDK["PYTHONEXEC"]) + " "
if GetOptimizeOption(opts) >= 4:
command += "-OO "
@ -3192,6 +3192,7 @@ if (not RUNTIME):
OPTS=['DIR:panda/src/pnmimage', 'BUILDING:PANDA', 'ZLIB']
TargetAdd('p3pnmimage_composite1.obj', opts=OPTS, input='p3pnmimage_composite1.cxx')
TargetAdd('p3pnmimage_composite2.obj', opts=OPTS, input='p3pnmimage_composite2.cxx')
TargetAdd('p3pnmimage_convert_srgb_sse2.obj', opts=OPTS+['SSE2'], input='convert_srgb_sse2.cxx')
OPTS=['DIR:panda/src/pnmimage', 'ZLIB']
IGATEFILES=GetDirectoryContents('panda/src/pnmimage', ["*.h", "*_composite*.cxx"])
@ -3621,6 +3622,7 @@ if (not RUNTIME):
TargetAdd('libpanda.dll', input='p3pnmimagetypes_composite2.obj')
TargetAdd('libpanda.dll', input='p3pnmimage_composite1.obj')
TargetAdd('libpanda.dll', input='p3pnmimage_composite2.obj')
TargetAdd('libpanda.dll', input='p3pnmimage_convert_srgb_sse2.obj')
TargetAdd('libpanda.dll', input='p3text_composite1.obj')
TargetAdd('libpanda.dll', input='p3text_composite2.obj')
TargetAdd('libpanda.dll', input='p3tform_composite1.obj')
@ -4609,7 +4611,7 @@ if (PkgSkip("DIRECT")==0):
OPTS=['DIR:direct/src/dcparser', 'WITHINPANDA', 'BUILDING:DIRECT', 'BISONPREFIX_dcyy']
CreateFile(GetOutputDir()+"/include/dcParser.h")
TargetAdd('p3dcparser_dcParser.obj', opts=OPTS, input='dcParser.yxx')
TargetAdd('dcParser.h', input='p3egg_parser.obj', opts=['DEPENDENCYONLY'])
TargetAdd('dcParser.h', input='p3dcparser_dcParser.obj', opts=['DEPENDENCYONLY'])
TargetAdd('p3dcparser_dcLexer.obj', opts=OPTS, input='dcLexer.lxx')
TargetAdd('p3dcparser_composite1.obj', opts=OPTS, input='p3dcparser_composite1.cxx')
TargetAdd('p3dcparser_composite2.obj', opts=OPTS, input='p3dcparser_composite2.cxx')
@ -6171,7 +6173,7 @@ except:
#
##########################################################################################
def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
def MakeInstallerNSIS(file, title, installdir):
if (os.path.isfile(file)):
os.remove(file)
elif (os.path.isdir(file)):
@ -6199,7 +6201,7 @@ def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
shutil.move("direct\\src\\plugin_installer\\p3d-setup.exe", file)
return
print("Building "+fullname+" installer. This can take up to an hour.")
print("Building "+title+" installer. This can take up to an hour.")
if (COMPRESSOR != "lzma"):
print("Note: you are using zlib, which is faster, but lzma gives better compression.")
if (os.path.exists("nsis-output.exe")):
@ -6210,19 +6212,13 @@ def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
nsis_defs = {
'COMPRESSOR' : COMPRESSOR,
'NAME' : fullname,
'SMDIRECTORY' : smdirectory,
'TITLE' : title,
'INSTALLDIR' : installdir,
'OUTFILE' : os.path.join(psource, 'nsis-output.exe'),
'LICENSE' : os.path.join(panda, 'LICENSE'),
'LANGUAGE' : "English",
'RUNTEXT' : "Visit the Panda Manual",
'IBITMAP' : "panda-install.bmp",
'UBITMAP' : "panda-install.bmp",
'PANDA' : panda,
'BUILT' : panda,
'SOURCE' : psource,
'PYVER' : SDK["PYTHONVERSION"][6:9],
'PANDACONF' : os.path.join(panda, 'etc'),
'PSOURCE' : psource,
'PYEXTRAS' : os.path.join(os.path.abspath(GetThirdpartyBase()), 'win-extras'),
'REGVIEW' : regview,
}
@ -6236,7 +6232,7 @@ def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
for item in nsis_defs.items():
cmd += ' -D%s="%s"' % item
cmd += ' "%s"' % (os.path.join(psource, 'direct', 'src', 'directscripts', 'packpanda.nsi'))
cmd += ' "%s"' % (os.path.join(psource, 'makepanda', 'installer.nsi'))
oscmd(cmd)
os.rename("nsis-output.exe", file)
@ -6761,14 +6757,14 @@ try:
if (GetOptimize() <= 2): dbg = "-dbg"
if GetTargetArch() == 'x64':
if (RUNTIME):
MakeInstallerNSIS("Panda3D-Runtime-"+VERSION+dbg+"-x64.exe", "Panda3D", "Panda3D "+VERSION, "C:\\Panda3D-"+VERSION+"-x64")
MakeInstallerNSIS("Panda3D-Runtime-"+VERSION+dbg+"-x64.exe", "Panda3D "+VERSION, "C:\\Panda3D-"+VERSION+"-x64")
else:
MakeInstallerNSIS("Panda3D-"+VERSION+dbg+"-x64.exe", "Panda3D", "Panda3D "+VERSION, "C:\\Panda3D-"+VERSION+"-x64")
MakeInstallerNSIS("Panda3D-"+VERSION+dbg+"-x64.exe", "Panda3D SDK "+VERSION, "C:\\Panda3D-"+VERSION+"-x64")
else:
if (RUNTIME):
MakeInstallerNSIS("Panda3D-Runtime-"+VERSION+dbg+".exe", "Panda3D", "Panda3D "+VERSION, "C:\\Panda3D-"+VERSION)
MakeInstallerNSIS("Panda3D-Runtime-"+VERSION+dbg+".exe", "Panda3D "+VERSION, "C:\\Panda3D-"+VERSION)
else:
MakeInstallerNSIS("Panda3D-"+VERSION+dbg+".exe", "Panda3D", "Panda3D "+VERSION, "C:\\Panda3D-"+VERSION)
MakeInstallerNSIS("Panda3D-"+VERSION+dbg+".exe", "Panda3D SDK "+VERSION, "C:\\Panda3D-"+VERSION)
elif (target == 'linux'):
MakeInstallerLinux()
elif (target == 'darwin'):

View File

@ -210,6 +210,8 @@ def PrettyTime(t):
return "%d sec" % (seconds)
def ProgressOutput(progress, msg, target = None):
sys.stdout.flush()
sys.stderr.flush()
prefix = ""
thisthread = threading.currentThread()
if thisthread is MAINTHREAD:
@ -235,6 +237,8 @@ def ProgressOutput(progress, msg, target = None):
suffix = GetColor()
print(''.join((prefix, msg, suffix)))
sys.stdout.flush()
sys.stderr.flush()
def exit(msg = ""):
sys.stdout.flush()
@ -498,7 +502,7 @@ def oscmd(cmd, ignoreError = False):
print(GetColor("blue") + cmd.split(" ", 1)[0] + " " + GetColor("magenta") + cmd.split(" ", 1)[1] + GetColor())
sys.stdout.flush()
if sys.platform == "win32":
if sys.platform in ("win32", "cygwin"):
exe = cmd.split()[0]
exe_path = LocateBinary(exe)
if exe_path is None:

View File

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 151 KiB

View File

@ -156,7 +156,7 @@ get_hit_fraction() const {
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
PandaNode *BulletRayHit::
const PandaNode *BulletRayHit::
get_node() const {
return (_object) ? (PandaNode *)_object->getUserPointer() : NULL;

View File

@ -33,7 +33,7 @@ struct EXPCL_PANDABULLET BulletRayHit {
PUBLISHED:
INLINE static BulletRayHit empty();
PandaNode *get_node() const;
const PandaNode *get_node() const;
LPoint3 get_hit_pos() const;
LVector3 get_hit_normal() const;
PN_stdfloat get_hit_fraction() const;

View File

@ -608,11 +608,12 @@ remove_vehicle(BulletVehicle *vehicle) {
////////////////////////////////////////////////////////////////////
// Function: BulletWorld::attach_constraint
// Access: Published
// Description: Deprecated!
// Please use BulletWorld::attach
// Description: Attaches a single constraint to a world. Collision
// checks between the linked objects will be disabled
// if the second parameter is set to TRUE.
////////////////////////////////////////////////////////////////////
void BulletWorld::
attach_constraint(BulletConstraint *constraint) {
attach_constraint(BulletConstraint *constraint, bool linked_collision) {
nassertv(constraint);
@ -622,7 +623,7 @@ attach_constraint(BulletConstraint *constraint) {
if (found == _constraints.end()) {
_constraints.push_back(constraint);
_world->addConstraint(constraint->ptr());
_world->addConstraint(constraint->ptr(), linked_collision);
}
else {
bullet_cat.warning() << "constraint already attached" << endl;

View File

@ -70,6 +70,8 @@ PUBLISHED:
// Attach/Remove
void attach(TypedObject *object);
void attach_constraint(BulletConstraint *constraint, bool linked_collision=false);
void remove(TypedObject *object);
// Ghost object
@ -172,7 +174,6 @@ PUBLISHED: // Deprecated methods, will become private soon
void attach_character(BulletBaseCharacterControllerNode *node);
void remove_character(BulletBaseCharacterControllerNode *node);
void attach_constraint(BulletConstraint *constraint);
void remove_constraint(BulletConstraint *constraint);
public:

View File

@ -144,15 +144,19 @@ test_intersection(const CollisionEntry &entry) const {
////////////////////////////////////////////////////////////////////
void CollisionBox::
xform(const LMatrix4 &mat) {
_min = _min * mat;
_max = _max * mat;
_center = _center * mat;
for(int v = 0; v < 8; v++)
for(int v = 0; v < 8; v++) {
_vertex[v] = _vertex[v] * mat;
for(int p = 0; p < 6 ; p++)
}
for(int p = 0; p < 6 ; p++) {
_planes[p] = set_plane(p);
_x = _vertex[0].get_x()-_center.get_x();
_y = _vertex[0].get_y()-_center.get_y();
_z = _vertex[0].get_z()-_center.get_z();
_radius = sqrt( _x*_x + _y*_y + _z*_z );
}
_x = _vertex[0].get_x() - _center.get_x();
_y = _vertex[0].get_y() - _center.get_y();
_z = _vertex[0].get_z() - _center.get_z();
_radius = sqrt(_x * _x + _y * _y + _z * _z);
setup_box();
mark_viz_stale();
mark_internal_bounds_stale();

View File

@ -1407,22 +1407,29 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
if (attrib == IN_ambient) {
#ifndef NDEBUG
Light *light = np.node()->as_light();
nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
#endif
// Lights don't currently have an ambient color in Panda3D.
// We still have to support the attribute.
t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
if (np.node()->is_of_type(AmbientLight::get_class_type())) {
LColor c = light->get_color();
c.componentwise_mult(_light_color_scale);
t.set_row(3, c);
} else {
// Non-ambient lights don't currently have an ambient color in Panda3D.
t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
}
return &t;
} else if (attrib == IN_diffuse) {
Light *light = np.node()->as_light();
nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
LColor c = light->get_color();
c.componentwise_mult(_light_color_scale);
t.set_row(3, c);
if (np.node()->is_of_type(AmbientLight::get_class_type())) {
// Ambient light has no diffuse color.
t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
} else {
LColor c = light->get_color();
c.componentwise_mult(_light_color_scale);
t.set_row(3, c);
}
return &t;
} else if (attrib == IN_specular) {
@ -1432,7 +1439,11 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
return &t;
} else if (attrib == IN_position) {
if (np.node()->is_of_type(DirectionalLight::get_class_type())) {
if (np.node()->is_of_type(AmbientLight::get_class_type())) {
// Ambient light has no position.
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
return &t;
} else if (np.node()->is_of_type(DirectionalLight::get_class_type())) {
DirectionalLight *light;
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
@ -1458,7 +1469,11 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
}
} else if (attrib == IN_halfVector) {
if (np.node()->is_of_type(DirectionalLight::get_class_type())) {
if (np.node()->is_of_type(AmbientLight::get_class_type())) {
// Ambient light has no half-vector.
t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
return &t;
} else if (np.node()->is_of_type(DirectionalLight::get_class_type())) {
DirectionalLight *light;
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
@ -1490,19 +1505,25 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
}
} else if (attrib == IN_spotDirection) {
LightLensNode *light;
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
Lens *lens = light->get_lens();
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
if (np.node()->is_of_type(AmbientLight::get_class_type())) {
// Ambient light has no spot direction.
t.set_row(3, LVector3(0.0f, 0.0f, 0.0f));
return &t;
} else {
LightLensNode *light;
DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
Lens *lens = light->get_lens();
nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
CPT(TransformState) transform =
get_scene()->get_cs_world_transform()->compose(
np.get_transform(_scene_setup->get_scene_root().get_parent()));
CPT(TransformState) transform =
get_scene()->get_cs_world_transform()->compose(
np.get_transform(_scene_setup->get_scene_root().get_parent()));
const LMatrix4 &light_mat = transform->get_mat();
LVector3 dir = lens->get_view_vector() * light_mat;
t.set_row(3, dir);
return &t;
const LMatrix4 &light_mat = transform->get_mat();
LVector3 dir = lens->get_view_vector() * light_mat;
t.set_row(3, dir);
return &t;
}
} else if (attrib == IN_spotCutoff) {
if (np.node()->is_of_type(Spotlight::get_class_type())) {

View File

@ -1476,6 +1476,10 @@ GROUPING ENTRIES
its geometry is used to define the extent of the collision
surface (unless the "descend" flag is given; see below).
It is now deprecated to use <Collide> without "descend"; it will
become the default soon. You should always specify it for best
compatibility.
Valid types so far are:
Plane
@ -1538,11 +1542,12 @@ GROUPING ENTRIES
descend
Instead of creating only one collision object of the given type,
each group descended from this node that contains geometry will
Each group descended from this node that contains geometry will
define a new collision object of the given type. The event
name, if any, will also be inherited from the top node and
shared among all the collision objects.
shared among all the collision objects. This option will soon
be the default; it is suggested that it is always specified for
most compatibility.
keep

View File

@ -223,8 +223,14 @@ HTTPDate(const string &format) {
if (_time != (time_t)-1) {
// Unfortunately, mktime() assumes local time; convert this back
// to GMT.
#ifdef IS_FREEBSD
time_t now = time(NULL);
struct tm *tp = localtime(&now);
_time -= tp->tm_gmtoff;
#else /* IS_FREEBSD */
extern long int timezone;
_time -= timezone;
#endif /* IS_FREEBSD */
}
#endif // __GNUC__
}

View File

@ -1865,6 +1865,10 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
node = new CollisionNode(egg_group->get_name());
make_collision_solids(egg_group, egg_group, (CollisionNode *)node.p());
// Transform all of the collision solids into local space.
node->xform(LCAST(PN_stdfloat, egg_group->get_vertex_to_node()));
if ((egg_group->get_collide_flags() & EggGroup::CF_keep) != 0) {
// If we also specified to keep the geometry, continue the
// traversal. In this case, we create a new PandaNode to be the
@ -1925,8 +1929,11 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
pnode->set_pos(center);
pnode->set_color(color);
pnode->set_radius(radius);
pnode->xform(LCAST(PN_stdfloat, egg_group->get_vertex_to_node()));
node = pnode;
} else if (egg_group->get_switch_flag()) {
if (egg_group->get_switch_fps() != 0.0) {
// Create a sequence node.
@ -2790,7 +2797,6 @@ find_first_polygon(EggGroup *egg_group) {
bool EggLoader::
make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags,
LPoint3 &center, PN_stdfloat &radius, LColor &color) {
bool success=false;
EggGroup *geom_group = find_collision_geometry(egg_group, flags);
if (geom_group != (EggGroup *)NULL) {
// Collect all of the vertices.
@ -2822,15 +2828,12 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags,
d_center /= (double)num_vertices;
//egg2pg_cat.debug() << "make_sphere d_center: " << d_center << "\n";
LMatrix4d mat = egg_group->get_vertex_to_node();
d_center = d_center * mat;
// And the furthest vertex determines the radius.
double radius2 = 0.0;
for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
EggVertex *vtx = (*vi);
LPoint3d p3 = vtx->get_pos3();
LVector3d v = p3 * mat - d_center;
LVector3d v = p3 - d_center;
radius2 = max(radius2, v.length_squared());
}
@ -2841,10 +2844,10 @@ make_sphere(EggGroup *egg_group, EggGroup::CollideFlags flags,
vi = vertices.begin();
EggVertex *clr_vtx = (*vi);
color = clr_vtx->get_color();
success = true;
return true;
}
}
return success;
return false;
}
////////////////////////////////////////////////////////////////////
@ -2900,9 +2903,8 @@ make_box(EggGroup *egg_group, EggGroup::CollideFlags flags,
max(max_pd[2], pos[2]));
}
LMatrix4d mat = egg_group->get_vertex_to_node();
min_p = LCAST(PN_stdfloat, min_pd * mat);
max_p = LCAST(PN_stdfloat, max_pd * mat);
min_p = LCAST(PN_stdfloat, min_pd);
max_p = LCAST(PN_stdfloat, max_pd);
return (min_pd != max_pd);
}
return false;
@ -2968,6 +2970,10 @@ make_collision_solids(EggGroup *start_group, EggGroup *egg_group,
make_collision_solids(start_group, DCAST(EggGroup, *ci), cnode);
}
}
} else {
egg2pg_cat.warning()
<< "Using <Collide> without 'descend' is deprecated. 'descend' "
<< "will become the default in a future version of Panda3D.\n";
}
}
@ -3170,7 +3176,6 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
// also determine the centroid). We compute this in node space.
size_t num_vertices = vertices.size();
if (num_vertices != 0) {
LMatrix4d mat = egg_group->get_vertex_to_node();
pvector<LPoint3d> vpos;
vpos.reserve(num_vertices);
@ -3178,7 +3183,7 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
pset<EggVertex *>::const_iterator vi;
for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
EggVertex *vtx = (*vi);
LPoint3d pos = vtx->get_pos3() * mat;
const LPoint3d &pos = vtx->get_pos3();
vpos.push_back(pos);
center += pos;
}
@ -3420,20 +3425,18 @@ create_collision_plane(EggPolygon *egg_poly, EggGroup *parent_group) {
<< "\n";
}
LMatrix4d mat = egg_poly->get_vertex_to_node();
pvector<LVertex> vertices;
if (!egg_poly->empty()) {
EggPolygon::const_iterator vi;
vi = egg_poly->begin();
LVertexd vert = (*vi)->get_pos3() * mat;
LVertexd vert = (*vi)->get_pos3();
vertices.push_back(LCAST(PN_stdfloat, vert));
LVertexd last_vert = vert;
++vi;
while (vi != egg_poly->end()) {
vert = (*vi)->get_pos3() * mat;
vert = (*vi)->get_pos3();
if (!vert.almost_equal(last_vert)) {
vertices.push_back(LCAST(PN_stdfloat, vert));
}
@ -3461,7 +3464,6 @@ void EggLoader::
create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
EggGroup *parent_group,
EggGroup::CollideFlags flags) {
LMatrix4d mat = egg_poly->get_vertex_to_node();
PT(EggGroup) group = new EggGroup;
@ -3489,13 +3491,13 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
EggPolygon::const_iterator vi;
vi = poly->begin();
LVertexd vert = (*vi)->get_pos3() * mat;
LVertexd vert = (*vi)->get_pos3();
vertices.push_back(LCAST(PN_stdfloat, vert));
LVertexd last_vert = vert;
++vi;
while (vi != poly->end()) {
vert = (*vi)->get_pos3() * mat;
vert = (*vi)->get_pos3();
if (!vert.almost_equal(last_vert)) {
vertices.push_back(LCAST(PN_stdfloat, vert));
}
@ -3513,12 +3515,11 @@ create_collision_polygons(CollisionNode *cnode, EggPolygon *egg_poly,
if (cspoly->is_valid()) {
apply_collision_flags(cspoly, flags);
cnode->add_solid(cspoly);
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: EggLoader::create_collision_floor_mesh
// Access: Private

View File

@ -22,6 +22,7 @@
#include "transformState.h"
#include "colorScaleAttrib.h"
#include "colorAttrib.h"
#include "materialAttrib.h"
#include "textureAttrib.h"
#include "cullFaceAttrib.h"
#include "transparencyAttrib.h"
@ -347,7 +348,7 @@ convert_character_bundle(PartGroup *bundleNode, EggGroupNode *egg_parent, Charac
CharacterJoint *character_joint = DCAST(CharacterJoint, bundleNode);
LMatrix4 transformf;
character_joint->get_net_transform(transformf);
character_joint->get_transform(transformf);
LMatrix4d transformd(LCAST(double, transformf));
EggGroup *joint = new EggGroup(bundleNode->get_name());
joint->add_matrix4(transformd);
@ -577,6 +578,13 @@ convert_primitive(const GeomVertexData *vertex_data,
}
}
// Check for a material.
EggMaterial *egg_mat = (EggMaterial *)NULL;
const MaterialAttrib *ma = DCAST(MaterialAttrib, net_state->get_attrib(MaterialAttrib::get_class_type()));
if (ma != (const MaterialAttrib *)NULL) {
egg_mat = get_egg_material(ma->get_material());
}
// Check for a texture.
EggTexture *egg_tex = (EggTexture *)NULL;
const TextureAttrib *ta = DCAST(TextureAttrib, net_state->get_attrib(TextureAttrib::get_class_type()));
@ -703,11 +711,15 @@ convert_primitive(const GeomVertexData *vertex_data,
// Huh, an unknown geometry type.
return;
}
for (int i = 0; i < num_primitives; ++i) {
PT(EggPrimitive) egg_prim = (*make_func)();
egg_parent->add_child(egg_prim);
if (egg_mat != (EggMaterial *)NULL) {
egg_prim->set_material(egg_mat);
}
if (egg_tex != (EggTexture *)NULL) {
egg_prim->set_texture(egg_tex);
}
@ -947,6 +959,41 @@ apply_tag(EggGroup *egg_group, PandaNode *node, const string &tag) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: EggSaver::get_egg_material
// Access: Private
// Description: Returns an EggMaterial pointer that corresponds to
// the indicated Material.
////////////////////////////////////////////////////////////////////
EggMaterial *EggSaver::
get_egg_material(Material *mat) {
if (mat != (Material *)NULL) {
EggMaterial temp(mat->get_name());
if (mat->has_ambient()) {
temp.set_amb(mat->get_ambient());
}
if (mat->has_diffuse()) {
temp.set_diff(mat->get_diffuse());
}
if (mat->has_specular()) {
temp.set_spec(mat->get_specular());
}
if (mat->has_emission()) {
temp.set_emit(mat->get_emission());
}
temp.set_shininess(mat->get_shininess());
temp.set_local(mat->get_local());
return _materials.create_unique_material(temp, ~EggMaterial::E_mref_name);
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: EggSaver::get_egg_texture
// Access: Private

View File

@ -92,6 +92,7 @@ private:
bool apply_tags(EggGroup *egg_group, PandaNode *node);
bool apply_tag(EggGroup *egg_group, PandaNode *node, const string &tag);
EggMaterial *get_egg_material(Material *tex);
EggTexture *get_egg_texture(Texture *tex);
static EggPrimitive *make_egg_polygon();
@ -102,8 +103,8 @@ private:
PT(EggData) _data;
PT(EggVertexPool) _vpool;
EggTextureCollection _textures;
EggMaterialCollection _materials;
EggTextureCollection _textures;
};
#include "eggSaver.I"

View File

@ -1,5 +1,5 @@
// Filename: eglGraphicsBuffer.cxx
// Created by: pro-rsoft (13Jun09)
// Created by: rdb (13Jun09)
//
////////////////////////////////////////////////////////////////////
//
@ -28,7 +28,7 @@ TypeHandle eglGraphicsBuffer::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
eglGraphicsBuffer::
eglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
eglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,
@ -187,7 +187,7 @@ open_buffer() {
_gsg = eglgsg;
}
}
if (eglgsg->_fbconfig == None) {
// If we didn't use an fbconfig to create the GSG, we can't create
// a PBuffer.
@ -195,11 +195,11 @@ open_buffer() {
}
int attrib_list[] = {
EGL_WIDTH, _x_size,
EGL_HEIGHT, _y_size,
EGL_WIDTH, _size.get_x(),
EGL_HEIGHT, _size.get_y(),
EGL_NONE
};
_pbuffer = eglCreatePbufferSurface(eglgsg->_egl_display, eglgsg->_fbconfig, attrib_list);
if (_pbuffer == EGL_NO_SURFACE) {
@ -224,7 +224,7 @@ open_buffer() {
return false;
}
_fb_properties = eglgsg->get_fb_properties();
_is_valid = true;
return true;
}

View File

@ -1,5 +1,5 @@
// Filename: eglGraphicsBuffer.h
// Created by: pro-rsoft (13Jun09)
// Created by: rdb (13Jun09)
//
////////////////////////////////////////////////////////////////////
//

View File

@ -1,5 +1,5 @@
// Filename: eglGraphicsPixmap.cxx
// Created by: pro-rsoft (13Jun09)
// Created by: rdb (13Jun09)
//
////////////////////////////////////////////////////////////////////
//
@ -29,7 +29,7 @@ TypeHandle eglGraphicsPixmap::_type_handle;
// Description:
////////////////////////////////////////////////////////////////////
eglGraphicsPixmap::
eglGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe,
eglGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe,
const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,
@ -105,7 +105,7 @@ begin_frame(FrameMode mode, Thread *current_thread) {
}
clear_cube_map_selection();
}
_gsg->set_current_properties(&get_fb_properties());
return _gsg->begin_frame(current_thread);
}
@ -195,7 +195,7 @@ open_buffer() {
_gsg = eglgsg;
}
}
if (eglgsg->_fbconfig == None) {
// If we didn't use an fbconfig to create the GSG, we can't create
// a PBuffer.
@ -221,8 +221,8 @@ open_buffer() {
}
}
_x_pixmap = XCreatePixmap(_display, _drawable,
_x_size, _y_size, visual_info->depth);
_x_pixmap = XCreatePixmap(_display, _drawable,
_size.get_x(), _size.get_y(), visual_info->depth);
if (_x_pixmap == None) {
egldisplay_cat.error()
<< "Failed to create X pixmap.\n";
@ -253,7 +253,7 @@ open_buffer() {
return false;
}
_fb_properties = eglgsg->get_fb_properties();
_is_valid = true;
return true;
}

View File

@ -1,5 +1,5 @@
// Filename: eglGraphicsPixmap.h
// Created by: pro-rsoft (13Jun09)
// Created by: rdb (13Jun09)
//
////////////////////////////////////////////////////////////////////
//
@ -29,7 +29,7 @@
////////////////////////////////////////////////////////////////////
class eglGraphicsPixmap : public GraphicsBuffer {
public:
eglGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe,
eglGraphicsPixmap(GraphicsEngine *engine, GraphicsPipe *pipe,
const string &name,
const FrameBufferProperties &fb_prop,
const WindowProperties &win_prop,

View File

@ -82,6 +82,33 @@ operator = (const Datagram &copy) {
_stdfloat_double = copy._stdfloat_double;
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Datagram::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE Datagram::
Datagram(Datagram &&from) NOEXCEPT :
_data(move(from._data)),
_stdfloat_double(from._stdfloat_double)
{
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Datagram::Move Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void Datagram::
operator = (Datagram &&from) NOEXCEPT {
_data = move(from._data);
_stdfloat_double = from._stdfloat_double;
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: Datagram::add_bool
// Access: Public

View File

@ -48,6 +48,11 @@ PUBLISHED:
INLINE Datagram(const Datagram &copy);
INLINE void operator = (const Datagram &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE Datagram(Datagram &&from) NOEXCEPT;
INLINE void operator = (Datagram &&from) NOEXCEPT;
#endif
virtual ~Datagram();
virtual void clear();

View File

@ -77,6 +77,21 @@ PointerToArray(const PointerToArray<Element> &copy) :
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::Move Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArray<Element>::
PointerToArray(PointerToArray<Element> &&from) NOEXCEPT :
PointerToArrayBase<Element>(move(from)),
_type_handle(from._type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::begin
// Access: Public
@ -682,6 +697,21 @@ operator = (const PointerToArray<Element> &copy) {
return *this;
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::Assignment operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArray<Element> &PointerToArray<Element>::
operator = (PointerToArray<Element> &&from) NOEXCEPT {
_type_handle = from._type_handle;
((PointerToArray<Element> *)this)->reassign(move(from));
return *this;
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArray::clear
// Access: Public
@ -736,6 +766,36 @@ ConstPointerToArray(const ConstPointerToArray<Element> &copy) :
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Move Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element>::
ConstPointerToArray(PointerToArray<Element> &&from) NOEXCEPT :
PointerToArrayBase<Element>(move(from)),
_type_handle(from._type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Move Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element>::
ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT :
PointerToArrayBase<Element>(move(from)),
_type_handle(from._type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::begin
// Access: Public
@ -1141,6 +1201,36 @@ operator = (const ConstPointerToArray<Element> &copy) {
return *this;
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Assignment operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
operator = (PointerToArray<Element> &&from) NOEXCEPT {
_type_handle = from._type_handle;
((ConstPointerToArray<Element> *)this)->reassign(move(from));
return *this;
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::Assignment operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE ConstPointerToArray<Element> &ConstPointerToArray<Element>::
operator = (ConstPointerToArray<Element> &&from) NOEXCEPT {
_type_handle = from._type_handle;
((ConstPointerToArray<Element> *)this)->reassign(move(from));
return *this;
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ConstPointerToArray::clear
// Access: Public

View File

@ -151,6 +151,10 @@ public:
INLINE PointerToArray(size_type n, const Element &value, TypeHandle type_handle = get_type_handle(Element));
INLINE PointerToArray(const PointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE PointerToArray(PointerToArray<Element> &&from) NOEXCEPT;
#endif
public:
// Duplicating the interface of vector. The following member
// functions are all const, because they do not reassign the
@ -231,6 +235,12 @@ public:
operator = (ReferenceCountedVector<Element> *ptr);
INLINE PointerToArray<Element> &
operator = (const PointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE PointerToArray<Element> &
operator = (PointerToArray<Element> &&from) NOEXCEPT;
#endif
INLINE void clear();
private:
@ -305,6 +315,11 @@ PUBLISHED:
INLINE ConstPointerToArray(const PointerToArray<Element> &copy);
INLINE ConstPointerToArray(const ConstPointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE ConstPointerToArray(PointerToArray<Element> &&from) NOEXCEPT;
INLINE ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT;
#endif
// Duplicating the interface of vector.
INLINE iterator begin() const;
@ -355,6 +370,14 @@ PUBLISHED:
operator = (const PointerToArray<Element> &copy);
INLINE ConstPointerToArray<Element> &
operator = (const ConstPointerToArray<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE ConstPointerToArray<Element> &
operator = (PointerToArray<Element> &&from) NOEXCEPT;
INLINE ConstPointerToArray<Element> &
operator = (ConstPointerToArray<Element> &&from) NOEXCEPT;
#endif
INLINE void clear();
private:

View File

@ -57,11 +57,11 @@ template<class Element>
INLINE ReferenceCountedVector<Element>::
~ReferenceCountedVector() {
}
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::size
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE TYPENAME ReferenceCountedVector<Element>::size_type ReferenceCountedVector<Element>::
@ -72,7 +72,7 @@ size() const {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::insert
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE TYPENAME ReferenceCountedVector<Element>::iterator ReferenceCountedVector<Element>::
@ -83,7 +83,7 @@ insert(iterator position, const Element &x) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::insert
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -94,7 +94,7 @@ insert(iterator position, size_type n, const Element &x) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::erase
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -105,7 +105,7 @@ erase(iterator position) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::erase
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -116,7 +116,7 @@ erase(iterator first, iterator last) {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::pop_back
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -127,7 +127,7 @@ pop_back() {
////////////////////////////////////////////////////////////////////
// Function: ReferenceCountedVector::clear
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE void ReferenceCountedVector<Element>::
@ -138,7 +138,7 @@ clear() {
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Constructor
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::
@ -150,7 +150,7 @@ PointerToArrayBase(ReferenceCountedVector<Element> *ptr) :
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Copy Constructor
// Access: Protected
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::
@ -159,10 +159,24 @@ PointerToArrayBase(const PointerToArrayBase<Element> &copy) :
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Move Constructor
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::
PointerToArrayBase(PointerToArrayBase<Element> &&from) NOEXCEPT :
PointerToBase<ReferenceCountedVector<Element> >(move(from))
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: PointerToArrayBase::Destructor
// Access: Published
// Description:
// Description:
////////////////////////////////////////////////////////////////////
template<class Element>
INLINE PointerToArrayBase<Element>::

View File

@ -82,6 +82,10 @@ protected:
INLINE PointerToArrayBase(ReferenceCountedVector<Element> *ptr);
INLINE PointerToArrayBase(const PointerToArrayBase<Element> &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE PointerToArrayBase(PointerToArrayBase<Element> &&from) NOEXCEPT;
#endif
PUBLISHED:
INLINE ~PointerToArrayBase();
};

View File

@ -22,26 +22,33 @@
// Python buffer protocol.
////////////////////////////////////////////////////////////////////
template<class Element>
void Extension<PointerToArray<Element> >::
INLINE void Extension<PointerToArray<Element> >::
__init__(PyObject *self, PyObject *source) {
#if PY_VERSION_HEX >= 0x02060000
if (PyObject_CheckBuffer(source)) {
// User passed a buffer object.
Py_buffer view;
if (PyObject_GetBuffer(source, &view, PyBUF_CONTIG_RO) == -1) {
PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a contiguous buffer");
PyErr_SetString(PyExc_TypeError,
"PointerToArray constructor requires a contiguous buffer");
return;
}
if (view.itemsize != 1 && view.itemsize != sizeof(Element)) {
PyErr_SetString(PyExc_TypeError, "buffer.itemsize does not match PointerToArray element size");
PyErr_SetString(PyExc_TypeError,
"buffer.itemsize does not match PointerToArray element size");
return;
}
int num_elements = view.len / sizeof(Element);
this->_this->insert(this->_this->begin(), num_elements, Element());
if (view.len % sizeof(Element) != 0) {
PyErr_Format(PyExc_ValueError,
"byte buffer is not a multiple of %zu bytes",
sizeof(Element));
return;
}
if (view.len > 0) {
this->_this->resize(view.len / sizeof(Element));
memcpy(this->_this->p(), view.buf, view.len);
}
@ -52,21 +59,22 @@ __init__(PyObject *self, PyObject *source) {
if (!PySequence_Check(source)) {
// If passed with a non-sequence, this isn't the right constructor.
PyErr_SetString(PyExc_TypeError, "PointerToArray constructor requires a sequence or buffer object");
PyErr_SetString(PyExc_TypeError,
"PointerToArray constructor requires a sequence or buffer object");
return;
}
// If we were passed a Python string, then instead of storing it
// character-at-a-time, just load the whole string as a data
// buffer.
// buffer. Not sure if this case is still necessary - don't Python
// str/bytes objects export the buffer protocol, as above?
#if PY_MAJOR_VERSION >= 3
if (PyBytes_Check(source)) {
int size = PyBytes_Size(source);
if (size % sizeof(Element) != 0) {
ostringstream stream;
stream << "Buffer not a multiple of " << sizeof(Element) << " bytes";
string str = stream.str();
PyErr_SetString(PyExc_ValueError, str.c_str());
PyErr_Format(PyExc_ValueError,
"bytes object is not a multiple of %zu bytes",
sizeof(Element));
return;
}
@ -85,10 +93,9 @@ __init__(PyObject *self, PyObject *source) {
if (PyString_CheckExact(source)) {
int size = PyString_Size(source);
if (size % sizeof(Element) != 0) {
ostringstream stream;
stream << "Buffer not a multiple of " << sizeof(Element) << " bytes";
string str = stream.str();
PyErr_SetString(PyExc_ValueError, str.c_str());
PyErr_Format(PyExc_ValueError,
"str object is not a multiple of %zu bytes",
sizeof(Element));
return;
}
@ -107,20 +114,29 @@ __init__(PyObject *self, PyObject *source) {
// Now construct the internal list by copying the elements
// one-at-a-time from Python.
PyObject *push_back = PyObject_GetAttrString(self, "push_back");
if (push_back == NULL) {
PyErr_BadArgument();
return;
}
// We need to initialize the this pointer before we can call push_back.
((Dtool_PyInstDef *)self)->_ptr_to_object = (void *)this->_this;
int size = PySequence_Size(source);
for (int i = 0; i < size; ++i) {
PyObject *item = PySequence_GetItem(source, i);
if (item == NULL) {
return;
}
PyObject *result = PyObject_CallMethod(self, (char *)"push_back", (char *)"O", item);
PyObject *result = PyObject_CallFunctionObjArgs(push_back, item, NULL);
Py_DECREF(item);
if (result == NULL) {
// Unable to add item--probably it wasn't of the appropriate type.
ostringstream stream;
stream << "Element " << i << " in sequence passed to PointerToArray constructor could not be added";
string str = stream.str();
PyErr_SetString(PyExc_TypeError, str.c_str());
PyErr_Print();
PyErr_Format(PyExc_TypeError,
"Element %d in sequence passed to PointerToArray "
"constructor could not be added", i);
return;
}
Py_DECREF(result);
@ -161,7 +177,9 @@ __setitem__(size_t n, const Element &value) {
template<class Element>
INLINE void Extension<ConstPointerToArray<Element> >::
__init__(PyObject *self, PyObject *source) {
new (this->_this) ConstPointerToArray<Element>(get_type_handle(Element));
PointerToArray<Element> array;
invoke_extension(&array).__init__(self, source);
*(this->_this) = MOVE(array);
}
////////////////////////////////////////////////////////////////////
@ -240,7 +258,7 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const {
if (view->internal != NULL) {
// Oh, right, let's not forget to unref this.
((const PointerToArray<Element> *) view->internal)->unref();
unref_delete((const PointerToArray<Element> *)view->internal);
view->internal = NULL;
}
}
@ -314,7 +332,7 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const {
if (view->internal != NULL) {
// Oh, right, let's not forget to unref this.
((const PointerToArray<Element> *) view->internal)->unref();
unref_delete((const PointerToArray<Element> *)view->internal);
view->internal = NULL;
}
}

View File

@ -66,6 +66,26 @@ public:
#endif
};
#ifdef _MSC_VER
// Ugh... MSVC needs this because they still don't have a decent linker.
#include "PTA_uchar.h"
#include "PTA_ushort.h"
#include "PTA_float.h"
#include "PTA_double.h"
#include "PTA_int.h"
template class EXPORT_THIS Extension<PTA_uchar>;
template class EXPORT_THIS Extension<PTA_ushort>;
template class EXPORT_THIS Extension<PTA_float>;
template class EXPORT_THIS Extension<PTA_double>;
template class EXPORT_THIS Extension<PTA_int>;
template class EXPORT_THIS Extension<CPTA_uchar>;
template class EXPORT_THIS Extension<CPTA_ushort>;
template class EXPORT_THIS Extension<CPTA_float>;
template class EXPORT_THIS Extension<CPTA_double>;
template class EXPORT_THIS Extension<CPTA_int>;
#endif
// This macro is used to map a data type to a format code
// as used in the Python 'struct' and 'array' modules.
#define get_format_code(type) _get_format_code((const type *)0)

View File

@ -148,7 +148,11 @@ FfmpegAudioCursor(FfmpegAudio *src) :
_can_seek = true;
_can_seek_fast = true;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
_frame = av_frame_alloc();
#else
_frame = avcodec_alloc_frame();
#endif
_packet = new AVPacket;
_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE / 2;
@ -194,7 +198,9 @@ FfmpegAudioCursor::
void FfmpegAudioCursor::
cleanup() {
if (_frame) {
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 45, 101)
av_frame_free(&_frame);
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
avcodec_free_frame(&_frame);
#else
av_free(&_frame);
@ -313,8 +319,7 @@ reload_buffer() {
#ifdef HAVE_SWRESAMPLE
if (_resample_ctx) {
// Resample the data to signed 16-bit sample format.
uint8_t* out[SWR_CH_MAX] = {(uint8_t*) _buffer, NULL};
bufsize = swr_convert(_resample_ctx, out, _buffer_size / 2, (const uint8_t**)_frame->extended_data, _frame->nb_samples);
bufsize = swr_convert(_resample_ctx, (uint8_t **)&_buffer, _buffer_size / 2, (const uint8_t**)_frame->extended_data, _frame->nb_samples);
bufsize *= _audio_channels * 2;
} else
#endif

View File

@ -94,8 +94,13 @@ init_from(FfmpegVideo *source) {
PIX_FMT_BGR24, SWS_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL);
#endif // HAVE_SWSCALE
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
_frame = av_frame_alloc();
_frame_out = av_frame_alloc();
#else
_frame = avcodec_alloc_frame();
_frame_out = avcodec_alloc_frame();
#endif
if ((_frame == 0)||(_frame_out == 0)) {
cleanup();

View File

@ -798,15 +798,28 @@ next_anim_control() {
if (_anim_controls_enabled) {
destroy_anim_controls();
if (_anim_controls.get_num_anims() == 0) {
set_anim_controls(false);
return;
}
// Stop the active animation.
pause_button();
++_anim_index;
if (_anim_index >= _anim_controls.get_num_anims()) {
set_anim_controls(false);
_anim_controls.loop_all(true);
} else {
create_anim_controls();
play_button();
}
} else {
_anim_index = 0;
set_anim_controls(true);
if (_anim_controls.get_num_anims() > 0) {
play_button();
}
}
}
@ -1451,6 +1464,23 @@ create_anim_controls() {
AnimControl *control = _anim_controls.get_anim(_anim_index);
nassertv(control != (AnimControl *)NULL);
if (control->get_num_frames() <= 1) {
// Don't show the controls when the animation has only 0 or 1 frames.
ostringstream text;
text << _anim_controls.get_anim_name(_anim_index);
text << " (" << control->get_num_frames() << " frame"
<< ((control->get_num_frames() == 1) ? "" : "s") << ")";
PT(TextNode) label = new TextNode("label");
label->set_align(TextNode::A_center);
label->set_text(text.str());
NodePath tnp = _anim_controls_group.attach_new_node(label);
tnp.set_pos(0.0f, 0.0f, 0.07f);
tnp.set_scale(0.1f);
return;
}
PT(TextNode) label = new TextNode("anim_name");
label->set_align(TextNode::A_left);
label->set_text(_anim_controls.get_anim_name(_anim_index));
@ -1525,13 +1555,17 @@ update_anim_controls() {
AnimControl *control = _anim_controls.get_anim(_anim_index);
nassertv(control != (AnimControl *)NULL);
if (_anim_slider->is_button_down()) {
control->pose((int)(_anim_slider->get_value() + 0.5));
} else {
_anim_slider->set_value((PN_stdfloat)control->get_frame());
if (_anim_slider != NULL) {
if (_anim_slider->is_button_down()) {
control->pose((int)(_anim_slider->get_value() + 0.5));
} else {
_anim_slider->set_value((PN_stdfloat)control->get_frame());
}
}
_frame_number->set_text(format_string(control->get_frame()));
if (_frame_number != NULL) {
_frame_number->set_text(format_string(control->get_frame()));
}
control->set_play_rate(_play_rate_slider->get_value());
}

View File

@ -57,7 +57,7 @@
// #include <GLES2/gl2ext.h>
#endif
#include "panda_esgl2ext.h"
#include "panda_esgl2ext.h"
// This helps to keep the source clean of hundreds of #ifdefs.
typedef char GLchar;
@ -100,20 +100,19 @@ typedef char GLchar;
#define GL_RGBA16F GL_RGBA16F_EXT
#define GL_RGB32F GL_RGB32F_EXT
#define GL_RGBA32F GL_RGBA32F_EXT
#define GL_DEBUG_SEVERITY_HIGH GL_DEBUG_SEVERITY_HIGH_KHR
#define GL_DEBUG_SEVERITY_MEDIUM GL_DEBUG_SEVERITY_MEDIUM_KHR
#define GL_DEBUG_SEVERITY_LOW GL_DEBUG_SEVERITY_LOW_KHR
#define GL_DEBUG_SEVERITY_NOTIFICATION GL_DEBUG_SEVERITY_NOTIFICATION_KHR
#define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR
#define GL_FRAMEBUFFER_SRGB GL_FRAMEBUFFER_SRGB_EXT
#define GL_SRGB GL_SRGB_EXT
#define GL_SRGB_ALPHA GL_SRGB_ALPHA_EXT
#define GL_SRGB8 GL_SRGB8_EXT
#define GL_SRGB8_ALPHA GL_SRGB8_ALPHA_EXT
#define GL_SLUMINANCE GL_SLUMINANCE_NV
#define GL_SLUMINANCE_ALPHA GL_SLUMINANCE_ALPHA_NV
#define GL_SLUMINANCE8 GL_SLUMINANCE8_NV
#define GL_SLUMINANCE8_ALPHA GL_SLUMINANCE8_ALPHA_NV
#define GL_SRGB8_ALPHA8 GL_SRGB8_ALPHA8_EXT
#define GL_RGBA8 GL_RGBA8_OES
#define GL_R8 GL_R8_EXT
#define GL_RG8 GL_RG8_EXT
#define GL_ALPHA8 GL_ALPHA8_OES
#define GL_LUMINANCE8 GL_LUMINANCE8_OES
#define GL_LUMINANCE8_ALPHA8 GL_LUMINANCE8_ALPHA8_EXT
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT
#define GL_R32F GL_R32F_EXT
#define GL_RG32F GL_RG32F_EXT
#define GL_RGB8 GL_RGB8_OES
#undef SUPPORT_IMMEDIATE_MODE
#define APIENTRY

View File

@ -115,6 +115,9 @@
#define GL_RGBA16F GL_RGBA16F_EXT
#define GL_RGB32F GL_RGB32F_EXT
#define GL_RGBA32F GL_RGBA32F_EXT
#define GL_ALPHA8 GL_ALPHA8_EXT
#define GL_LUMINANCE8 GL_LUMINANCE8_EXT
#define GL_LUMINANCE8_ALPHA8 GL_LUMINANCE8_ALPHA8_EXT
#undef SUPPORT_IMMEDIATE_MODE
#define APIENTRY

View File

@ -41,7 +41,6 @@ CLP(CgShaderContext)::
CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) {
_glgsg = glgsg;
_cg_program = 0;
_glsl_profile = false;
nassertv(s->get_language() == Shader::SL_Cg);
@ -63,10 +62,6 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
release_resources();
} else {
if (cgGetProgramProfile(_cg_program) == CG_PROFILE_GLSLC) {
_glsl_profile = true;
}
cgGLLoadProgram(_cg_program);
CGerror error = cgGetError();
if (error != CG_NO_ERROR) {
@ -412,7 +407,7 @@ disable_shader_vertex_arrays() {
CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
if (p == 0) continue;
if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) {
if (cgGetParameterBaseResource(p) == CG_ATTR0) {
int index = cgGetParameterResourceIndex(p);
if (index >= 8) {
_glgsg->_glClientActiveTexture(GL_TEXTURE0 + (index - 8));
@ -501,11 +496,9 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
num_values = GL_BGRA;
}
// This is truly the most preposterous hack. When using the GLSL
// profiles, cgGLSetParameterPointer relies on the the driver mapping
// standard attributes to fixed indices (and breaking the spec doing
// so), which only the NVIDIA drivers do. Unbelievable.
if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) {
// cgGLSetParameterPointer is just stupidly bugged on every level.
// Sigh. This seems to work on both NVIDIA and AMD cards now.
if (cgGetParameterBaseResource(p) == CG_ATTR0) {
int index = cgGetParameterResourceIndex(p);
switch (index) {
case 0: // gl_Vertex

View File

@ -52,7 +52,6 @@ public:
private:
CGprogram _cg_program;
bool _glsl_profile;
pvector<CGparameter> _cg_parameter_map;

View File

@ -1674,7 +1674,7 @@ resolve_multisamples() {
GL_NEAREST);
}
// Now handle the other color buffers.
#ifndef OPENGLES_1
#ifndef OPENGLES
int next = GL_COLOR_ATTACHMENT1_EXT;
if (_fb_properties.is_stereo()) {
glReadBuffer(next);

View File

@ -745,9 +745,12 @@ call_glTexParameterfv(GLenum target, GLenum pname, const LVecBase4 &value) {
// Access: Public
// Description: Convert index to gl light id
////////////////////////////////////////////////////////////////////
INLINE GLenum CLP(GraphicsStateGuardian)::get_light_id(int index) const {
INLINE GLenum CLP(GraphicsStateGuardian)::
get_light_id(int index) const {
#ifndef OPENGLES_2
return GL_LIGHT0 + index;
#else
return 0;
#endif
}
@ -760,6 +763,8 @@ INLINE GLenum CLP(GraphicsStateGuardian)::
get_clip_plane_id(int index) const {
#ifndef OPENGLES_2
return GL_CLIP_PLANE0 + index;
#else
return 0;
#endif
}

View File

@ -127,16 +127,16 @@ null_glBlendColor(GLclampf, GLclampf, GLclampf, GLclampf) {
// a fixed-function pipeline.
// This default shader just outputs a red color, telling
// the user that something went wrong.
CPT(Shader::ShaderFile) default_shader_name = new Shader::ShaderFile("default-shader");
CPT(Shader::ShaderFile) default_shader_body = new Shader::ShaderFile("\
uniform mediump mat4 p3d_ModelViewProjectionMatrix;\
attribute highp vec4 p3d_Vertex;\
void main(void) {\
gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;\
}\n",
"void main(void) {\
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\
}\n", "", "", "");
static const string default_vshader =
"uniform mediump mat4 p3d_ModelViewProjectionMatrix;\n"
"attribute highp vec4 p3d_Vertex;\n"
"void main(void) {\n"
" gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;\n"
"}\n";
static const string default_fshader =
"void main(void) {\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
#endif
@ -558,10 +558,13 @@ reset() {
_glPrimitiveRestartIndex = NULL;
if (gl_support_primitive_restart_index) {
if (is_at_least_gl_version(4, 3) || has_extension("GL_ARB_ES3_compatibility")) {
if ((is_at_least_gl_version(4, 3) || has_extension("GL_ARB_ES3_compatibility")) &&
_gl_renderer.substr(0, 7) != "Gallium") {
// As long as we enable this, OpenGL will always use the highest possible index
// for a numeric type as strip cut index, which coincides with our convention.
// This saves us a call to glPrimitiveRestartIndex.
// This saves us a call to glPrimitiveRestartIndex
// ... of course, though, the Gallium driver bugs out here. See also:
// https://www.panda3d.org/forums/viewtopic.php?f=5&t=17512
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
_supported_geom_rendering |= Geom::GR_strip_cut_index;
@ -1370,7 +1373,7 @@ reset() {
// if it failed to compile. This default shader just outputs
// a red color, indicating that something went wrong.
if (_default_shader == NULL) {
_default_shader = new Shader(default_shader_name, default_shader_body, Shader::SL_GLSL);
_default_shader = Shader::load(Shader::SL_GLSL, default_vshader, default_fshader);
}
#endif
@ -1915,6 +1918,8 @@ reset() {
}
_supports_sampler_objects = false;
#ifndef OPENGLES
if (gl_support_sampler_objects &&
((is_at_least_gl_version(3, 3) || has_extension("GL_ARB_sampler_objects")))) {
_glGenSamplers = (PFNGLGENSAMPLERSPROC) get_extension_func("glGenSamplers");
@ -1935,6 +1940,7 @@ reset() {
_supports_sampler_objects = true;
}
}
#endif // OPENGLES
// Check availability of multi-bind functions.
_supports_multi_bind = false;
@ -1944,10 +1950,12 @@ reset() {
_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)
get_extension_func("glBindImageTextures");
#ifndef OPENGLES
if (_supports_sampler_objects) {
_glBindSamplers = (PFNGLBINDSAMPLERSPROC)
get_extension_func("glBindSamplers");
}
#endif // OPENGLES
if (_glBindTextures != NULL && _glBindImageTextures != NULL) {
_supports_multi_bind = true;
@ -2011,14 +2019,18 @@ reset() {
_supports_stencil_wrap =
has_extension("GL_EXT_stencil_wrap") || has_extension("GL_OES_stencil_wrap");
_supports_two_sided_stencil = has_extension("GL_EXT_stencil_two_side");
if (_supports_two_sided_stencil) {
_supports_two_sided_stencil = false;
#ifndef OPENGLES
if (has_extension("GL_EXT_stencil_two_side")) {
_glActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)
get_extension_func("glActiveStencilFaceEXT");
}
else {
_supports_two_sided_stencil = true;
} else {
_glActiveStencilFaceEXT = 0;
}
#endif
#ifndef OPENGLES
// Some drivers expose one, some expose the other. ARB seems to be the newer one.
@ -2618,9 +2630,11 @@ clear_before_callback() {
// Clear the bound sampler object, so that we do not inadvertently
// override the callback's desired sampler settings.
#ifndef OPENGLES
if (_supports_sampler_objects) {
_glBindSampler(0, 0);
}
#endif
}
////////////////////////////////////////////////////////////////////
@ -2761,7 +2775,7 @@ begin_frame(Thread *current_thread) {
}*/
#endif
#ifndef OPENGLES_1
#ifndef OPENGLES
if (_current_properties->get_srgb_color()) {
glEnable(GL_FRAMEBUFFER_SRGB);
}
@ -2819,7 +2833,7 @@ void CLP(GraphicsStateGuardian)::
end_frame(Thread *current_thread) {
report_my_gl_errors();
#ifndef OPENGLES_1
#ifndef OPENGLES
if (_current_properties->get_srgb_color()) {
glDisable(GL_FRAMEBUFFER_SRGB);
}
@ -4521,8 +4535,10 @@ prepare_sampler(const SamplerState &sampler) {
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
release_sampler(SamplerContext *sc) {
#ifndef OPENGLES
CLP(SamplerContext) *gsc = DCAST(CLP(SamplerContext), sc);
delete gsc;
#endif
}
////////////////////////////////////////////////////////////////////
@ -5205,7 +5221,7 @@ make_geom_munger(const RenderState *state, Thread *current_thread) {
// from the camera plane. The point is assumed to be
// in the GSG's internal coordinate system.
////////////////////////////////////////////////////////////////////
PN_stdfloat GLGraphicsStateGuardian::
PN_stdfloat CLP(GraphicsStateGuardian)::
compute_distance_to(const LPoint3 &point) const {
return -point[2];
}
@ -7447,7 +7463,7 @@ get_external_image_format(Texture *tex) const {
break;
case Texture::CM_dxt1:
#ifndef OPENGLES_1
#ifndef OPENGLES
if (format == Texture::F_srgb_alpha) {
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
} else if (format == Texture::F_srgb) {
@ -7484,13 +7500,13 @@ get_external_image_format(Texture *tex) const {
#else
case Texture::CM_pvr1_2bpp:
#ifndef OPENGLES_1
#ifndef OPENGLES
if (format == Texture::F_srgb_alpha) {
return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
} else if (format == Texture::F_srgb) {
return GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
} else
#endif // OPENGLES_1
#endif // OPENGLES
if (Texture::has_alpha(format)) {
return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
} else {
@ -7498,13 +7514,13 @@ get_external_image_format(Texture *tex) const {
}
case Texture::CM_pvr1_4bpp:
#ifndef OPENGLES_1
#ifndef OPENGLES
if (format == Texture::F_srgb_alpha) {
return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
} else if (format == Texture::F_srgb) {
return GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
} else
#endif // OPENGLES_1
#endif // OPENGLES
if (Texture::has_alpha(format)) {
return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
} else {
@ -7762,7 +7778,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
#endif
case Texture::CM_dxt1:
#ifndef OPENGLES_1
#ifndef OPENGLES
if (format == Texture::F_srgb_alpha) {
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
} else if (format == Texture::F_srgb) {
@ -7798,13 +7814,6 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
}
#else
case Texture::CM_pvr1_2bpp:
#ifndef OPENGLES_1
if (format == Texture::F_srgb_alpha) {
return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
} else if (format == Texture::F_srgb) {
return GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
} else
#endif // OPENGLES_1
if (Texture::has_alpha(format)) {
return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
} else {
@ -7812,13 +7821,6 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
}
case Texture::CM_pvr1_4bpp:
#ifndef OPENGLES_1
if (format == Texture::F_srgb_alpha) {
return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
} else if (format == Texture::F_srgb) {
return GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
} else
#endif // OPENGLES_1
if (Texture::has_alpha(format)) {
return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
} else {
@ -7843,7 +7845,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
case Texture::F_depth_stencil:
if (_supports_depth_stencil) {
#ifndef OPENGLES_1
#ifndef OPENGLES
if (tex->get_component_type() == Texture::T_float) {
return GL_DEPTH32F_STENCIL8;
} else
@ -7903,7 +7905,10 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
#ifndef OPENGLES_1
if (tex->get_component_type() == Texture::T_float) {
return GL_RGBA16F;
} else if (tex->get_component_type() == Texture::T_unsigned_short) {
} else
#endif
#ifndef OPENGLES
if (tex->get_component_type() == Texture::T_unsigned_short) {
return GL_RGBA16;
} else
#endif
@ -7949,7 +7954,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
case Texture::F_rgba12:
return GL_RGBA12;
#endif // OPENGLES
#ifndef OPENGLES_1
#ifndef OPENGLES
case Texture::F_rgba16:
if (tex->get_component_type() == Texture::T_float) {
return GL_RGBA16F;
@ -8040,26 +8045,36 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
return force_sized ? GL_ALPHA8 : GL_ALPHA;
case Texture::F_luminance:
#ifndef OPENGLES
if (tex->get_component_type() == Texture::T_float) {
return GL_LUMINANCE16F_ARB;
} else if (tex->get_component_type() == Texture::T_unsigned_short) {
return GL_LUMINANCE16;
} else {
} else
#endif // OPENGLES
{
return force_sized ? GL_LUMINANCE8 : GL_LUMINANCE;
}
case Texture::F_luminance_alpha:
case Texture::F_luminance_alphamask:
#ifndef OPENGLES
if (tex->get_component_type() == Texture::T_float || tex->get_component_type() == Texture::T_unsigned_short) {
return GL_LUMINANCE_ALPHA16F_ARB;
} else {
} else
#endif // OPENGLES
{
return force_sized ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE_ALPHA;
}
#ifndef OPENGLES_1
case Texture::F_srgb:
#ifndef OPENGLES
return GL_SRGB8;
#endif
case Texture::F_srgb_alpha:
return GL_SRGB8_ALPHA8;
#endif
#ifndef OPENGLES
case Texture::F_sluminance:
return GL_SLUMINANCE8;
case Texture::F_sluminance_alpha:
@ -9043,7 +9058,7 @@ set_state_and_transform(const RenderState *target,
////////////////////////////////////////////////////////////////////
void CLP(GraphicsStateGuardian)::
free_pointers() {
#ifdef HAVE_CG
#if defined(HAVE_CG) && !defined(OPENGLES)
if (_cg_context != 0) {
cgDestroyContext(_cg_context);
_cg_context = 0;
@ -10081,6 +10096,7 @@ bool CLP(GraphicsStateGuardian)::
apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc);
#ifndef OPENGLES
if (_supports_sampler_objects) {
// We support sampler objects. Prepare the sampler object and
// bind it to the indicated texture unit.
@ -10097,7 +10113,9 @@ apply_sampler(GLuint unit, const SamplerState &sampler, TextureContext *tc) {
<< "bind " << unit << " " << sampler << "\n";
}
} else {
} else
#endif // OPENGLES
{
// We don't support sampler objects. We'll have to bind the
// texture and change the texture parameters if they don't match.
if (gtc->_active_sampler != sampler) {
@ -10678,6 +10696,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
if (tex->has_clear_color()) {
// The texture has a clear color, so we should fill this mipmap
// level to a solid color.
#ifndef OPENGLES
if (_supports_clear_texture) {
// We can do that with the convenient glClearTexImage function.
string clear_data = tex->get_clear_data();
@ -10685,12 +10704,13 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
_glClearTexImage(gtc->_index, n - mipmap_bias, external_format,
component_type, (void *)clear_data.data());
continue;
} else {
// Ask the Texture class to create the mipmap level in RAM.
// It'll fill it in with the correct clear color, which we
// can then upload.
ptimage = tex->make_ram_mipmap_image(n);
}
#endif // OPENGLES
// Ask the Texture class to create the mipmap level in RAM.
// It'll fill it in with the correct clear color, which we
// can then upload.
ptimage = tex->make_ram_mipmap_image(n);
} else {
// No clear color and no more images.
break;
@ -10726,13 +10746,8 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
_data_transferred_pcollector.add_level(view_size);
#endif
switch (texture_target) {
#ifdef OPENGLES_2
case GL_TEXTURE_3D_OES:
#endif
#ifndef OPENGLES
case GL_TEXTURE_3D:
#endif
#ifndef OPENGLES_1
case GL_TEXTURE_3D:
if (_supports_3d_texture) {
if (image_compression == Texture::CM_off) {
_glTexSubImage3D(page_target, n - mipmap_bias, 0, 0, 0, width, height, depth,
@ -10746,7 +10761,9 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
return false;
}
break;
#endif // OPENGLES_1
#ifndef OPENGLES
case GL_TEXTURE_1D:
if (image_compression == Texture::CM_off) {
glTexSubImage1D(page_target, n - mipmap_bias, 0, width,
@ -10756,7 +10773,8 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
external_format, view_size, image_ptr);
}
break;
#endif
#endif // OPENGLES
#ifndef OPENGLES
case GL_TEXTURE_2D_ARRAY_EXT:
if (_supports_2d_texture_array) {
@ -10772,7 +10790,8 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
return false;
}
break;
#endif
#endif // OPENGLES
default:
if (image_compression == Texture::CM_off) {
if (n==0) {
@ -11319,7 +11338,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
type = Texture::T_unsigned_int_24_8;
format = Texture::F_depth_stencil;
break;
#ifndef OPENGLES_1
#ifndef OPENGLES
case GL_DEPTH32F_STENCIL8:
type = Texture::T_float;
format = Texture::F_depth_stencil;
@ -11483,26 +11502,34 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
format = Texture::F_alpha;
break;
case GL_LUMINANCE:
#ifndef OPENGLES
case GL_LUMINANCE16:
case GL_LUMINANCE16F_ARB:
#endif
case 1:
format = Texture::F_luminance;
break;
case GL_LUMINANCE_ALPHA:
#ifndef OPENGLES
case GL_LUMINANCE_ALPHA16F_ARB:
#endif
case 2:
format = Texture::F_luminance_alpha;
break;
#ifndef OPENGLES_1
case GL_SRGB:
#ifndef OPENGLES
case GL_SRGB8:
#endif
format = Texture::F_srgb;
break;
case GL_SRGB_ALPHA:
case GL_SRGB8_ALPHA8:
format = Texture::F_srgb_alpha;
break;
#endif // OPENGLES_1
#ifndef OPENGLES
case GL_SLUMINANCE:
case GL_SLUMINANCE8:
format = Texture::F_sluminance;
@ -11511,7 +11538,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
case GL_SLUMINANCE8_ALPHA8:
format = Texture::F_sluminance_alpha;
break;
#endif
#endif // OPENGLES
#ifndef OPENGLES
case GL_COMPRESSED_RGB:
@ -11561,7 +11588,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
format = Texture::F_rgbm;
compression = Texture::CM_dxt1;
break;
#ifndef OPENGLES_1
#ifndef OPENGLES
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
format = Texture::F_srgb;
compression = Texture::CM_dxt1;
@ -11572,25 +11599,6 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
break;
#endif
#ifdef OPENGLES_2
case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
format = Texture::F_srgb;
compression = Texture::CM_pvr1_2bpp;
break;
case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
format = Texture::F_srgb_alpha;
compression = Texture::CM_pvr1_2bpp;
break;
case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
format = Texture::F_srgb;
compression = Texture::CM_pvr1_4bpp;
break;
case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
format = Texture::F_srgb_alpha;
compression = Texture::CM_pvr1_4bpp;
break;
#endif // OPENGLES_2
#ifdef OPENGLES
case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
format = Texture::F_rgb;
@ -11963,6 +11971,7 @@ do_issue_stencil() {
<< "SRS_back_stencil_pass_z_pass_operation " << (int)stencil->get_render_state(StencilAttrib::SRS_back_stencil_pass_z_pass_operation) << "\n";
}
#ifndef OPENGLES
if (_supports_two_sided_stencil) {
//TODO: add support for OpenGL 2.0-style glStencilFuncSeparate.
unsigned int back_compare;
@ -11989,6 +11998,7 @@ do_issue_stencil() {
_glActiveStencilFaceEXT(GL_FRONT);
}
#endif // OPENGLES
unsigned int front_compare;
front_compare = stencil->get_render_state(StencilAttrib::SRS_front_comparison_function);
@ -12018,9 +12028,11 @@ do_issue_stencil() {
}
} else {
glDisable(GL_STENCIL_TEST);
#ifndef OPENGLES
if (_supports_two_sided_stencil) {
glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
}
#endif // OPENGLES
}
}
@ -12067,9 +12079,12 @@ do_issue_scissor() {
if (_scissor_array.size() > 0) {
// Scissoring is enabled on the display region.
// Revert to the scissor state specified in the DisplayRegion.
#ifndef OPENGLES
if (_supports_viewport_arrays) {
_glScissorArrayv(0, _scissor_array.size(), _scissor_array[0].get_data());
} else {
} else
#endif // OPENGLES
{
const LVecBase4i sr = _scissor_array[0];
glScissor(sr[0], sr[1], sr[2], sr[3]);
}

View File

@ -14,6 +14,8 @@
#include "pnotify.h"
#ifndef OPENGLES
TypeHandle CLP(SamplerContext)::_type_handle;
////////////////////////////////////////////////////////////////////
@ -81,3 +83,5 @@ reset_data() {
// re-load the sampler later.
//glGenSamplers(1, &_index);
}
#endif // OPENGLES

View File

@ -12,6 +12,8 @@
//
////////////////////////////////////////////////////////////////////
#ifndef OPENGLES
#include "pandabase.h"
#include "samplerContext.h"
#include "deletedChain.h"
@ -56,3 +58,5 @@ public:
private:
static TypeHandle _type_handle;
};
#endif // OPENGLES

View File

@ -412,6 +412,20 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
s->_mat_spec.push_back(bind);
continue;
}
if (noprefix == "Color") {
Shader::ShaderMatSpec bind;
bind._id = arg_id;
bind._piece = Shader::SMP_row3;
bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_attr_color;
bind._arg[0] = NULL;
bind._dep[0] = Shader::SSD_general | Shader::SSD_color;
bind._part[1] = Shader::SMO_identity;
bind._arg[1] = NULL;
bind._dep[1] = Shader::SSD_NONE;
s->_mat_spec.push_back(bind);
continue;
}
if (noprefix == "ClipPlane") {
for (int i = 0; i < param_size; ++i) {
Shader::ShaderMatSpec bind;
@ -821,10 +835,12 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
param_type == GL_INT_VEC2 ||
param_type == GL_INT_VEC3 ||
param_type == GL_INT_VEC4 ||
param_type == GL_UNSIGNED_INT ||
#ifndef OPENGLES
param_type == GL_UNSIGNED_INT_VEC2 ||
param_type == GL_UNSIGNED_INT_VEC3 ||
param_type == GL_UNSIGNED_INT_VEC4);
param_type == GL_UNSIGNED_INT_VEC4 ||
#endif
param_type == GL_UNSIGNED_INT );
if (noprefix.empty()) {
// Arbitrarily named attribute.
@ -863,12 +879,16 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
// Get the number of bind points.
switch (param_type) {
case GL_FLOAT_MAT3:
#ifndef OPENGLES
case GL_DOUBLE_MAT3:
#endif
bind._elements = 3 * param_size;
break;
case GL_FLOAT_MAT4:
#ifndef OPENGLES
case GL_DOUBLE_MAT4:
#endif
bind._elements = 4 * param_size;
break;

View File

@ -283,7 +283,9 @@ void CLP(init_classes)() {
CLP(ShaderContext)::init_type();
#endif
CLP(TextureContext)::init_type();
#ifndef OPENGLES
CLP(SamplerContext)::init_type();
#endif
CLP(VertexBufferContext)::init_type();
CLP(GraphicsBuffer)::init_type();

View File

@ -36,7 +36,7 @@ make(PyUnicodeObject *str) {
}
string name(c_str, len);
return InternalName::make(c_str, len);
return InternalName::make(name);
}
InternalName::PyInternTable::const_iterator it;

View File

@ -18,6 +18,7 @@
#include "pandabase.h"
#include "adaptiveLru.h"
#include "simpleLru.h"
#include "samplerState.h"
#include "savedContext.h"

View File

@ -21,6 +21,7 @@
#include "namable.h"
#include "luse.h"
#include "numeric_types.h"
#include "bamReader.h"
#include "config_gobj.h"
class FactoryParams;

View File

@ -41,6 +41,7 @@
#include "pbitops.h"
#include "streamReader.h"
#include "texturePeeker.h"
#include "convert_srgb.h"
#ifdef HAVE_SQUISH
#include <squish.h>
@ -131,46 +132,6 @@ struct DDSHeader {
DDSCaps2 caps;
};
// This table is used for converting unsigned char texture values in an sRGB
// texture to linear RGB values, for use in mipmap generation.
static float srgb_to_lrgbf[256] = {0.000000f, 0.000304f, 0.000607f, 0.000911f,
0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f,
0.006049f, 0.006512f, 0.006995f, 0.007499f, 0.008023f, 0.008568f, 0.009134f,
0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f,
0.014444f, 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f,
0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, 0.025187f, 0.026241f,
0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f,
0.035601f, 0.036889f, 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f,
0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, 0.054480f,
0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f,
0.068478f, 0.070360f, 0.072272f, 0.074214f, 0.076185f, 0.078187f, 0.080220f,
0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f,
0.114435f, 0.116971f, 0.119538f, 0.122139f, 0.124772f, 0.127438f, 0.130136f,
0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f,
0.152926f, 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f,
0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, 0.191202f, 0.194618f,
0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f,
0.223228f, 0.226966f, 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f,
0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, 0.274677f,
0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f,
0.309469f, 0.313989f, 0.318547f, 0.323143f, 0.327778f, 0.332452f, 0.337164f,
0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
0.376262f, 0.381326f, 0.386429f, 0.391572f, 0.396755f, 0.401978f, 0.407240f,
0.412543f, 0.417885f, 0.423268f, 0.428690f, 0.434154f, 0.439657f, 0.445201f,
0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473531f, 0.479320f, 0.485150f,
0.491021f, 0.496933f, 0.502886f, 0.508881f, 0.514918f, 0.520996f, 0.527115f,
0.533276f, 0.539479f, 0.545724f, 0.552011f, 0.558340f, 0.564712f, 0.571125f,
0.577580f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f,
0.623960f, 0.630757f, 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f,
0.672443f, 0.679542f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, 0.715694f,
0.723055f, 0.730461f, 0.737910f, 0.745404f, 0.752942f, 0.760525f, 0.768151f,
0.775822f, 0.783538f, 0.791298f, 0.799103f, 0.806952f, 0.814847f, 0.822786f,
0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f,
0.947307f, 0.955973f, 0.964686f, 0.973445f, 0.982251f, 0.991102f, 1.000000f};
////////////////////////////////////////////////////////////////////
// Function: Texture::Constructor
// Access: Published
@ -6990,7 +6951,13 @@ do_filter_2d_mipmap_pages(const CData *cdata,
// We currently only support sRGB mipmap generation for
// unsigned byte textures, due to our use of a lookup table.
nassertv(cdata->_component_type == T_unsigned_byte);
filter_component = &filter_2d_unsigned_byte_srgb;
if (has_sse2_sRGB_encode()) {
filter_component = &filter_2d_unsigned_byte_srgb_sse2;
} else {
filter_component = &filter_2d_unsigned_byte_srgb;
}
// Alpha is always linear.
filter_alpha = &filter_2d_unsigned_byte;
@ -7140,7 +7107,13 @@ do_filter_3d_mipmap_level(const CData *cdata,
// We currently only support sRGB mipmap generation for
// unsigned byte textures, due to our use of a lookup table.
nassertv(cdata->_component_type == T_unsigned_byte);
filter_component = &filter_3d_unsigned_byte_srgb;
if (has_sse2_sRGB_encode()) {
filter_component = &filter_3d_unsigned_byte_srgb_sse2;
} else {
filter_component = &filter_3d_unsigned_byte_srgb;
}
// Alpha is always linear.
filter_alpha = &filter_3d_unsigned_byte;
@ -7385,18 +7358,32 @@ filter_2d_unsigned_byte(unsigned char *&p, const unsigned char *&q,
void Texture::
filter_2d_unsigned_byte_srgb(unsigned char *&p, const unsigned char *&q,
size_t pixel_size, size_t row_size) {
float result = (srgb_to_lrgbf[q[0]] +
srgb_to_lrgbf[q[pixel_size]] +
srgb_to_lrgbf[q[row_size]] +
srgb_to_lrgbf[q[pixel_size + row_size]]) / 4.0f;
float result = (decode_sRGB_float(q[0]) +
decode_sRGB_float(q[pixel_size]) +
decode_sRGB_float(q[row_size]) +
decode_sRGB_float(q[pixel_size + row_size]));
// This is based on the formula out of the EXT_texture_sRGB
// specification, except the factors are multiplied with 255.0f.
if (result < 0.0031308f) {
*p = (unsigned char)(result * 3294.6f);
} else {
*p = (unsigned char)(269.025f * powf(result, 0.41666f) - 14.025f);
}
*p = encode_sRGB_uchar(result * 0.25f);
++p;
++q;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::filter_2d_unsigned_byte_srgb_sse2
// Access: Public, Static
// Description: Averages a 2x2 block of pixel components into a
// single pixel component, for producing the next mipmap
// level. Increments p and q to the next component.
////////////////////////////////////////////////////////////////////
void Texture::
filter_2d_unsigned_byte_srgb_sse2(unsigned char *&p, const unsigned char *&q,
size_t pixel_size, size_t row_size) {
float result = (decode_sRGB_float(q[0]) +
decode_sRGB_float(q[pixel_size]) +
decode_sRGB_float(q[row_size]) +
decode_sRGB_float(q[pixel_size + row_size]));
*p = encode_sRGB_uchar_sse2(result * 0.25f);
++p;
++q;
}
@ -7470,22 +7457,40 @@ filter_3d_unsigned_byte(unsigned char *&p, const unsigned char *&q,
void Texture::
filter_3d_unsigned_byte_srgb(unsigned char *&p, const unsigned char *&q,
size_t pixel_size, size_t row_size, size_t page_size) {
float result = (srgb_to_lrgbf[q[0]] +
srgb_to_lrgbf[q[pixel_size]] +
srgb_to_lrgbf[q[row_size]] +
srgb_to_lrgbf[q[pixel_size + row_size]] +
srgb_to_lrgbf[q[page_size]] +
srgb_to_lrgbf[q[pixel_size + page_size]] +
srgb_to_lrgbf[q[row_size + page_size]] +
srgb_to_lrgbf[q[pixel_size + row_size + page_size]]) / 8.0f;
float result = (decode_sRGB_float(q[0]) +
decode_sRGB_float(q[pixel_size]) +
decode_sRGB_float(q[row_size]) +
decode_sRGB_float(q[pixel_size + row_size]) +
decode_sRGB_float(q[page_size]) +
decode_sRGB_float(q[pixel_size + page_size]) +
decode_sRGB_float(q[row_size + page_size]) +
decode_sRGB_float(q[pixel_size + row_size + page_size]));
// This is based on the formula out of the EXT_texture_sRGB
// specification, except the factors are multiplied with 255.0f.
if (result < 0.0031308f) {
*p = (unsigned char)(result * 3294.6f);
} else {
*p = (unsigned char)(269.025f * powf(result, 0.41666f) - 14.025f);
}
*p = encode_sRGB_uchar(result * 0.125f);
++p;
++q;
}
////////////////////////////////////////////////////////////////////
// Function: Texture::filter_3d_unsigned_byte_srgb_sse2
// Access: Public, Static
// Description: Averages a 2x2x2 block of pixel components into a
// single pixel component, for producing the next mipmap
// level. Increments p and q to the next component.
////////////////////////////////////////////////////////////////////
void Texture::
filter_3d_unsigned_byte_srgb_sse2(unsigned char *&p, const unsigned char *&q,
size_t pixel_size, size_t row_size, size_t page_size) {
float result = (decode_sRGB_float(q[0]) +
decode_sRGB_float(q[pixel_size]) +
decode_sRGB_float(q[row_size]) +
decode_sRGB_float(q[pixel_size + row_size]) +
decode_sRGB_float(q[page_size]) +
decode_sRGB_float(q[pixel_size + page_size]) +
decode_sRGB_float(q[row_size + page_size]) +
decode_sRGB_float(q[pixel_size + row_size + page_size]));
*p = encode_sRGB_uchar_sse2(result * 0.125f);
++p;
++q;
}

View File

@ -749,6 +749,9 @@ private:
static void filter_2d_unsigned_byte_srgb(unsigned char *&p,
const unsigned char *&q,
size_t pixel_size, size_t row_size);
static void filter_2d_unsigned_byte_srgb_sse2(unsigned char *&p,
const unsigned char *&q,
size_t pixel_size, size_t row_size);
static void filter_2d_unsigned_short(unsigned char *&p,
const unsigned char *&q,
size_t pixel_size, size_t row_size);
@ -763,6 +766,10 @@ private:
const unsigned char *&q,
size_t pixel_size, size_t row_size,
size_t page_size);
static void filter_3d_unsigned_byte_srgb_sse2(unsigned char *&p,
const unsigned char *&q,
size_t pixel_size, size_t row_size,
size_t page_size);
static void filter_3d_unsigned_short(unsigned char *&p,
const unsigned char *&q,
size_t pixel_size, size_t row_size,

View File

@ -353,7 +353,7 @@ bool FLOATNAME(LMatrix3)::
almost_equal(const FLOATNAME(LMatrix3) &other, FLOATTYPE threshold) const {
TAU_PROFILE("bool LMatrix3::almost_equal(const LMatrix3 &, FLOATTYPE)", " ", TAU_USER);
#ifdef HAVE_EIGEN
return ((_m - other._m).cwiseAbs().maxCoeff() < NEARLY_ZERO(FLOATTYPE));
return ((_m - other._m).cwiseAbs().maxCoeff() < threshold);
#else
return (IS_THRESHOLD_EQUAL((*this)(0, 0), other(0, 0), threshold) &&
IS_THRESHOLD_EQUAL((*this)(0, 1), other(0, 1), threshold) &&

View File

@ -296,7 +296,7 @@ bool FLOATNAME(LMatrix4)::
almost_equal(const FLOATNAME(LMatrix4) &other, FLOATTYPE threshold) const {
TAU_PROFILE("bool LMatrix4::almost_equal(const LMatrix4 &, FLOATTYPE)", " ", TAU_USER);
#ifdef HAVE_EIGEN
return ((_m - other._m).cwiseAbs().maxCoeff() < NEARLY_ZERO(FLOATTYPE));
return ((_m - other._m).cwiseAbs().maxCoeff() < threshold);
#else
return (IS_THRESHOLD_EQUAL((*this)(0, 0), other(0, 0), threshold) &&
IS_THRESHOLD_EQUAL((*this)(0, 1), other(0, 1), threshold) &&

View File

@ -0,0 +1,28 @@
// Filename: pta_LMatrix3_ext.h
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef PTA_LMATRIX3_EXT_H
#define PTA_LMATRIX3_EXT_H
#include "pointerToArray_ext.h"
#include "pta_LMatrix3.h"
#if defined(_MSC_VER) && !defined(CPPPARSER)
template class EXPORT_THIS Extension<PTA_LMatrix3f>;
template class EXPORT_THIS Extension<PTA_LMatrix3d>;
template class EXPORT_THIS Extension<CPTA_LMatrix3f>;
template class EXPORT_THIS Extension<CPTA_LMatrix3d>;
#endif
#endif

View File

@ -0,0 +1,28 @@
// Filename: pta_LMatrix4_ext.h
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef PTA_LMATRIX4_EXT_H
#define PTA_LMATRIX4_EXT_H
#include "pointerToArray_ext.h"
#include "pta_LMatrix4.h"
#if defined(_MSC_VER) && !defined(CPPPARSER)
template class EXPORT_THIS Extension<PTA_LMatrix4f>;
template class EXPORT_THIS Extension<PTA_LMatrix4d>;
template class EXPORT_THIS Extension<CPTA_LMatrix4f>;
template class EXPORT_THIS Extension<CPTA_LMatrix4d>;
#endif
#endif

View File

@ -0,0 +1,30 @@
// Filename: pta_LVecBase2_ext.h
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef PTA_LVECBASE2_EXT_H
#define PTA_LVECBASE2_EXT_H
#include "pointerToArray_ext.h"
#include "pta_LVecBase2.h"
#if defined(_MSC_VER) && !defined(CPPPARSER)
template class EXPORT_THIS Extension<PTA_LVecBase2f>;
template class EXPORT_THIS Extension<PTA_LVecBase2d>;
template class EXPORT_THIS Extension<PTA_LVecBase2i>;
template class EXPORT_THIS Extension<CPTA_LVecBase2f>;
template class EXPORT_THIS Extension<CPTA_LVecBase2d>;
template class EXPORT_THIS Extension<CPTA_LVecBase2i>;
#endif
#endif

View File

@ -0,0 +1,30 @@
// Filename: pta_LVecBase3_ext.h
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef PTA_LVECBASE3_EXT_H
#define PTA_LVECBASE3_EXT_H
#include "pointerToArray_ext.h"
#include "pta_LVecBase3.h"
#if defined(_MSC_VER) && !defined(CPPPARSER)
template class EXPORT_THIS Extension<PTA_LVecBase3f>;
template class EXPORT_THIS Extension<PTA_LVecBase3d>;
template class EXPORT_THIS Extension<PTA_LVecBase3i>;
template class EXPORT_THIS Extension<CPTA_LVecBase3f>;
template class EXPORT_THIS Extension<CPTA_LVecBase3d>;
template class EXPORT_THIS Extension<CPTA_LVecBase3i>;
#endif
#endif

View File

@ -0,0 +1,30 @@
// Filename: pta_LVecBase4_ext.h
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef PTA_LVECBASE4_EXT_H
#define PTA_LVECBASE4_EXT_H
#include "pointerToArray_ext.h"
#include "pta_LVecBase4.h"
#if defined(_MSC_VER) && !defined(CPPPARSER)
template class EXPORT_THIS Extension<PTA_LVecBase4f>;
template class EXPORT_THIS Extension<PTA_LVecBase4d>;
template class EXPORT_THIS Extension<PTA_LVecBase4i>;
template class EXPORT_THIS Extension<CPTA_LVecBase4f>;
template class EXPORT_THIS Extension<CPTA_LVecBase4d>;
template class EXPORT_THIS Extension<CPTA_LVecBase4i>;
#endif
#endif

View File

@ -79,6 +79,7 @@
occluderNode.I occluderNode.h \
pandaNode.I pandaNode.h \
pandaNodeChain.I pandaNodeChain.h \
paramNodePath.I paramNodePath.h \
planeNode.I planeNode.h \
polylightEffect.I polylightEffect.h \
polylightNode.I polylightNode.h \
@ -184,6 +185,7 @@
occluderNode.cxx \
pandaNode.cxx \
pandaNodeChain.cxx \
paramNodePath.cxx \
planeNode.cxx \
polylightEffect.cxx \
polylightNode.cxx \
@ -286,6 +288,7 @@
pandaNode.I pandaNode.h \
pandaNode_ext.h pandaNode_ext.cxx \
pandaNodeChain.I pandaNodeChain.h \
paramNodePath.I paramNodePath.h \
planeNode.I planeNode.h \
polylightEffect.I polylightEffect.h \
polylightNode.I polylightNode.h \

View File

@ -60,6 +60,7 @@
#include "nodePath.h"
#include "nodePathComponent.h"
#include "pandaNode.h"
#include "paramNodePath.h"
#include "planeNode.h"
#include "polylightEffect.h"
#include "polylightNode.h"
@ -436,6 +437,7 @@ init_libpgraph() {
NodePathComponent::init_type();
PandaNode::init_type();
PandaNodePipelineReader::init_type();
ParamNodePath::init_type();
PlaneNode::init_type();
PolylightNode::init_type();
PolylightEffect::init_type();

View File

@ -20,6 +20,7 @@
#include "cullBinEnums.h"
#include "pointerTo.h"
#include "pvector.h"
#include "epvector.h"
#include "pmap.h"
#include "vector_int.h"
#include "pStatCollector.h"

View File

@ -343,11 +343,11 @@ try_load_file(const Filename &pathname, const LoaderOptions &options,
return result;
}
}
}
if (loader_cat.is_debug()) {
loader_cat.debug()
<< "Model " << pathname << " not found in cache.\n";
if (loader_cat.is_debug()) {
loader_cat.debug()
<< "Model " << pathname << " not found in cache.\n";
}
}
bool cache_only = (options.get_flags() & LoaderOptions::LF_cache_only) != 0;

View File

@ -38,6 +38,9 @@
#include "pta_LVecBase3.h"
#include "pta_LVecBase2.h"
#include "stl_compares.h"
#include "shaderInput.h"
#include "textureCollection.h"
#include "textureStageCollection.h"
class NodePathCollection;
class FindApproxPath;
@ -1008,9 +1011,6 @@ private:
INLINE ostream &operator << (ostream &out, const NodePath &node_path);
// We have to put this down here, to work around a circular include.
#include "shaderInput.h"
#include "nodePath.I"
#endif

View File

@ -21,6 +21,7 @@
#include "occluderNode.cxx"
#include "pandaNode.cxx"
#include "pandaNodeChain.cxx"
#include "paramNodePath.cxx"
#include "planeNode.cxx"
#include "polylightEffect.cxx"
#include "polylightNode.cxx"

View File

@ -721,13 +721,15 @@ get_user_bounds(int pipeline_stage, Thread *current_thread) const {
////////////////////////////////////////////////////////////////////
INLINE void PandaNode::
mark_bounds_stale(int pipeline_stage, Thread *current_thread) const {
// It's important that we don't hold the lock during the call to
// force_bounds_stale().
// We check whether it is already marked stale. If so, we don't have
// to make the call to force_bounds_stale().
bool is_stale_bounds;
{
CDStageReader cdata(_cycler, pipeline_stage, current_thread);
is_stale_bounds = (cdata->_last_bounds_update != cdata->_next_update);
is_stale_bounds = (cdata->_last_update != cdata->_next_update);
}
// It's important that we don't hold the lock during the call to
// force_bounds_stale().
if (!is_stale_bounds) {
((PandaNode *)this)->force_bounds_stale(pipeline_stage, current_thread);
}
@ -1833,7 +1835,7 @@ get_off_clip_planes() const {
////////////////////////////////////////////////////////////////////
INLINE CPT(BoundingVolume) PandaNodePipelineReader::
get_bounds() const {
nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_external_bounds);
nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_external_bounds);
return _cdata->_external_bounds;
}
@ -1852,7 +1854,7 @@ get_bounds() const {
////////////////////////////////////////////////////////////////////
INLINE int PandaNodePipelineReader::
get_nested_vertices() const {
nassertr(_cdata->_last_update == _cdata->_next_update, _cdata->_nested_vertices);
nassertr(_cdata->_last_bounds_update == _cdata->_next_update, _cdata->_nested_vertices);
return _cdata->_nested_vertices;
}

View File

@ -0,0 +1,60 @@
// Filename: paramNodePath.I
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::Constructor
// Access: Published
// Description: Creates a new ParamNodePath storing the given
// node path object.
////////////////////////////////////////////////////////////////////
INLINE ParamNodePath::
ParamNodePath(const NodePath &node_path) :
_node_path(node_path)
{
}
#ifdef USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::Move Constructor
// Access: Published
// Description: Creates a new ParamNodePath storing the given
// node path object.
////////////////////////////////////////////////////////////////////
INLINE ParamNodePath::
ParamNodePath(NodePath &&node_path) NOEXCEPT :
_node_path(move(node_path))
{
}
#endif // USE_MOVE_SEMANTICS
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::get_value_type
// Access: Published, Virtual
// Description: Returns NodePath::get_class_type().
////////////////////////////////////////////////////////////////////
INLINE TypeHandle ParamNodePath::
get_value_type() const {
return NodePath::get_class_type();
}
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::get_value
// Access: Published
// Description: Retrieves the NodePath stored in the parameter.
////////////////////////////////////////////////////////////////////
INLINE const NodePath &ParamNodePath::
get_value() const {
return _node_path;
}

View File

@ -0,0 +1,108 @@
// Filename: paramNodePath.cxx
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "paramNodePath.h"
#include "dcast.h"
#include "pandaNode.h"
TypeHandle ParamNodePath::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void ParamNodePath::
output(ostream &out) const {
out << "node path " << _node_path;
}
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// ParamValue.
////////////////////////////////////////////////////////////////////
void ParamNodePath::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void ParamNodePath::
write_datagram(BamWriter *manager, Datagram &dg) {
ParamValueBase::write_datagram(manager, dg);
// We can't store a NodePath, so we store a pointer to the
// underlying node, and pray that there is an unambiguous path
// from the root to it.
if (_node_path.is_empty()) {
manager->write_pointer(dg, NULL);
} else {
manager->write_pointer(dg, _node_path.node());
}
}
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int ParamNodePath::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = ParamValueBase::complete_pointers(p_list, manager);
_node_path = NodePath(DCAST(PandaNode, p_list[pi++]));
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type ParamValue is encountered
// in the Bam file. It should create the ParamValue
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *ParamNodePath::
make_from_bam(const FactoryParams &params) {
ParamNodePath *param = new ParamNodePath;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
param->fillin(scan, manager);
return param;
}
////////////////////////////////////////////////////////////////////
// Function: ParamNodePath::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new ParamValue.
////////////////////////////////////////////////////////////////////
void ParamNodePath::
fillin(DatagramIterator &scan, BamReader *manager) {
ParamValueBase::fillin(scan, manager);
manager->read_pointer(scan);
}

View File

@ -0,0 +1,75 @@
// Filename: paramNodePath.h
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef PARAMNODEPATH_H
#define PARAMNODEPATH_H
#include "pandabase.h"
#include "paramValue.h"
#include "nodePath.h"
////////////////////////////////////////////////////////////////////
// Class : ParamNodePath
// Description : A class object for storing a NodePath as a parameter.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_GOBJ ParamNodePath : public ParamValueBase {
protected:
INLINE ParamNodePath() {};
PUBLISHED:
INLINE ParamNodePath(const NodePath &node_path);
#ifdef USE_MOVE_SEMANTICS
INLINE ParamNodePath(NodePath &&node_path) NOEXCEPT;
#endif
INLINE virtual TypeHandle get_value_type() const;
INLINE const NodePath &get_value() const;
virtual void output(ostream &out) const;
private:
NodePath _node_path;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist,
BamReader *manager);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
ParamValueBase::init_type();
register_type(_type_handle, "ParamNodePath",
ParamValueBase::get_class_type());
}
private:
static TypeHandle _type_handle;
};
#include "paramNodePath.I"
#endif

View File

@ -85,11 +85,10 @@ disable(){
// Description: Set this light's position
////////////////////////////////////////////////////////////////////
INLINE void PolylightNode::
set_pos(const LVecBase3 &position){
set_pos(const LPoint3 &position) {
_position = position;
}
////////////////////////////////////////////////////////////////////
// Function: PolylightNode::set_pos
// Access: Published
@ -107,7 +106,7 @@ set_pos(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z){
// Access: Published
// Description: Returns position as a LPoint3
////////////////////////////////////////////////////////////////////
INLINE LVecBase3 PolylightNode::
INLINE LPoint3 PolylightNode::
get_pos() const {
return _position;
}

View File

@ -65,6 +65,30 @@ make_copy() const {
return new PolylightNode(*this);
}
////////////////////////////////////////////////////////////////////
// Function: PolylightNode::xform
// Access: Public, Virtual
// Description: Transforms the contents of this node by the indicated
// matrix, if it means anything to do so. For most
// kinds of nodes, this does nothing.
////////////////////////////////////////////////////////////////////
void PolylightNode::
xform(const LMatrix4 &mat) {
nassertv(!mat.is_nan());
if (mat.almost_equal(LMatrix4::ident_mat())) {
return;
}
_position = _position * mat;
// This is a little cheesy and fails miserably in the presence of a
// non-uniform scale.
LVector3 radius_v = LVector3(_radius, 0.0f, 0.0f) * mat;
_radius = length(radius_v);
mark_internal_bounds_stale();
}
////////////////////////////////////////////////////////////////////
// Function: PolylightNode::Constructor
// Access: Public

View File

@ -58,9 +58,9 @@ PUBLISHED:
PolylightNode(const string &name);
INLINE void enable();
INLINE void disable();
INLINE void set_pos(const LVecBase3 &position);
INLINE void set_pos(const LPoint3 &position);
INLINE void set_pos(PN_stdfloat x,PN_stdfloat y, PN_stdfloat z);
INLINE LVecBase3 get_pos() const;
INLINE LPoint3 get_pos() const;
INLINE void set_color(const LColor &color);
INLINE void set_color(PN_stdfloat r, PN_stdfloat g, PN_stdfloat b);
INLINE LColor get_color() const;
@ -100,11 +100,11 @@ PUBLISHED:
public:
LColor flicker() const;
virtual PandaNode *make_copy() const;
virtual void xform(const LMatrix4 &mat);
private:
bool _enabled;
LVecBase3 _position;
LPoint3 _position;
LColor _color;
PN_stdfloat _radius;
Attenuation_Type _attenuation_type;

View File

@ -119,23 +119,6 @@ ShaderInput(CPT_InternalName name, ParamValueBase *param, int priority) :
{
}
////////////////////////////////////////////////////////////////////
// Function: ShaderInput::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE ShaderInput::
ShaderInput(CPT_InternalName name, const NodePath &np, int priority) :
_name(MOVE(name)),
_type(M_nodepath),
_priority(priority),
_stored_nodepath(np),
_bind_layer(0),
_bind_level(0),
_access(A_read)
{
}
////////////////////////////////////////////////////////////////////
// Function: ShaderInput::Constructor
// Access: Published
@ -678,16 +661,6 @@ get_texture() const {
return DCAST(Texture, _value);
}
////////////////////////////////////////////////////////////////////
// Function: ShaderInput::get_nodepath
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE const NodePath &ShaderInput::
get_nodepath() const {
return _stored_nodepath;
}
////////////////////////////////////////////////////////////////////
// Function: ShaderInput::get_vector
// Access: Published

View File

@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////
#include "shaderInput.h"
#include "paramNodePath.h"
TypeHandle ShaderInput::_type_handle;
@ -32,13 +33,40 @@ get_blank() {
return blank;
}
////////////////////////////////////////////////////////////////////
// Function: ShaderInput::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
ShaderInput::
ShaderInput(CPT_InternalName name, const NodePath &np, int priority) :
_name(MOVE(name)),
_type(M_nodepath),
_priority(priority),
_value(new ParamNodePath(np)),
_bind_layer(0),
_bind_level(0),
_access(A_read)
{
}
////////////////////////////////////////////////////////////////////
// Function: ShaderInput::get_nodepath
// Access: Published
// Description: Warning: no error checking is done. This *will*
// crash if get_value_type() is not M_nodepath.
////////////////////////////////////////////////////////////////////
const NodePath &ShaderInput::
get_nodepath() const {
return DCAST(ParamNodePath, _value)->get_value();
}
////////////////////////////////////////////////////////////////////
// Function: ShaderInput::register_with_read_factory
// Access: Public, Static
// Description:
// Description:
////////////////////////////////////////////////////////////////////
void ShaderInput::
register_with_read_factory() {
// IMPLEMENT ME
}

View File

@ -19,7 +19,6 @@
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "nodePath.h"
#include "internalName.h"
#include "paramValue.h"
#include "pta_float.h"
@ -53,7 +52,6 @@ PUBLISHED:
static const ShaderInput *get_blank();
INLINE ShaderInput(CPT_InternalName name, int priority=0);
INLINE ShaderInput(CPT_InternalName name, const NodePath &np, int priority=0);
INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0);
INLINE ShaderInput(CPT_InternalName name, Texture *tex, const SamplerState &sampler, int priority=0);
INLINE ShaderInput(CPT_InternalName name, Texture *tex, bool read, bool write, int z=-1, int n=0, int priority=0);
@ -90,6 +88,8 @@ PUBLISHED:
INLINE ShaderInput(CPT_InternalName name, const LVecBase3i &vec, int priority=0);
INLINE ShaderInput(CPT_InternalName name, const LVecBase2i &vec, int priority=0);
ShaderInput(CPT_InternalName name, const NodePath &np, int priority=0);
enum ShaderInputType {
M_invalid = 0,
M_texture,
@ -105,11 +105,12 @@ PUBLISHED:
INLINE int get_value_type() const;
INLINE int get_priority() const;
INLINE Texture *get_texture() const;
INLINE const NodePath &get_nodepath() const;
INLINE const LVecBase4 &get_vector() const;
INLINE const Shader::ShaderPtrData &get_ptr() const;
INLINE const SamplerState &get_sampler() const;
const NodePath &get_nodepath() const;
public:
INLINE ParamValueBase *get_param() const;
@ -118,7 +119,6 @@ public:
private:
SamplerState _sampler;
LVecBase4 _stored_vector;
NodePath _stored_nodepath;
Shader::ShaderPtrData _stored_ptr;
CPT_InternalName _name;
PT(TypedWritableReferenceCount) _value;

View File

@ -18,6 +18,7 @@
#include "virtualFileSystem.h"
#include "loader.h"
#include "shader.h"
#include "string_utils.h"
ShaderPool *ShaderPool::_global_ptr = (ShaderPool *)NULL;

View File

@ -0,0 +1,175 @@
// Filename: convert_srgb.I
// Created by: rdb (29Oct14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: decode_sRGB_float
// Description: Decodes the sRGB-encoded unsigned char value to
// a linearized float in the range 0-1.
////////////////////////////////////////////////////////////////////
CONSTEXPR float decode_sRGB_float(unsigned char val) {
return to_linear_float_table[val];
}
////////////////////////////////////////////////////////////////////
// Function: encode_sRGB_float
// Description: Decodes the sRGB-encoded floating-point value in
// the range 0-1 to a linearized float in the range
// 0-1. Inputs outside this range produce invalid
// results.
////////////////////////////////////////////////////////////////////
INLINE float decode_sRGB_float(float val) {
return (val <= 0.04045f)
? (val * (1.f / 12.92f))
: cpow((val + 0.055f) * (1.f / 1.055f), 2.4f);
}
////////////////////////////////////////////////////////////////////
// Function: decode_sRGB_uchar
// Description: Decodes the sRGB-encoded unsigned char value to
// a linearized unsigned char value.
////////////////////////////////////////////////////////////////////
CONSTEXPR unsigned char decode_sRGB_uchar(unsigned char val) {
return to_linear_uchar_table[val];
}
////////////////////////////////////////////////////////////////////
// Function: decode_sRGB_uchar
// Description: Decodes the sRGB-encoded floating-point value in
// the range 0-1 to a linearized unsigned char value.
// Inputs outside this range are clamped.
////////////////////////////////////////////////////////////////////
INLINE unsigned char decode_sRGB_uchar(float val) {
return (val <= 0.04045f)
? (unsigned char)(max(0.f, val) * (255.f / 12.92f) + 0.5f)
: (unsigned char)(cpow((min(val, 1.f) + 0.055f) * (1.f / 1.055f), 2.4f) * 255.f + 0.5f);
}
////////////////////////////////////////////////////////////////////
// Function: encode_sRGB_float
// Description: Encodes the linearized unsigned char value to an
// sRGB-encoded floating-point value in ther range 0-1.
////////////////////////////////////////////////////////////////////
INLINE float
encode_sRGB_float(unsigned char val) {
// This seems like a very unlikely use case, so I didn't bother
// making a look-up table for this.
return (val == 0) ? 0
: (1.055f * cpow((float)val * (1.f / 255.f), 0.41666f) - 0.055);
}
////////////////////////////////////////////////////////////////////
// Function: encode_sRGB_float
// Description: Encodes the linearized floating-point value in the
// range 0-1 to an sRGB-encoded float in the range
// 0-1. Inputs outside this range produce invalid
// results.
////////////////////////////////////////////////////////////////////
INLINE float
encode_sRGB_float(float val) {
return (val < 0.0031308f)
? (val * 12.92f)
: (1.055f * cpow(val, 0.41666f) - 0.055);
}
////////////////////////////////////////////////////////////////////
// Function: encode_sRGB_uchar
// Description: Encodes the linearized unsigned char value to an
// sRGB-encoded unsigned char value.
////////////////////////////////////////////////////////////////////
CONSTEXPR unsigned char
encode_sRGB_uchar(unsigned char val) {
return to_srgb8_table[val];
}
////////////////////////////////////////////////////////////////////
// Function: encode_sRGB_uchar
// Description: Encodes the linearized floating-point value in the
// range 0-1 to an sRGB-encoded unsigned char value.
// Inputs outside this range are clamped.
//
// When SSE2 support is known at compile time, this
// automatically uses an optimized version. Otherwise,
// it does not attempt runtime CPU detection. If you
// know that SSE2 is supported (ie. if the function
// has_sse2_sRGB_encode() returns true) you should
// call encode_sRGB_uchar_sse2 instead.
////////////////////////////////////////////////////////////////////
INLINE unsigned char
encode_sRGB_uchar(float val) {
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
// Use a highly optimized approximation that has more than enough
// accuracy for an unsigned char.
return encode_sRGB_uchar_sse2(val);
#else
return (val < 0.0031308f)
? (unsigned char) (max(0.f, val) * 3294.6f + 0.5f)
: (unsigned char) (269.025f * cpow(min(val, 1.f), 0.41666f) - 13.525f);
#endif
}
////////////////////////////////////////////////////////////////////
// Function: encode_sRGB_uchar
// Description: Encodes the linearized floating-point color value
// an sRGB-encoded xel in the range 0-255.
//
// When SSE2 support is known at compile time, this
// automatically uses an optimized version. Otherwise,
// it does not attempt runtime CPU detection. If you
// know that SSE2 is supported (ie. if the function
// has_sse2_sRGB_encode() returns true) you should
// call encode_sRGB_uchar_sse2 instead.
////////////////////////////////////////////////////////////////////
INLINE void
encode_sRGB_uchar(const LColorf &color, xel &into) {
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
// SSE2 support compiled-in; we're guaranteed to have it.
encode_sRGB_uchar_sse2(color, into);
#else
// Boring, slow, non-SSE2 version.
PPM_ASSIGN(into,
encode_sRGB_uchar(color[0]),
encode_sRGB_uchar(color[1]),
encode_sRGB_uchar(color[2]));
#endif
}
////////////////////////////////////////////////////////////////////
// Function: encode_sRGB_uchar
// Description: Encodes the linearized floating-point color value
// an sRGB-encoded xel and alpha in the range 0-255.
// The alpha value is not sRGB-encoded.
//
// When SSE2 support is known at compile time, this
// automatically uses an optimized version. Otherwise,
// it does not attempt runtime CPU detection. If you
// know that SSE2 is supported (ie. if the function
// has_sse2_sRGB_encode() returns true) you should
// call encode_sRGB_uchar_sse2 instead.
////////////////////////////////////////////////////////////////////
INLINE void
encode_sRGB_uchar(const LColorf &color, xel &into, xelval &into_alpha) {
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
// SSE2 support compiled-in; we're guaranteed to have it.
encode_sRGB_uchar_sse2(color, into, into_alpha);
#else
// Boring, slow, non-SSE2 version.
PPM_ASSIGN(into,
encode_sRGB_uchar(color[0]),
encode_sRGB_uchar(color[1]),
encode_sRGB_uchar(color[2]));
into_alpha = (xelval) (color[3] * 255.f + 0.5f);
#endif
}

View File

@ -0,0 +1,165 @@
// Filename: convert_srgb.cxx
// Created by: rdb (13Nov14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#include "convert_srgb.h"
#ifdef __GNUC__
#include <cpuid.h>
#endif
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#endif
// Lookup tables for converting from unsigned char formats.
ALIGN_64BYTE const
unsigned char to_srgb8_table[256] = { 0x00, 0x0d, 0x16, 0x1c, 0x22, 0x26, 0x2a,
0x2e, 0x32, 0x35, 0x38, 0x3b, 0x3d, 0x40, 0x42, 0x45, 0x47, 0x49, 0x4b, 0x4d,
0x4f, 0x51, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5d, 0x5f, 0x60, 0x62, 0x63,
0x65, 0x66, 0x68, 0x69, 0x6a, 0x6c, 0x6d, 0x6e, 0x70, 0x71, 0x72, 0x73, 0x75,
0x76, 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90,
0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b,
0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6,
0xa7, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xaf, 0xaf,
0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb8, 0xb9,
0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1,
0xc2, 0xc2, 0xc3, 0xc4, 0xc4, 0xc5, 0xc5, 0xc6, 0xc7, 0xc7, 0xc8, 0xc8, 0xc9,
0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf, 0xd0, 0xd0, 0xd1,
0xd1, 0xd2, 0xd2, 0xd3, 0xd4, 0xd4, 0xd5, 0xd5, 0xd6, 0xd6, 0xd7, 0xd7, 0xd8,
0xd8, 0xd9, 0xda, 0xda, 0xdb, 0xdb, 0xdc, 0xdc, 0xdd, 0xdd, 0xde, 0xde, 0xdf,
0xdf, 0xe0, 0xe0, 0xe1, 0xe2, 0xe2, 0xe3, 0xe3, 0xe4, 0xe4, 0xe5, 0xe5, 0xe6,
0xe6, 0xe7, 0xe7, 0xe8, 0xe8, 0xe9, 0xe9, 0xea, 0xea, 0xeb, 0xeb, 0xec, 0xec,
0xed, 0xed, 0xee, 0xee, 0xee, 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2,
0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8,
0xf9, 0xf9, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe,
0xff, 0xff};
ALIGN_64BYTE const
unsigned char to_linear_uchar_table[256] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04,
0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07,
0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b,
0x0b, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x10,
0x11, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e,
0x1f, 0x20, 0x20, 0x21, 0x22, 0x23, 0x23, 0x24, 0x25, 0x25, 0x26, 0x27, 0x28,
0x29, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4c, 0x4d,
0x4e, 0x4f, 0x50, 0x51, 0x52, 0x54, 0x55, 0x56, 0x57, 0x58, 0x5a, 0x5b, 0x5c,
0x5d, 0x5f, 0x60, 0x61, 0x63, 0x64, 0x65, 0x67, 0x68, 0x69, 0x6b, 0x6c, 0x6d,
0x6f, 0x70, 0x72, 0x73, 0x74, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f, 0x80,
0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x92, 0x93, 0x95,
0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9f, 0xa1, 0xa3, 0xa4, 0xa6, 0xa8, 0xaa, 0xab,
0xad, 0xaf, 0xb1, 0xb3, 0xb5, 0xb7, 0xb8, 0xba, 0xbc, 0xbe, 0xc0, 0xc2, 0xc4,
0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0xe0, 0xe2, 0xe5, 0xe7, 0xe9, 0xeb, 0xed, 0xef, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa,
0xfd, 0xff};
ALIGN_64BYTE
const float to_linear_float_table[256] = { 0, 0.000304f, 0.000607f, 0.000911f,
0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f,
0.006049f, 0.006512f, 0.006995f, 0.007499f, 0.008023f, 0.008568f, 0.009134f,
0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f,
0.014444f, 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f,
0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, 0.025187f, 0.026241f,
0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f,
0.035601f, 0.036889f, 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f,
0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, 0.054480f,
0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f,
0.068478f, 0.070360f, 0.072272f, 0.074214f, 0.076185f, 0.078187f, 0.080220f,
0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f,
0.114435f, 0.116971f, 0.119538f, 0.122139f, 0.124772f, 0.127438f, 0.130136f,
0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f,
0.152926f, 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f,
0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, 0.191202f, 0.194618f,
0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f,
0.223228f, 0.226966f, 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f,
0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, 0.274677f,
0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f,
0.309469f, 0.313989f, 0.318547f, 0.323143f, 0.327778f, 0.332452f, 0.337164f,
0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
0.376262f, 0.381326f, 0.386429f, 0.391572f, 0.396755f, 0.401978f, 0.407240f,
0.412543f, 0.417885f, 0.423268f, 0.428690f, 0.434154f, 0.439657f, 0.445201f,
0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473531f, 0.479320f, 0.485150f,
0.491021f, 0.496933f, 0.502886f, 0.508881f, 0.514918f, 0.520996f, 0.527115f,
0.533276f, 0.539479f, 0.545724f, 0.552011f, 0.558340f, 0.564712f, 0.571125f,
0.577580f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f,
0.623960f, 0.630757f, 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f,
0.672443f, 0.679542f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, 0.715694f,
0.723055f, 0.730461f, 0.737910f, 0.745404f, 0.752942f, 0.760525f, 0.768151f,
0.775822f, 0.783538f, 0.791298f, 0.799103f, 0.806952f, 0.814847f, 0.822786f,
0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f,
0.947307f, 0.955973f, 0.964686f, 0.973445f, 0.982251f, 0.991102f, 1.000000f};
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
// SSE2 support enabled at compile time. No runtime detection mechanism needed.
bool
has_sse2_sRGB_encode() {
return true;
}
#else
// SSE2 support not guaranteed. Use a runtime detection mechanism.
bool
has_sse2_sRGB_encode() {
#if defined(__GNUC__)
unsigned int a, b, c, d;
static const bool has_support =
(__get_cpuid(1, &a, &b, &c, &d) == 1 && (d & 0x04000000) != 0);
#elif defined(_WIN32)
static const bool has_support =
(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE) != FALSE);
#else
static const bool has_support = false;
#endif
if (pnmimage_cat.is_debug()) {
static bool checked = false;
if (!checked) {
#if defined(__GNUC__) || defined(_WIN32)
if (has_support) {
pnmimage_cat.debug()
<< "Runtime detection reports SSE2 instructions available: "
<< "SSE2-optimized sRGB encoding routines enabled.\n";
} else {
pnmimage_cat.debug()
<< "Runtime detection reports SSE2 instructions unavailable: "
<< "SSE2-optimized sRGB encoding routines disabled.\n";
}
#else
pnmimage_cat.debug()
<< "No runtime detection mechanism for SSE2 instructions available: "
<< "SSE2-optimized sRGB encoding routines disabled.\n";
#endif
checked = true;
}
}
return has_support;
}
#endif // __SSE2__

View File

@ -0,0 +1,59 @@
// Filename: convert_srgb.h
// Created by: rdb (13Nov14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef CONVERT_SRGB_H
#define CONVERT_SRGB_H
#include "pandabase.h"
#include "luse.h"
#include "pnmimage_base.h"
// The below functions can encode and decode sRGB colors in various
// representations. Some of them are implemented using look-up tables,
// some others using SSE2 intrinsics.
extern EXPCL_PANDA_PNMIMAGE const unsigned char to_srgb8_table[256];
extern EXPCL_PANDA_PNMIMAGE const unsigned char to_linear_uchar_table[256];
extern EXPCL_PANDA_PNMIMAGE const float to_linear_float_table[256];
EXPCL_PANDA_PNMIMAGE CONSTEXPR float decode_sRGB_float(unsigned char val);
EXPCL_PANDA_PNMIMAGE INLINE float decode_sRGB_float(float val);
EXPCL_PANDA_PNMIMAGE CONSTEXPR unsigned char decode_sRGB_uchar(unsigned char val);
EXPCL_PANDA_PNMIMAGE INLINE unsigned char decode_sRGB_uchar(float val);
EXPCL_PANDA_PNMIMAGE INLINE float encode_sRGB_float(unsigned char val);
EXPCL_PANDA_PNMIMAGE INLINE float encode_sRGB_float(float val);
EXPCL_PANDA_PNMIMAGE CONSTEXPR unsigned char encode_sRGB_uchar(unsigned char val);
EXPCL_PANDA_PNMIMAGE INLINE unsigned char encode_sRGB_uchar(float val);
// These functions convert more than one component in one go,
// which can be faster due to vectorization.
EXPCL_PANDA_PNMIMAGE INLINE void encode_sRGB_uchar(const LColorf &from,
xel &into);
EXPCL_PANDA_PNMIMAGE INLINE void encode_sRGB_uchar(const LColorf &from,
xel &into, xelval &into_alpha);
// Use these functions if you know that SSE2 support is available.
// Otherwise, they will crash!
EXPCL_PANDA_PNMIMAGE unsigned char encode_sRGB_uchar_sse2(float val);
EXPCL_PANDA_PNMIMAGE void encode_sRGB_uchar_sse2(const LColorf &from,
xel &into);
EXPCL_PANDA_PNMIMAGE void encode_sRGB_uchar_sse2(const LColorf &from,
xel &into, xelval &into_alpha);
// Use the following to find out if you can call either of the above.
EXPCL_PANDA_PNMIMAGE bool has_sse2_sRGB_encode();
#include "convert_srgb.I"
#endif

View File

@ -0,0 +1,151 @@
// Filename: convert_srgb_sse2.cxx
// Created by: rdb (13Nov14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
// This file should always be compiled with SSE2 support. These
// functions will only be called when SSE2 support is detected at
// run-time.
#include "convert_srgb.h"
#include "luse.h"
#if defined(__SSE2__) || (_M_IX86_FP >= 2) || defined(_M_X64) || defined(_M_AMD64)
#include <xmmintrin.h>
#include <emmintrin.h>
static INLINE __m128i _encode_sRGB_sse2_mul255(__m128 val) {
// This an SSE2-based approximation of the sRGB encode function.
// It has a maximum error of around 0.001, which is by far small
// enough for a uchar. It is also at least 10x as fast as the
// original; up to 40x when taking advantage of vectorization.
// Note that the fourth float is only multiplied with 255.
// Part of the code in this function is derived from:
// http://stackoverflow.com/a/6486630/2135754
// Clamp to 0-1 range.
val = _mm_max_ps(val, _mm_set1_ps(0.0f));
val = _mm_min_ps(val, _mm_set1_ps(1.0f));
// Pre-multiply with constant factor to adjust for exp bias.
__m128 xf = _mm_mul_ps(val, _mm_set1_ps(6.3307e18f));
// Approximate logarithm by... casting!
xf = _mm_cvtepi32_ps(_mm_castps_si128(xf));
// Multiply 'logarithm' by power.
xf = _mm_mul_ps(xf, _mm_set1_ps(2.0f / 3.0f));
// Reverse operation of above: cast the other way.
xf = _mm_castsi128_ps(_mm_cvtps_epi32(xf));
// Make an overestimate and an underestimate.
__m128 xover = _mm_mul_ps(val, xf);
__m128 xunder = _mm_mul_ps(_mm_mul_ps(val, val),
_mm_rsqrt_ps(xf));
// Average the two factors, with a slight bias.
__m128 xavg = _mm_mul_ps(_mm_add_ps(xover, xunder),
_mm_set1_ps(0.5286098f));
// Take square root twice. Note that this is faster than
// the more expensive _mm_sqrt_ps instruction.
xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg));
xavg = _mm_mul_ps(xavg, _mm_rsqrt_ps(xavg));
// Bring it into the correct range. These factors are determined
// not on the basis of accuracy, but are chosen such that the
// decoder lookup table produces an equivalent result for any value.
xavg = _mm_mul_ps(xavg, _mm_set1_ps(269.122f));
xavg = _mm_sub_ps(xavg, _mm_set1_ps(13.55f));
// Compute the linear section. This is also the path that
// the alpha channel takes, so we set the alpha multiplier
// to 255 (since alpha is not sRGB-converted).
__m128 lval = _mm_mul_ps(val,
_mm_set_ps(255.0f, 3294.6f, 3294.6f, 3294.6f));
lval = _mm_add_ps(lval, _mm_set1_ps(0.5f));
// Decide which version to return. Rig the alpha
// comparator to always fail so that the linear path
// is always chosen for alpha.
__m128 mask = _mm_cmpge_ps(val,
_mm_set_ps(2.0f, 0.0031308f, 0.0031308f, 0.0031308f));
// This is a non-branching way to return one or the other value.
return _mm_cvttps_epi32(_mm_or_ps(
_mm_and_ps(mask, xavg),
_mm_andnot_ps(mask, lval)));
}
unsigned char
encode_sRGB_uchar_sse2(float val) {
// Running only a single component through this function is still
// way faster than the equivalent non-SSE2 version.
return (unsigned char)
_mm_extract_epi16(_encode_sRGB_sse2_mul255(_mm_set1_ps(val)), 0);
}
void
encode_sRGB_uchar_sse2(const LColorf &color, xel &into) {
#ifdef LINMATH_ALIGN
__m128 vec = _mm_load_ps(color.get_data());
#else
__m128 vec = _mm_loadu_ps(color.get_data());
#endif
__m128i vals = _encode_sRGB_sse2_mul255(vec);
into.r = _mm_extract_epi16(vals, 0);
into.g = _mm_extract_epi16(vals, 2);
into.b = _mm_extract_epi16(vals, 4);
}
void
encode_sRGB_uchar_sse2(const LColorf &color, xel &into, xelval &into_alpha) {
#ifdef LINMATH_ALIGN
__m128 vec = _mm_load_ps(color.get_data());
#else
__m128 vec = _mm_loadu_ps(color.get_data());
#endif
__m128i vals = _encode_sRGB_sse2_mul255(vec);
into.r = _mm_extract_epi16(vals, 0);
into.g = _mm_extract_epi16(vals, 2);
into.b = _mm_extract_epi16(vals, 4);
into_alpha = _mm_extract_epi16(vals, 6);
}
#else
// Somehow we're still compiling this without SSE2 support. We'll
// still have to define these functions, but emit a warning that the
// build system isn't configured properly.
#warning convert_srgb_sse2.cxx is being compiled without SSE2 support!
unsigned char
encode_sRGB_uchar_sse2(float val) {
return encode_sRGB_uchar(val);
}
void
encode_sRGB_uchar_sse2(const LColorf &color, xel &into) {
encode_sRGB_uchar(color, into);
}
void
encode_sRGB_uchar_sse2(const LColorf &color, xel &into, xelval &into_alpha) {
encode_sRGB_uchar(color, into, into_alpha);
}
#endif

View File

@ -1,4 +1,5 @@
#include "config_pnmimage.cxx"
#include "convert_srgb.cxx"
#include "pfmFile.cxx"
#include "pnm-image-filter.cxx"
#include "pnmbitio.cxx"

View File

@ -27,6 +27,7 @@
cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \
callbackData.h callbackData.I \
callbackObject.h callbackObject.I \
callbackObject_ext.h callbackObject_ext.I \
clockObject.h clockObject.I \
collideMask.h \
copyOnWriteObject.h copyOnWriteObject.I \
@ -139,6 +140,7 @@
cachedTypedWritableReferenceCount.h cachedTypedWritableReferenceCount.I \
callbackData.h callbackData.I \
callbackObject.h callbackObject.I \
callbackObject_ext.h callbackObject_ext.I \
clockObject.h clockObject.I \
collideMask.h \
copyOnWriteObject.h copyOnWriteObject.I \

View File

@ -43,7 +43,7 @@ BamCache() :
_index_stale_since(0)
{
ConfigVariableFilename model_cache_dir
("model-cache-dir", Filename(),
("model-cache-dir", Filename(),
PRC_DESC("The full path to a directory, local to this computer, in which "
"model and texture files will be cached on load. If a directory "
"name is specified here, files may be loaded from the cache "
@ -51,7 +51,7 @@ BamCache() :
"especially if you are loading egg files instead of bam files, "
"or if you are loading models from a shared network drive. "
"If this is the empty string, no cache will be used."));
ConfigVariableInt model_cache_flush
("model-cache-flush", 30,
PRC_DESC("This is the amount of time, in seconds, between automatic "
@ -138,7 +138,7 @@ set_root(const Filename &root) {
////////////////////////////////////////////////////////////////////
// Function: BamCache::lookup
// Access: Published
// Description: Looks up a file in the cache.
// Description: Looks up a file in the cache.
//
// If the file is cacheable, then regardless of whether
// the file is found in the cache or not, this returns a
@ -163,7 +163,7 @@ lookup(const Filename &source_filename, const string &cache_extension) {
consider_flush_index();
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
Filename source_pathname(source_filename);
source_pathname.make_absolute(vfs->get_cwd());
@ -200,7 +200,7 @@ store(BamCacheRecord *record) {
if (_read_only) {
return false;
}
consider_flush_index();
#ifndef NDEBUG
@ -231,7 +231,7 @@ store(BamCacheRecord *record) {
emergency_read_only();
return false;
}
if (!dout.write_header(_bam_header)) {
util_cat.error()
<< "Unable to write to " << temp_pathname << "\n";
@ -247,7 +247,7 @@ store(BamCacheRecord *record) {
vfs->delete_file(temp_pathname);
return false;
}
TypeRegistry *type_registry = TypeRegistry::ptr();
TypeHandle texture_type = type_registry->find_type("Texture");
if (record->get_data()->is_of_type(texture_type)) {
@ -257,14 +257,14 @@ store(BamCacheRecord *record) {
// Any other kinds of objects write texture references.
writer.set_file_texture_mode(BamWriter::BTM_fullpath);
}
if (!writer.write_object(record)) {
util_cat.error()
<< "Unable to write object to " << temp_pathname << "\n";
vfs->delete_file(temp_pathname);
return false;
}
if (!writer.write_object(record->get_data())) {
util_cat.error()
<< "Unable to write object data to " << temp_pathname << "\n";
@ -354,7 +354,7 @@ flush_index() {
emergency_read_only();
return;
}
// Now atomically write the name of this index file to the index
// reference file.
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
@ -385,6 +385,16 @@ flush_index() {
check_cache_size();
}
////////////////////////////////////////////////////////////////////
// Function: BamCache::list_index
// Access: Published
// Description: Writes the contents of the index to standard output.
////////////////////////////////////////////////////////////////////
void BamCache::
list_index(ostream &out, int indent_level) const {
_index->write(out, indent_level);
}
////////////////////////////////////////////////////////////////////
// Function: BamCache::read_index
// Access: Private

View File

@ -73,13 +73,15 @@ PUBLISHED:
INLINE void set_read_only(bool ro);
INLINE bool get_read_only() const;
PT(BamCacheRecord) lookup(const Filename &source_filename,
PT(BamCacheRecord) lookup(const Filename &source_filename,
const string &cache_extension);
bool store(BamCacheRecord *record);
void consider_flush_index();
void flush_index();
void list_index(ostream &out, int indent_level = 0) const;
INLINE static BamCache *get_global_ptr();
private:
@ -96,7 +98,7 @@ private:
void check_cache_size();
void emergency_read_only();
static BamCacheIndex *do_read_index(const Filename &index_pathname);
static bool do_write_index(const Filename &index_pathname, const BamCacheIndex *index);
@ -105,7 +107,7 @@ private:
PT(BamCacheRecord) read_record(const Filename &source_pathname,
const Filename &cache_filename,
int pass);
static PT(BamCacheRecord) do_read_record(const Filename &cache_pathname,
static PT(BamCacheRecord) do_read_record(const Filename &cache_pathname,
bool read_data);
static string hash_filename(const string &filename);

View File

@ -38,6 +38,8 @@ public:
PUBLISHED:
virtual void output(ostream &out) const;
EXTENSION(static PT(CallbackObject) make(PyObject *function));
public:
virtual void do_callback(CallbackData *cbdata);

View File

@ -0,0 +1,32 @@
// Filename: callbackObject_ext.I
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: Extension<CallbackObject>::make
// Access: Published
// Description: This static constructor is merely provided so that
// interrogate can automatically coerce Python
// functions when passing them to a C++ function that
// accepts a CallbackObject.
////////////////////////////////////////////////////////////////////
INLINE PT(CallbackObject) Extension<CallbackObject>::
make(PyObject *function) {
if (function != Py_None && !PyCallable_Check(function)) {
PyErr_SetString(PyExc_TypeError, "expected callable or None");
return NULL;
} else {
return new PythonCallbackObject(function);
}
}

View File

@ -0,0 +1,47 @@
// Filename: callbackObject_ext.h
// Created by: rdb (25Feb15)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University. All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license. You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////
#ifndef CALLBACKOBJECT_EXT_H
#define CALLBACKOBJECT_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "pythonCallbackObject.h"
#include "py_panda.h"
////////////////////////////////////////////////////////////////////
// Class : Extension<CallbackObject>
// Description : This class defines the extension methods for
// CallbackObject, which are called instead of
// any C++ methods with the same prototype.
//
// This just defines a static constructor, which makes
// it possible for Interrogate to automatically accept
// a Python function wherever a CallbackObject is
// accepted.
////////////////////////////////////////////////////////////////////
template<>
class Extension<CallbackObject> : public ExtensionBase<CallbackObject> {
public:
INLINE static PT(CallbackObject) make(PyObject *function);
};
#include "callbackObject_ext.I"
#endif // HAVE_PYTHON
#endif // CALLBACKOBJECT_EXT_H

View File

@ -75,7 +75,7 @@ typedef unsigned int ZPOINT;
((((unsigned int)(a) << 24) & 0xff000000) | (((unsigned int)(r) << 16) & 0xff0000) | (((unsigned int)(g) << 8) & 0xff00) | (unsigned int)(b))
#define SRGB_TO_PIXEL(r,g,b) \
((encode_sRGB[(unsigned int)(r) >> 4] << 16) | (encode_sRGB10[(unsigned int)(g) >> 4] << 8) | (encode_sRGB[(unsigned int)(b) >> 4]))
((encode_sRGB[(unsigned int)(r) >> 4] << 16) | (encode_sRGB[(unsigned int)(g) >> 4] << 8) | (encode_sRGB[(unsigned int)(b) >> 4]))
#define SRGBA_TO_PIXEL(r,g,b,a) \
((((unsigned int)(a) << 16) & 0xff000000) | (encode_sRGB[(unsigned int)(r) >> 4] << 16) | (encode_sRGB[(unsigned int)(g) >> 4] << 8) | (encode_sRGB[(unsigned int)(b) >> 4]))

View File

@ -17,88 +17,316 @@
#include "fcollada_utils.h"
#include "pt_EggVertex.h"
#include "eggXfmSAnim.h"
#include "daeToEggConverter.h"
#include "daeMaterials.h"
#include "eggExternalReference.h"
#include "FCDocument/FCDocument.h"
#include "FCDocument/FCDController.h"
#include "FCDocument/FCDGeometry.h"
#include "FCDocument/FCDSceneNodeTools.h"
#include "FCDocument/FCDSceneNode.h"
#include "FCDocument/FCDTransform.h"
#include "FCDocument/FCDAnimated.h"
#include "FCDocument/FCDAnimationCurve.h"
#include "FCDocument/FCDAnimationKey.h"
TypeHandle DaeCharacter::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: DaeCharacter::Constructor
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
DaeCharacter::
DaeCharacter(const string name, const FCDControllerInstance* controller_instance) {
_controller_instance = (FCDControllerInstance*) controller_instance;
_name = name;
_frame_rate = 0;
_skin_controller = NULL;
DaeCharacter(EggGroup *node_group, const FCDControllerInstance *instance) :
_node_group(node_group),
_name(node_group->get_name()),
_instance(instance),
_skin_controller(NULL),
_skin_mesh(NULL) {
_bind_shape_mat = LMatrix4d::ident_mat();
// If it's a skin controller, add the controller joints.
FCDController* controller = (FCDController*) controller_instance->GetEntity();
if (controller == NULL) return;
const FCDController *controller = (const FCDController *)instance->GetEntity();
if (controller == NULL) {
return;
}
_skin_mesh = controller->GetBaseGeometry()->GetMesh();
if (controller->IsSkin()) {
_skin_controller = controller->GetSkinController();
if (_skin_controller == NULL) return;
for (size_t j = 0; j < _skin_controller->GetJointCount(); ++j) {
_controller_joints[FROM_FSTRING(_skin_controller->GetJoint(j)->GetId())] = (FCDSkinControllerJoint*) _skin_controller->GetJoint(j);
_bind_shape_mat = DAEToEggConverter::convert_matrix(_skin_controller->GetBindShapeTransform());
}
}
////////////////////////////////////////////////////////////////////
// Function: DaeCharacter::bind_joints
// Access: Public
// Description: Binds the joints to the character. This means
// changing them to the bind pose. It is necessary
// to call this before process_skin_geometry.
//
// Returns the root group.
////////////////////////////////////////////////////////////////////
void DaeCharacter::
bind_joints(JointMap &joint_map) {
_joints.clear();
size_t num_joints = _skin_controller->GetJointCount();
_joints.reserve(num_joints);
// Record the bind pose for each joint.
for (size_t j = 0; j < num_joints; ++j) {
const FCDSkinControllerJoint *skin_joint = _skin_controller->GetJoint(j);
string sid = FROM_FSTRING(skin_joint->GetId());
LMatrix4d bind_pose;
bind_pose.invert_from(DAEToEggConverter::convert_matrix(
skin_joint->GetBindPoseInverse()));
// Check that we already encountered this joint during traversal.
JointMap::iterator ji = joint_map.find(sid);
if (ji != joint_map.end()) {
Joint &joint = ji->second;
if (joint._character != (DaeCharacter *)NULL) {
// In some cases, though, multiple controllers share the same joints.
// We can't support this without duplicating the joint structure,
// so we check if the bind poses are the same.
if (!joint._bind_pose.almost_equal(bind_pose, 0.0001)) {
// Ugh. What else could we do?
daeegg_cat.error()
<< "Multiple controllers share joint with sid " << sid
<< ", with different bind poses.\n";
}
} else {
// Mark the joint as being controlled by this character.
joint._bind_pose = bind_pose;
joint._character = this;
}
_joints.push_back(joint);
} else {
daeegg_cat.warning()
<< "Unknown joint sid being referenced: '" << sid << "'\n";
// We still have to add a dummy joint or the index will be off.
_joints.push_back(Joint(NULL, NULL));
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DaeCharacter::as_egg_bundle
// Function: DaeCharacter::adjust_joints
// Access: Public
// Description: Returns the character as a <Bundle> element,
// suited for the animation table.
// Description: Traverses through the character hierarchy in order
// to bind the mesh to the character. This involves
// reorienting the joints to match the bind pose.
//
// It is important that this is called only once.
////////////////////////////////////////////////////////////////////
PT(EggTable) DaeCharacter::
as_egg_bundle() {
PT(EggTable) bundle = new EggTable(_name);
bundle->set_table_type(EggTable::TT_bundle);
PT(EggTable) skeleton = new EggTable("<skeleton>");
skeleton->set_table_type(EggTable::TT_table);
bundle->add_child(skeleton);
// Loop through the joint hierarchy
#if FCOLLADA_VERSION < 0x00030005
FCDSceneNodeList roots = _controller_instance->FindSkeletonNodes();
#else
FCDSceneNodeList roots;
_controller_instance->FindSkeletonNodes(roots);
#endif
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
process_joint(skeleton, *it);
void DaeCharacter::
adjust_joints(FCDSceneNode *node, const JointMap &joint_map,
const LMatrix4d &transform) {
LMatrix4d this_transform = transform;
if (node->IsJoint()) {
string sid = FROM_FSTRING(node->GetSubId());
JointMap::const_iterator ji = joint_map.find(sid);
if (ji != joint_map.end()) {
const Joint &joint = ji->second;
// Panda needs the joints to be in bind pose. Not fun! We copy the joint
// transform to the default pose, though, so that Panda will restore the
// joint transformation after binding.
if (joint._character == this) {
LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat *
invert(transform);
//LMatrix4d bind_pose = joint._bind_pose * _bind_shape_mat *
// joint._group->get_parent()->get_node_frame_inv();
this_transform = bind_pose * this_transform;
joint._group->set_default_pose(*joint._group);
joint._group->set_transform3d(bind_pose);
/*
PT(EggGroup) sphere = new EggGroup;
sphere->add_uniform_scale(0.1);
sphere->set_group_type(EggGroup::GT_instance);
sphere->add_child(new EggExternalReference("", "jack.egg"));
joint._group->add_child(sphere);
*/
}
}
} else {
//this_transform = DAEToEggConverter::convert_matrix(node->ToMatrix());
}
// Loop through the children joints
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
//if (node->GetChild(ch)->IsJoint()) {
adjust_joints(node->GetChild(ch), joint_map, this_transform);
//}
}
return bundle;
}
////////////////////////////////////////////////////////////////////
// Function: DaeCharacter::process_joint
// Function: DaeCharacter::influence_vertex
// Access: Public
// Description: Adds the influences for the given vertex.
////////////////////////////////////////////////////////////////////
void DaeCharacter::
influence_vertex(int index, EggVertex *vertex) {
const FCDSkinControllerVertex *influence = _skin_controller->GetVertexInfluence(index);
for (size_t pa = 0; pa < influence->GetPairCount(); ++pa) {
const FCDJointWeightPair* jwpair = influence->GetPair(pa);
if (jwpair->jointIndex >= 0 && jwpair->jointIndex < _joints.size()) {
EggGroup *joint = _joints[jwpair->jointIndex]._group.p();
if (joint != NULL) {
joint->ref_vertex(vertex, jwpair->weight);
}
} else {
daeegg_cat.error()
<< "Invalid joint index: " << jwpair->jointIndex << "\n";
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DaeCharacter::collect_keys
// Access: Public
// Description: Collects all animation keys of animations applied
// to this character.
////////////////////////////////////////////////////////////////////
void DaeCharacter::
collect_keys(pset<float> &keys) {
#if FCOLLADA_VERSION < 0x00030005
FCDSceneNodeList roots = _instance->FindSkeletonNodes();
#else
FCDSceneNodeList roots;
_instance->FindSkeletonNodes(roots);
#endif
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
r_collect_keys(*it, keys);
}
}
////////////////////////////////////////////////////////////////////
// Function: DaeCharacter::r_collect_keys
// Access: Public
// Description: Collects all animation keys found for the given
// node tree.
////////////////////////////////////////////////////////////////////
void DaeCharacter::
r_collect_keys(FCDSceneNode* node, pset<float> &keys) {
FCDAnimatedList animateds;
// Collect all the animation curves
for (size_t t = 0; t < node->GetTransformCount(); ++t) {
FCDTransform *transform = node->GetTransform(t);
FCDAnimated *animated = transform->GetAnimated();
if (animated != NULL) {
const FCDAnimationCurveListList &all_curves = animated->GetCurves();
for (size_t ci = 0; ci < all_curves.size(); ++ci) {
const FCDAnimationCurveTrackList &curves = all_curves[ci];
if (curves.empty()) {
continue;
}
size_t num_keys = curves.front()->GetKeyCount();
const FCDAnimationKey **curve_keys = curves.front()->GetKeys();
for (size_t c = 0; c < num_keys; ++c) {
keys.insert(curve_keys[c]->input);
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: DaeCharacter::build_table
// Access: Public
// Description: Processes a joint node and its transforms.
////////////////////////////////////////////////////////////////////
void DaeCharacter::
process_joint(PT(EggTable) parent, FCDSceneNode* node) {
build_table(EggTable *parent, FCDSceneNode* node, const pset<float> &keys) {
nassertv(node != NULL);
string node_id = FROM_FSTRING(node->GetDaeId());
PT(EggTable) joint = new EggTable(node_id);
joint->set_table_type(EggTable::TT_table);
parent->add_child(joint);
PT(EggXfmSAnim) xform = new EggXfmSAnim("xform");
joint->add_child(xform);
xform->set_fps(_frame_rate);
// Generate the sampled animation and loop through the matrices
FCDSceneNodeTools::GenerateSampledAnimation(node);
FMMatrix44List matrices = FCDSceneNodeTools::GetSampledAnimationMatrices();
for (FMMatrix44List::const_iterator it = matrices.begin(); it != matrices.end(); ++it) {
LMatrix4d matr = DAEToEggConverter::convert_matrix(*it);
assert(xform->add_data(matr));
if (!node->IsJoint()) {
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
build_table(parent, node->GetChild(ch), keys);
}
return;
}
// Loop through the children joints
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
if (node->GetChild(ch)->IsJoint()) {
process_joint(joint, node->GetChild(ch));
string node_id = FROM_FSTRING(node->GetDaeId());
PT(EggTable) table = new EggTable(node_id);
table->set_table_type(EggTable::TT_table);
parent->add_child(table);
PT(EggXfmSAnim) xform = new EggXfmSAnim("xform");
table->add_child(xform);
// Generate the sampled animation and loop through the matrices
FCDAnimatedList animateds;
// Collect all the animation curves
for (size_t t = 0; t < node->GetTransformCount(); ++t) {
FCDTransform *transform = node->GetTransform(t);
FCDAnimated *animated = transform->GetAnimated();
if (animated != (FCDAnimated *)NULL) {
if (animated->HasCurve()) {
animateds.push_back(animated);
}
}
}
// Sample the scene node transform
float last_key;
float timing_total = 0;
pset<float>::const_iterator ki;
for (ki = keys.begin(); ki != keys.end(); ++ki) {
for (FCDAnimatedList::iterator it = animateds.begin(); it != animateds.end(); ++it) {
// Sample each animated, which changes the transform values directly
(*it)->Evaluate(*ki);
}
if (ki != keys.begin()) {
timing_total += (*ki - last_key);
}
last_key = *ki;
// Retrieve the new transform matrix for the COLLADA scene node
FMMatrix44 fmat = node->ToMatrix();
// Work around issue in buggy exporters (like ColladaMax)
if (IS_NEARLY_ZERO(fmat[3][3])) {
fmat[3][3] = 1;
}
xform->add_data(DAEToEggConverter::convert_matrix(fmat));
}
// Quantize the FPS, otherwise Panda complains about FPS mismatches.
float fps = cfloor(((keys.size() - 1) / timing_total) * 100 + 0.5f) * 0.01f;
xform->set_fps(fps);
// Loop through the children joints
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
//if (node->GetChild(ch)->IsJoint()) {
build_table(table, node->GetChild(ch), keys);
//}
}
}

View File

@ -12,20 +12,22 @@
//
////////////////////////////////////////////////////////////////////
#ifndef DAECHARACTER_H
#define DAECHARACTER_H
#include "pandatoolbase.h"
#include "typedReferenceCount.h"
#include "typeHandle.h"
#include "eggTable.h"
#include "daeToEggConverter.h"
#include "pre_fcollada_include.h"
#include "FCollada.h"
#include "FCDocument/FCDSceneNode.h"
#include "FCDocument/FCDControllerInstance.h"
#include "FCDocument/FCDSkinController.h"
#include "FCDocument/FCDGeometryMesh.h"
#ifndef DAECHARACTER_H
#define DAECHARACTER_H
class DAEToEggConverter;
////////////////////////////////////////////////////////////////////
// Class : DaeCharacter
@ -33,17 +35,46 @@
////////////////////////////////////////////////////////////////////
class DaeCharacter : public TypedReferenceCount {
public:
DaeCharacter(const string name, const FCDControllerInstance* controller_instance);
PT(EggTable) as_egg_bundle();
void process_joint(PT(EggTable) parent, FCDSceneNode* node);
DaeCharacter(EggGroup *node_group, const FCDControllerInstance* controller_instance);
struct Joint {
INLINE Joint(EggGroup *group, const FCDSceneNode *scene_node) :
_group(group),
_scene_node(scene_node),
_character(NULL),
_bind_pose(LMatrix4d::ident_mat()) {}
LMatrix4d _bind_pose;
PT(EggGroup) _group;
const FCDSceneNode *_scene_node;
DaeCharacter *_character;
};
typedef pvector<Joint> Joints;
typedef pmap<string, Joint> JointMap;
void bind_joints(JointMap &joint_map);
void adjust_joints(FCDSceneNode *node, const JointMap &joint_map,
const LMatrix4d &transform = LMatrix4d::ident_mat());
void influence_vertex(int index, EggVertex *vertex);
void collect_keys(pset<float> &keys);
void r_collect_keys(FCDSceneNode *node, pset<float> &keys);
void build_table(EggTable *parent, FCDSceneNode* node, const pset<float> &keys);
public:
PT(EggGroup) _node_group;
const FCDGeometryMesh *_skin_mesh;
const FCDControllerInstance *_instance;
LMatrix4d _bind_shape_mat;
private:
int _frame_rate;
string _name;
FCDControllerInstance* _controller_instance;
FCDSkinController* _skin_controller;
pmap<string, FCDSkinControllerJoint*> _controller_joints;
const FCDSkinController *_skin_controller;
Joints _joints;
JointMap _bound_joints;
public:
virtual TypeHandle get_type() const {
return get_class_type();

View File

@ -35,7 +35,7 @@ TypeHandle DaeMaterials::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: DaeMaterials::Constructor
// Access: Public
// Description:
// Description:
////////////////////////////////////////////////////////////////////
DaeMaterials::
DaeMaterials(const FCDGeometryInstance* geometry_instance) {
@ -58,7 +58,7 @@ void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) {
return;
}
_materials[semantic] = new DaeMaterial();
// Load in the uvsets
for (size_t vib = 0; vib < instance->GetVertexInputBindingCount(); ++vib) {
const FCDMaterialInstanceBindVertexInput* mivib = instance->GetVertexInputBinding(vib);
@ -74,7 +74,7 @@ void DaeMaterials::add_material_instance(const FCDMaterialInstance* instance) {
#endif
_materials[semantic]->_uvsets.push_back(bvi);
}
// Handle the material stuff
daeegg_cat.spam() << "Trying to process material with semantic " << semantic << endl;
PT_EggMaterial egg_material = new EggMaterial(semantic);
@ -204,12 +204,13 @@ process_extra(const string semantic, const FCDExtra* extra) {
for (size_t et = 0; et < etype->GetTechniqueCount(); ++et) {
const FCDENode* enode = ((const FCDENode*)(etype->GetTechnique(et)))->FindChildNode("double_sided");
if (enode != NULL) {
if (trim(enode->GetContent()) == "1") {
string content = trim(enode->GetContent());
if (content == "1" || content == "true") {
_materials[semantic]->_double_sided = true;
} else if (trim(enode->GetContent()) == "0") {
} else if (content == "0" || content == "false") {
_materials[semantic]->_double_sided = false;
} else {
daeegg_cat.warning() << "Expected <double_sided> tag to be either 1 or 0, found '" << enode->GetContent() << "' instead" << endl;
daeegg_cat.warning() << "Expected <double_sided> tag to be either 1 or 0, found '" << content << "' instead" << endl;
}
}
}
@ -391,7 +392,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen
blend->_color = LColor::zero();
blend->_operand_a = EggGroup::BO_unspecified;
blend->_operand_b = EggGroup::BO_unspecified;
// First fill in the color value.
if (mode == FCDEffectStandard::A_ONE) {// || mode == FCDEffectStandard::A_ZERO) {
double value = transparent[3] * transparency;
@ -404,7 +405,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen
blend->_enabled = false;
return blend;
}
// Now figure out the operands.
if (mode == FCDEffectStandard::RGB_ZERO) {// || mode == FCDEffectStandard::A_ZERO) {
blend->_operand_a = EggGroup::BO_one_minus_constant_color;
@ -417,7 +418,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen
blend->_enabled = false;
return blend;
}
// See if we can optimize out the color.
if (blend->_operand_a == EggGroup::BO_constant_color) {
if (blend->_color == LColor::zero()) {
@ -447,7 +448,7 @@ convert_blend(FCDEffectStandard::TransparencyMode mode, const LColor &transparen
blend->_operand_b = EggGroup::BO_zero;
}
}
// See if we can entirely disable the blend.
if (blend->_operand_a == EggGroup::BO_one && blend->_operand_b == EggGroup::BO_zero) {
blend->_enabled = false;

View File

@ -56,9 +56,10 @@
////////////////////////////////////////////////////////////////////
DAEToEggConverter::
DAEToEggConverter() {
_unit_name = "meter";
_unit_meters = 1.0;
_document = NULL;
_table = NULL;
_frame_rate = -1;
_error_handler = NULL;
_invert_transparency = false;
}
@ -131,18 +132,15 @@ convert_file(const Filename &filename) {
// Reset stuff
clear_error();
_joints.clear();
_vertex_pools.clear();
_skeletons.clear();
_frame_rate = -1;
if (_error_handler == NULL) {
_error_handler = new FUErrorSimpleHandler;
}
// The default coordinate system is Y-up
if (_egg_data->get_coordinate_system() == CS_default) {
_egg_data->set_coordinate_system(CS_yup_right);
}
// Read the file
FCollada::Initialize();
_document = FCollada::LoadDocument(filename.to_os_specific().c_str());
@ -155,201 +153,375 @@ convert_file(const Filename &filename) {
if (_document->GetAsset() != NULL) {
FCDocumentTools::StandardizeUpAxisAndLength(_document);
}
_table = new EggTable();
_table->set_table_type(EggTable::TT_table);
// Process the stuff
// Process the scene
process_asset();
preprocess();
PT(EggGroup) scene_group;
string model_name = _character_name;
FCDSceneNode* visual_scene = _document->GetVisualSceneInstance();
if (visual_scene != NULL) {
// First check for an <extra> tag
const FCDExtra* extra = visual_scene->GetExtra();
//FIXME: eek this looks horrid
if (extra != NULL) {
const FCDEType* etype = extra->GetDefaultType();
if (etype != NULL) {
const FCDENode* enode = (const FCDENode*) etype->FindTechnique("MAX3D");
if (enode != NULL) {
enode = enode->FindChildNode("frame_rate");
if (enode != NULL && !string_to_int(enode->GetContent(), _frame_rate)) {
daeegg_cat.warning() << "Invalid integer in <frame_rate> tag: '" << enode->GetContent() << "'" << endl;
} } } }
// Now loop through the children
if (model_name.empty()) {
// By lack of anything better...
model_name = FROM_FSTRING(visual_scene->GetName());
}
scene_group = new EggGroup(model_name);
_egg_data->add_child(scene_group);
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
process_node(DCAST(EggGroupNode, _egg_data), visual_scene->GetChild(ch));
process_node(scene_group, visual_scene->GetChild(ch));
}
} else {
daeegg_cat.warning()
<< "No visual scene instance found in COLLADA document.\n";
}
// Now process the characters. This depends on information from collected
// joints, which is why it's done in a second step.
if (get_animation_convert() != AC_none) {
Characters::iterator it;
DaeCharacter *character;
for (it = _characters.begin(); it != _characters.end(); ++it) {
character = *it;
if (get_animation_convert() != AC_chan) {
character->bind_joints(_joints);
const FCDGeometryMesh *mesh = character->_skin_mesh;
if (mesh != NULL) {
PT(DaeMaterials) materials = new DaeMaterials(character->_instance);
daeegg_cat.spam() << "Processing mesh for controller\n";
process_mesh(character->_node_group, mesh, materials, character);
}
}
}
// Put the joints in bind pose.
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
character->adjust_joints(visual_scene->GetChild(ch), _joints, LMatrix4d::ident_mat());
}
if (scene_group != NULL) {
// Mark the scene as character.
if (get_animation_convert() == AC_chan) {
_egg_data->remove_child(scene_group);
} else {
scene_group->set_dart_type(EggGroup::DT_default);
}
}
if (get_animation_convert() != AC_model) {
_table = new EggTable();
_table->set_table_type(EggTable::TT_table);
_egg_data->add_child(_table);
PT(EggTable) bundle = new EggTable(model_name);
bundle->set_table_type(EggTable::TT_bundle);
_table->add_child(bundle);
PT(EggTable) skeleton = new EggTable("<skeleton>");
skeleton->set_table_type(EggTable::TT_table);
bundle->add_child(skeleton);
pset<float> keys;
Characters::iterator it;
DaeCharacter *character;
for (it = _characters.begin(); it != _characters.end(); ++it) {
character = *it;
// Collect key frame timings.
if (get_animation_convert() == AC_both ||
get_animation_convert() == AC_chan) {
character->collect_keys(keys);
}
}
if (_frame_inc != 0.0) {
// A frame increment was given, this means that we have to sample the
// animation.
float start, end;
if (_end_frame != _start_frame) {
start = _start_frame;
end = _end_frame;
} else {
// No range was given. Infer the frame range from the keys.
start = *keys.begin();
end = *keys.rbegin();
}
keys.clear();
for (float t = start; t <= end; t += _frame_inc) {
keys.insert(t);
}
} else {
// No sampling parameters given; not necessarily a failure, since the
// animation may already be sampled. We use the key frames as animation
// frames.
if (_end_frame != 0.0) {
// An end frame was given, chop off all keys after that.
float end = _end_frame;
pset<float>::iterator ki;
for (ki = keys.begin(); ki != keys.end(); ++ki) {
if (*ki > end && !IS_THRESHOLD_EQUAL(*ki, end, 0.001)) {
keys.erase(ki, keys.end());
break;
}
}
}
if (_start_frame != 0.0) {
// A start frame was given, chop off all keys before that.
float start = _start_frame;
pset<float>::iterator ki;
for (ki = keys.begin(); ki != keys.end(); ++ki) {
if (*ki > start && !IS_THRESHOLD_EQUAL(*ki, start, 0.001)) {
keys.erase(keys.begin(), ki);
break;
}
}
}
// Check that this does indeed look like a sampled animation; if not,
// issue an appropriate warning.
pset<float>::const_iterator ki = keys.begin();
if (ki != keys.end()) {
float last = *ki;
float diff = 0;
for (++ki; ki != keys.end(); ++ki) {
if (diff != 0 && !IS_THRESHOLD_EQUAL((*ki - last), diff, 0.001)) {
daeegg_cat.error()
<< "This does not appear to be a sampled animation.\n"
<< "Specify the -sf, -ef and -if options to indicate how the "
<< "animations should be sampled.\n";
break;
}
diff = (*ki - last);
last = *ki;
}
}
}
// It doesn't really matter which character we grab for this as
// it'll iterate over the whole graph right now anyway.
for (size_t ch = 0; ch < visual_scene->GetChildrenCount(); ++ch) {
character->build_table(skeleton, visual_scene->GetChild(ch), keys);
}
}
}
SAFE_DELETE(visual_scene);
_egg_data->add_child(_table);
// Clean up and return
SAFE_DELETE(visual_scene);
SAFE_DELETE(_document);
FCollada::Release();
return true;
}
void DAEToEggConverter::process_asset() {
if (_document->GetAsset() == NULL) return;
////////////////////////////////////////////////////////////////////
// Function: DAEToEggConverter::get_input_units
// Access: Public, Virtual
// Description: This may be called after convert_file() has been
// called and returned true, indicating a successful
// conversion. It will return the distance units
// represented by the converted egg file, if known, or
// DU_invalid if not known.
////////////////////////////////////////////////////////////////////
DistanceUnit DAEToEggConverter::
get_input_units() {
if (IS_NEARLY_EQUAL(_unit_meters, 0.001)) {
return DU_millimeters;
}
if (IS_NEARLY_EQUAL(_unit_meters, 0.01)) {
return DU_centimeters;
}
if (IS_NEARLY_EQUAL(_unit_meters, 1.0)) {
return DU_meters;
}
if (IS_NEARLY_EQUAL(_unit_meters, 1000.0)) {
return DU_kilometers;
}
if (IS_NEARLY_EQUAL(_unit_meters, 3.0 * 12.0 * 0.0254)) {
return DU_yards;
}
if (IS_NEARLY_EQUAL(_unit_meters, 12.0 * 0.0254)) {
return DU_feet;
}
if (IS_NEARLY_EQUAL(_unit_meters, 0.0254)) {
return DU_inches;
}
if (IS_NEARLY_EQUAL(_unit_meters, 1852.0)) {
return DU_nautical_miles;
}
if (IS_NEARLY_EQUAL(_unit_meters, 5280.0 * 12.0 * 0.0254)) {
return DU_statute_miles;
}
// Whatever.
return DU_invalid;
}
void DAEToEggConverter::
process_asset() {
const FCDAsset *asset = _document->GetAsset();
if (_document->GetAsset() == NULL) {
return;
}
_unit_name = FROM_FSTRING(asset->GetUnitName());
_unit_meters = asset->GetUnitConversionFactor();
// Read out the coordinate system
FMVector3 up_axis (_document->GetAsset()->GetUpAxis());
FMVector3 up_axis = asset->GetUpAxis();
if (up_axis == FMVector3(0, 1, 0)) {
_egg_data->set_coordinate_system(CS_yup_right);
} else if (up_axis == FMVector3(0, 0, 1)) {
_egg_data->set_coordinate_system(CS_zup_right);
} else {
_egg_data->set_coordinate_system(CS_invalid);
daeegg_cat.warning() << "Unrecognized coordinate system!\n";
}
}
// This function lists all the joints and referenced skeletons
void DAEToEggConverter::preprocess(const FCDSceneNode* node) {
// If the node is NULL, take the visual scene instance.
if (node == NULL) {
assert(_document != NULL);
_skeletons.clear();
_joints.clear();
node = _document->GetVisualSceneInstance();
}
if (node == NULL) return;
if (node->IsJoint()) {
_joints[FROM_FSTRING(node->GetDaeId())] = NULL;
}
// Loop through the instances first.
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
if (node->GetInstance(in)->GetType() == FCDEntityInstance::CONTROLLER) {
// Loop through the skeleton roots now.
#if FCOLLADA_VERSION < 0x00030005
FCDSceneNodeList roots = ((FCDControllerInstance*) node->GetInstance(in))->FindSkeletonNodes();
#else
FCDSceneNodeList roots;
((FCDControllerInstance*) node->GetInstance(in))->FindSkeletonNodes(roots);
#endif
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
daeegg_cat.spam() << "Found referenced skeleton root " << FROM_FSTRING((*it)->GetDaeId()) << endl;
_skeletons.push_back(FROM_FSTRING((*it)->GetDaeId()));
}
}
}
// Now loop through the children and recurse.
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
preprocess(node->GetChild(ch));
}
}
// Process the node. If forced is true, it will even process it if its known to be a skeleton root.
void DAEToEggConverter::process_node(PT(EggGroupNode) parent, const FCDSceneNode* node, bool forced) {
void DAEToEggConverter::
process_node(EggGroupNode *parent, const FCDSceneNode* node, bool forced) {
nassertv(node != NULL);
string node_id = FROM_FSTRING(node->GetDaeId());
daeegg_cat.spam() << "Processing node with ID '" << node_id << "'" << endl;
// Important! If it's known to be a skeleton root, ignore it for now, unless we're processing forced.
if (!forced && count(_skeletons.begin(), _skeletons.end(), node_id) > 0) {
daeegg_cat.spam() << "Ignoring skeleton root node with ID '" << node_id << "', we'll process it later" << endl;
return;
}
// Create an egg group for this node
PT(EggGroup) node_group = new EggGroup(FROM_FSTRING(node->GetName()));
PT(EggGroup) node_group = new EggGroup(FROM_FSTRING(node->GetDaeId()));
process_extra(node_group, node->GetExtra());
parent->add_child(node_group);
// Check if its a joint
if (node->IsJoint()) {
string sid = FROM_FSTRING(node->GetSubId());
node_group->set_group_type(EggGroup::GT_joint);
_joints[node_id] = node_group;
if (!_joints.insert(DaeCharacter::JointMap::value_type(sid,
DaeCharacter::Joint(node_group, node))).second) {
daeegg_cat.error()
<< "Joint with sid " << sid << " occurs more than once!\n";
}
}
// Loop through the transforms and apply them
for (size_t tr = 0; tr < node->GetTransformCount(); ++tr) {
apply_transform(node_group, node->GetTransform(tr));
// Loop through the transforms and apply them (in reverse order)
for (size_t tr = node->GetTransformCount(); tr > 0; --tr) {
apply_transform(node_group, node->GetTransform(tr - 1));
}
//node_group->set_transform3d(convert_matrix(node->ToMatrix()));
// Loop through the instances and process them
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
process_instance(node_group, node->GetInstance(in));
}
// Loop through the children and recursively process them
for (size_t ch = 0; ch < node->GetChildrenCount(); ++ch) {
process_node(DCAST(EggGroupNode, node_group), node->GetChild(ch));
}
// Loop through any possible scene node instances and process those, too.
for (size_t in = 0; in < node->GetInstanceCount(); ++in) {
if (node->GetInstance(in)->GetEntity() && node->GetInstance(in)->GetEntity()->GetType() == FCDEntity::SCENE_NODE) {
process_node(DCAST(EggGroupNode, node_group), (const FCDSceneNode*) node->GetInstance(in)->GetEntity());
const FCDEntity *entity = node->GetInstance(in)->GetEntity();
if (entity && entity->GetType() == FCDEntity::SCENE_NODE) {
process_node(node_group, (const FCDSceneNode*) entity);
}
}
}
void DAEToEggConverter::process_instance(PT(EggGroup) parent, const FCDEntityInstance* instance) {
void DAEToEggConverter::
process_instance(EggGroup *parent, const FCDEntityInstance* instance) {
nassertv(instance != NULL);
nassertv(instance->GetEntity() != NULL);
// Check what kind of instance this is
switch (instance->GetType()) {
case FCDEntityInstance::GEOMETRY: {
const FCDGeometry* geometry = (const FCDGeometry*) instance->GetEntity();
assert(geometry != NULL);
if (geometry->IsMesh()) {
// Now, handle the mesh.
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
case FCDEntityInstance::GEOMETRY:
{
if (get_animation_convert() != AC_chan) {
const FCDGeometry* geometry = (const FCDGeometry*) instance->GetEntity();
assert(geometry != NULL);
if (geometry->IsMesh()) {
// Now, handle the mesh.
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
}
if (geometry->IsSpline()) {
process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
}
}
if (geometry->IsSpline()) {
process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
}
break; }
case FCDEntityInstance::CONTROLLER: {
// Add the dart tag and process the controller instance
parent->set_dart_type(EggGroup::DT_default);
process_controller(parent, (const FCDControllerInstance*) instance);
break; }
case FCDEntityInstance::MATERIAL:
// We don't process this directly, handled per-geometry instead.
break;
case FCDEntityInstance::SIMPLE: {
// Grab the entity and check it's type.
}
break;
case FCDEntityInstance::CONTROLLER:
// Add the dart tag and process the controller instance
//parent->set_dart_type(EggGroup::DT_default);
process_controller(parent, (const FCDControllerInstance*) instance);
break;
case FCDEntityInstance::MATERIAL:
// We don't process this directly, handled per-geometry instead.
break;
case FCDEntityInstance::SIMPLE:
{
// Grab the entity and check its type.
const FCDEntity* entity = instance->GetEntity();
if (entity->GetType() != FCDEntity::SCENE_NODE) {
daeegg_cat.warning() << "Unsupported entity type found" << endl;
}
break; }
default:
daeegg_cat.warning() << "Unsupported instance type found" << endl;
}
break;
default:
daeegg_cat.warning() << "Unsupported instance type found" << endl;
}
}
// Processes the given mesh.
void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* mesh, PT(DaeMaterials) materials) {
void DAEToEggConverter::
process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh,
DaeMaterials *materials, DaeCharacter *character) {
nassertv(mesh != NULL);
daeegg_cat.debug() << "Processing mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << endl;
// Create the egg stuff to hold this mesh
PT(EggGroup) mesh_group = new EggGroup(FROM_FSTRING(mesh->GetDaeId()));
parent->add_child(mesh_group);
PT(EggVertexPool) mesh_pool = new EggVertexPool(FROM_FSTRING(mesh->GetDaeId()));
mesh_group->add_child(mesh_pool);
_vertex_pools[FROM_FSTRING(mesh->GetDaeId())] = mesh_pool;
// First retrieve the vertex source
if (mesh->GetSourceCount() == 0) {
daeegg_cat.debug() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has no sources" << endl;
return;
}
const FCDGeometrySource* vsource = mesh->FindSourceByType(FUDaeGeometryInput::POSITION);
const FCDGeometrySource* vsource = mesh->FindSourceByType(FUDaeGeometryInput::POSITION);
if (vsource == NULL) {
daeegg_cat.debug() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has no source for POSITION data" << endl;
return;
}
// Loop through the polygon groups and add them
daeegg_cat.spam() << "Mesh with id " << FROM_FSTRING(mesh->GetDaeId()) << " has " << mesh->GetPolygonsCount() << " polygon groups" << endl;
if (mesh->GetPolygonsCount() == 0) return;
// This is an array of pointers, I know. But since they are refcounted, I don't have a better idea.
PT(EggGroup) *primitive_holders = new PT(EggGroup) [mesh->GetPolygonsCount()];
for (size_t gr = 0; gr < mesh->GetPolygonsCount(); ++gr) {
const FCDGeometryPolygons* polygons = mesh->GetPolygons(gr);
string material_semantic = FROM_FSTRING(polygons->GetMaterialSemantic());
// Stores which group holds the primitives.
PT(EggGroup) primitiveholder;
// If we have materials, make a group for each material. Then, apply the material's per-group stuff.
if (materials != NULL && (!polygons->GetMaterialSemantic().empty()) && mesh->GetPolygonsCount() > 1) {
primitiveholder = new EggGroup(FROM_FSTRING(mesh->GetDaeId()) + "." + FROM_FSTRING(polygons->GetMaterialSemantic()));
//primitiveholder = new EggGroup(FROM_FSTRING(mesh->GetDaeId()) + "." + material_semantic);
primitiveholder = new EggGroup;
mesh_group->add_child(primitiveholder);
} else {
primitiveholder = mesh_group;
@ -357,7 +529,7 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
primitive_holders[gr] = primitiveholder;
// Apply the per-group data of the materials, if we have it.
if (materials != NULL) {
materials->apply_to_group(FROM_FSTRING(polygons->GetMaterialSemantic()), primitiveholder, _invert_transparency);
materials->apply_to_group(material_semantic, primitiveholder, _invert_transparency);
}
// Find the position sources
const FCDGeometryPolygonsInput* pinput = polygons->FindInput(FUDaeGeometryInput::POSITION);
@ -389,26 +561,47 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
const uint32* tindices;
if (tinput != NULL) tindices = tinput->GetIndices();
// Get a name for potential coordinate sets
string tcsetname ("");
string tcsetname;
if (materials != NULL && tcinput != NULL) {
daeegg_cat.debug() << "Assigning texcoord set " << tcinput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n";
tcsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXCOORD, tcinput->GetSet());
if (daeegg_cat.is_debug()) {
daeegg_cat.debug()
<< "Assigning texcoord set " << tcinput->GetSet()
<< " to semantic '" << material_semantic << "'\n";
}
tcsetname = materials->get_uvset_name(material_semantic,
FUDaeGeometryInput::TEXCOORD, tcinput->GetSet());
}
string tbsetname ("");
string tbsetname;
if (materials != NULL && binput != NULL) {
daeegg_cat.debug() << "Assigning texbinormal set " << binput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n";
tbsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXBINORMAL, binput->GetSet());
if (daeegg_cat.is_debug()) {
daeegg_cat.debug()
<< "Assigning texbinormal set " << binput->GetSet()
<< " to semantic '" << material_semantic << "'\n";
}
tbsetname = materials->get_uvset_name(material_semantic,
FUDaeGeometryInput::TEXBINORMAL, binput->GetSet());
}
string ttsetname ("");
string ttsetname;
if (materials != NULL && tinput != NULL) {
daeegg_cat.debug() << "Assigning textangent set " << tinput->GetSet() << " to semantic '" << FROM_FSTRING(polygons->GetMaterialSemantic()) << "'\n";
ttsetname = materials->get_uvset_name(FROM_FSTRING(polygons->GetMaterialSemantic()), FUDaeGeometryInput::TEXTANGENT, tinput->GetSet());
if (daeegg_cat.is_debug()) {
daeegg_cat.debug()
<< "Assigning textangent set " << tinput->GetSet()
<< " to semantic '" << material_semantic << "'\n";
}
ttsetname = materials->get_uvset_name(material_semantic,
FUDaeGeometryInput::TEXTANGENT, tinput->GetSet());
}
// Loop through the indices and add the vertices.
for (size_t ix = 0; ix < pinput->GetIndexCount(); ++ix) {
PT_EggVertex vertex = mesh_pool->make_new_vertex();
const float* data = &vsource->GetData()[indices[ix]*3];
vertex->set_pos(LPoint3d(data[0], data[1], data[2]));
if (character != NULL) {
// If this is skinned geometry, add the vertex influences.
character->influence_vertex(indices[ix], vertex);
}
// Process the normal
if (nsource != NULL && ninput != NULL) {
assert(nsource->GetStride() == 3);
@ -469,26 +662,26 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
PT(EggPrimitive) primitive = NULL;
// Create a primitive that matches the fcollada type
switch (polygons->GetPrimitiveType()) {
case FCDGeometryPolygons::LINES:
primitive = new EggLine();
break;
case FCDGeometryPolygons::POLYGONS:
primitive = new EggPolygon();
break;
case FCDGeometryPolygons::TRIANGLE_FANS:
primitive = new EggTriangleFan();
break;
case FCDGeometryPolygons::TRIANGLE_STRIPS:
primitive = new EggTriangleStrip();
break;
case FCDGeometryPolygons::POINTS:
primitive = new EggPoint();
break;
case FCDGeometryPolygons::LINE_STRIPS:
daeegg_cat.warning() << "Linestrips not yet supported!" << endl;
break;
default:
daeegg_cat.warning() << "Unsupported primitive type found!" << endl;
case FCDGeometryPolygons::LINES:
primitive = new EggLine();
break;
case FCDGeometryPolygons::POLYGONS:
primitive = new EggPolygon();
break;
case FCDGeometryPolygons::TRIANGLE_FANS:
primitive = new EggTriangleFan();
break;
case FCDGeometryPolygons::TRIANGLE_STRIPS:
primitive = new EggTriangleStrip();
break;
case FCDGeometryPolygons::POINTS:
primitive = new EggPoint();
break;
case FCDGeometryPolygons::LINE_STRIPS:
daeegg_cat.warning() << "Linestrips not yet supported!" << endl;
break;
default:
daeegg_cat.warning() << "Unsupported primitive type found!" << endl;
}
if (primitive != NULL) {
primitive_holders[gr]->add_child(primitive);
@ -506,7 +699,8 @@ void DAEToEggConverter::process_mesh(PT(EggGroup) parent, const FCDGeometryMesh*
delete[] primitive_holders;
}
void DAEToEggConverter::process_spline(PT(EggGroup) parent, const string group_name, FCDGeometrySpline* geometry_spline) {
void DAEToEggConverter::
process_spline(EggGroup *parent, const string group_name, FCDGeometrySpline* geometry_spline) {
assert(geometry_spline != NULL);
PT(EggGroup) result = new EggGroup(group_name);
parent->add_child(result);
@ -521,7 +715,8 @@ void DAEToEggConverter::process_spline(PT(EggGroup) parent, const string group_n
}
}
void DAEToEggConverter::process_spline(PT(EggGroup) parent, const FCDSpline* spline) {
void DAEToEggConverter::
process_spline(EggGroup *parent, const FCDSpline* spline) {
assert(spline != NULL);
nassertv(spline->GetSplineType() == FUDaeSplineType::NURBS);
// Now load in the nurbs curve to the egg library
@ -542,70 +737,26 @@ void DAEToEggConverter::process_spline(PT(EggGroup) parent, const FCDSpline* spl
}
}
void DAEToEggConverter::process_controller(PT(EggGroup) parent, const FCDControllerInstance* instance) {
void DAEToEggConverter::
process_controller(EggGroup *parent, const FCDControllerInstance *instance) {
assert(instance != NULL);
const FCDController* controller = (const FCDController*) instance->GetEntity();
const FCDController* controller = (const FCDController *)instance->GetEntity();
assert(controller != NULL);
PT(EggVertexPool) vertex_pool = NULL;
// Add the skin geometry
const FCDGeometry* geometry = controller->GetBaseGeometry();
if (geometry != NULL) {
if (geometry->IsMesh()) {
process_mesh(parent, geometry->GetMesh(), new DaeMaterials((const FCDGeometryInstance*) instance));
if (get_animation_convert() == AC_none) {
// If we're exporting a static mesh, export the base geometry as-is.
const FCDGeometryMesh *mesh = controller->GetBaseGeometry()->GetMesh();
if (mesh != NULL) {
PT(DaeMaterials) materials = new DaeMaterials(instance);
daeegg_cat.spam() << "Processing mesh for controller\n";
if (_vertex_pools.count(FROM_FSTRING(geometry->GetMesh()->GetDaeId()))) {
daeegg_cat.debug() << "Using vertex pool " << FROM_FSTRING(geometry->GetMesh()->GetDaeId()) << "\n";
vertex_pool = _vertex_pools[FROM_FSTRING(geometry->GetMesh()->GetDaeId())];
}
}
if (geometry->IsSpline()) {
process_spline(parent, FROM_FSTRING(geometry->GetName()), const_cast<FCDGeometrySpline*> (geometry->GetSpline()));
}
}
// Add the joint hierarchy
#if FCOLLADA_VERSION < 0x00030005
FCDSceneNodeList roots = (const_cast<FCDControllerInstance*> (instance))->FindSkeletonNodes();
#else
FCDSceneNodeList roots;
(const_cast<FCDControllerInstance*> (instance))->FindSkeletonNodes(roots);
#endif
for (FCDSceneNodeList::iterator it = roots.begin(); it != roots.end(); ++it) {
process_node(DCAST(EggGroupNode, parent), *it, true);
}
if (controller->IsSkin()) {
// Load in the vertex influences first
pmap<int32, pvector<pair<PT_EggVertex, PN_stdfloat> > > influences;
if (vertex_pool) {
for (size_t in = 0; in < controller->GetSkinController()->GetInfluenceCount(); ++in) {
assert(vertex_pool->has_vertex(in));
for (size_t pa = 0; pa < controller->GetSkinController()->GetVertexInfluence(in)->GetPairCount(); ++pa) {
const FCDJointWeightPair* jwpair = controller->GetSkinController()->GetVertexInfluence(in)->GetPair(pa);
influences[jwpair->jointIndex].push_back(pair<PT_EggVertex, PN_stdfloat> (vertex_pool->get_vertex(in), jwpair->weight));
}
}
}
// Loop through the joints in the vertex influences
for (pmap<int32, pvector<pair<PT_EggVertex, PN_stdfloat> > >::iterator it = influences.begin(); it != influences.end(); ++it) {
if (it->first == -1) {
daeegg_cat.warning() << "Ignoring vertex influence with negative joint index\n";
//FIXME: Why are there joints with index -1
} else {
const string joint_id = FROM_FSTRING(controller->GetSkinController()->GetJoint(it->first)->GetId());
//TODO: what if the joints have just not been defined yet?
if (_joints.count(joint_id) > 0) {
if (_joints[joint_id]) {
for (pvector<pair<PT_EggVertex, PN_stdfloat> >::iterator vi = it->second.begin(); vi != it->second.end(); ++vi) {
_joints[joint_id]->ref_vertex(vi->first, vi->second);
}
} else {
daeegg_cat.warning() << "Unprocessed joint being referenced: '" << joint_id << "'" << endl;
}
} else {
daeegg_cat.warning() << "Unknown joint being referenced: '" << joint_id << "'" << endl;
}
}
process_mesh(parent, mesh, materials);
}
} else {
// Add a character for this to the table, the mesh is processed later
PT(DaeCharacter) character = new DaeCharacter(parent, instance);
_characters.push_back(character);
}
if (controller->IsMorph()) {
assert(controller != NULL);
const FCDMorphController* morph_controller = controller->GetMorphController();
@ -628,28 +779,25 @@ void DAEToEggConverter::process_controller(PT(EggGroup) parent, const FCDControl
morph->add_child(target);
}
}
// Get a <Bundle> for the character and add it to the table
PT(DaeCharacter) character = new DaeCharacter(parent->get_name(), instance);
_table->add_child(character->as_egg_bundle());
}
void DAEToEggConverter::process_extra(PT(EggGroup) group, const FCDExtra* extra) {
void DAEToEggConverter::
process_extra(EggGroup *group, const FCDExtra* extra) {
if (extra == NULL) {
return;
}
nassertv(group != NULL);
const FCDEType* etype = extra->GetDefaultType();
if (etype == NULL) {
return;
}
const FCDENode* enode = (const FCDENode*) etype->FindTechnique("PANDA3D");
if (enode == NULL) {
return;
}
FCDENodeList tags;
enode->FindChildrenNodes("param", tags);
for (FCDENodeList::iterator it = tags.begin(); it != tags.end(); ++it) {
@ -660,18 +808,45 @@ void DAEToEggConverter::process_extra(PT(EggGroup) group, const FCDExtra* extra)
}
}
LMatrix4d DAEToEggConverter::convert_matrix(const FMMatrix44& matrix) {
LMatrix4d result = LMatrix4d::zeros_mat();
for (char x = 0; x < 4; ++x) {
for (char y = 0; y < 4; ++y) {
result(x, y) = matrix[x][y];
}
}
return result;
LMatrix4d DAEToEggConverter::
convert_matrix(const FMMatrix44 &matrix) {
return LMatrix4d(
matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
}
void DAEToEggConverter::apply_transform(const PT(EggGroup) to, const FCDTransform* from) {
void DAEToEggConverter::
apply_transform(EggGroup *to, const FCDTransform* from) {
assert(from != NULL);
assert(to != NULL);
to->set_transform3d(convert_matrix(from->ToMatrix()) * to->get_transform3d());
//to->set_transform3d(convert_matrix(from->ToMatrix()) * to->get_transform3d());
switch (from->GetType()) {
case FCDTransform::TRANSLATION:
{
const FCDTTranslation *trans = (const FCDTTranslation *)from;
to->add_translate3d(TO_VEC3(trans->GetTranslation()));
}
break;
case FCDTransform::ROTATION:
{
const FCDTRotation *rot = (const FCDTRotation *)from;
to->add_rotate3d(rot->GetAngle(), TO_VEC3(rot->GetAxis()));
}
break;
case FCDTransform::SCALE:
{
const FCDTScale *scale = (const FCDTScale *)from;
to->add_scale3d(TO_VEC3(scale->GetScale()));
}
break;
default:
// Either a matrix, or something we can't handle.
to->add_matrix4(convert_matrix(from->ToMatrix()));
break;
}
}

View File

@ -35,6 +35,7 @@
#include "FMath/FMMatrix44.h"
#include "daeMaterials.h"
#include "daeCharacter.h"
#include "pvector.h" // Include last
////////////////////////////////////////////////////////////////////
@ -47,39 +48,41 @@ public:
DAEToEggConverter();
DAEToEggConverter(const DAEToEggConverter &copy);
~DAEToEggConverter();
virtual SomethingToEggConverter *make_copy();
virtual string get_name() const;
virtual string get_extension() const;
virtual bool convert_file(const Filename &filename);
virtual DistanceUnit get_input_units();
bool _invert_transparency;
private:
string _unit_name;
double _unit_meters;
PT(EggTable) _table;
FCDocument* _document;
FUErrorSimpleHandler* _error_handler;
pmap<const string, PT(EggGroup)> _joints;
pmap<const string, PT(EggVertexPool)> _vertex_pools;
pvector<string> _skeletons;
int _frame_rate;
DaeCharacter::JointMap _joints;
typedef pvector<PT(DaeCharacter)> Characters;
Characters _characters;
void process_asset();
void preprocess(const FCDSceneNode* node = NULL);
void process_node(PT(EggGroupNode) parent, const FCDSceneNode* node, bool forced = false);
void process_instance(PT(EggGroup) parent, const FCDEntityInstance* instance);
void process_mesh(PT(EggGroup) parent, const FCDGeometryMesh* mesh, PT(DaeMaterials) materials);
void process_spline(PT(EggGroup) parent, const string group_name, FCDGeometrySpline* geometry_spline);
void process_spline(PT(EggGroup) parent, const FCDSpline* spline);
void process_controller(PT(EggGroup) parent, const FCDControllerInstance* instance);
//void process_table_joint(PT(EggTable) parent, FCDSceneNode* node);
void process_extra(PT(EggGroup) group, const FCDExtra* extra);
void process_node(EggGroupNode *parent, const FCDSceneNode* node, bool forced = false);
void process_instance(EggGroup *parent, const FCDEntityInstance* instance);
void process_mesh(EggGroup *parent, const FCDGeometryMesh* mesh,
DaeMaterials *materials, DaeCharacter *character = NULL);
void process_spline(EggGroup *parent, const string group_name, FCDGeometrySpline* geometry_spline);
void process_spline(EggGroup *parent, const FCDSpline* spline);
void process_controller(EggGroup *parent, const FCDControllerInstance* instance);
void process_extra(EggGroup *group, const FCDExtra* extra);
static LMatrix4d convert_matrix(const FMMatrix44& matrix);
void apply_transform(const PT(EggGroup) to, const FCDTransform* from);
void apply_transform(EggGroup *to, const FCDTransform* from);
friend class DaeCharacter;
};

View File

@ -22,6 +22,13 @@
#error You must include pre_fcollada_include.h before including FCollada.h!
#endif
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <winsock2.h>
#endif
// FCollada expects LINUX to be defined on linux
#ifdef IS_LINUX
#ifndef LINUX

View File

@ -26,6 +26,7 @@ DAEToEgg::
DAEToEgg():
SomethingToEgg("COLLADA", ".dae")
{
add_animation_options();
add_units_options();
add_normals_options();
add_transform_options();
@ -42,6 +43,7 @@ DAEToEgg():
("This program converts .dae files (COLLADA Digital Asset Exchange) to .egg.");
_coordinate_system = CS_yup_right;
_animation_convert = AC_both;
}
////////////////////////////////////////////////////////////////////
@ -51,6 +53,12 @@ DAEToEgg():
////////////////////////////////////////////////////////////////////
void DAEToEgg::
run() {
if (_animation_convert != AC_both && _animation_convert != AC_none &&
_animation_convert != AC_chan && _animation_convert != AC_model) {
cerr << "Unsupported animation convert option.\n";
exit(1);
}
nout << "Reading " << _input_filename << "\n";
_data->set_coordinate_system(_coordinate_system);