remove ancient program
This commit is contained in:
parent
70db0829ff
commit
e9c0e4b267
|
|
@ -1,56 +0,0 @@
|
|||
#define USE_PACKAGES fftw
|
||||
|
||||
#begin bin_target
|
||||
#define TARGET stitch-command
|
||||
#define LOCAL_LIBS \
|
||||
stitchbase
|
||||
#define OTHER_LIBS \
|
||||
progbase pandatoolbase converter \
|
||||
pnmimage:c mathutil:c linmath:c putil:c panda:m \
|
||||
express:c pandabase:c pandaexpress:m \
|
||||
dtoolutil:c dconfig:c dtoolbase:c dtoolconfig:m dtool:m \
|
||||
pystub
|
||||
|
||||
#define SOURCES \
|
||||
stitchCommandProgram.cxx stitchCommandProgram.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
|
||||
#end bin_target
|
||||
|
||||
#begin bin_target
|
||||
#define TARGET stitch-image
|
||||
#define LOCAL_LIBS \
|
||||
stitchbase
|
||||
#define OTHER_LIBS \
|
||||
progbase pandatoolbase converter \
|
||||
pnmimagetypes:c pnmimage:c linmath:c putil:c panda:m \
|
||||
express:c pandabase:c pandaexpress:m \
|
||||
dtoolutil:c dconfig:c dtoolbase:c dtoolconfig:m dtool:m \
|
||||
pystub
|
||||
|
||||
#define SOURCES \
|
||||
stitchImageProgram.cxx stitchImageProgram.h
|
||||
|
||||
#end bin_target
|
||||
|
||||
#begin bin_target
|
||||
// Temporarily commented out until we can bring this to new scene graph.
|
||||
#define BUILD_TARGET
|
||||
#define TARGET stitch-viewer
|
||||
#define LOCAL_LIBS \
|
||||
stitchviewer stitchbase
|
||||
#define OTHER_LIBS \
|
||||
progbase converter \
|
||||
device:c tform:c graph:c dgraph:c sgraph:c gobj:c sgattrib:c \
|
||||
event:c chancfg:c display:c sgraphutil:c light:c \
|
||||
pnmimagetypes:c pnmimage:c putil:c express:c pandabase:c \
|
||||
panda:m pandaexpress:m \
|
||||
dtoolutil:c dconfig:c dtoolbase:c dtoolconfig:m dtool:m \
|
||||
pystub
|
||||
|
||||
#define SOURCES \
|
||||
stitchViewerProgram.cxx stitchViewerProgram.h
|
||||
|
||||
#end bin_target
|
||||
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
// Filename: stitchCommandProgram.cxx
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchCommandProgram.h"
|
||||
#include "stitchImageCommandOutput.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCommandProgram::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchCommandProgram::
|
||||
StitchCommandProgram() {
|
||||
set_program_description
|
||||
("This program reads a stitch command file, performs processing on the "
|
||||
"file (such as alignment of images according to points marked within a "
|
||||
"stitch region), and writes the resulting command file to standard "
|
||||
"output. It does not actually operate on any images.\n"
|
||||
|
||||
"The primary function of this program is to test the syntax of a "
|
||||
"command file, or to preprocess a command file so that a series of "
|
||||
"images (for instance, frames of a movie) may be easily transformed "
|
||||
"by the exact same operation.");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCommandProgram::run
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchCommandProgram::
|
||||
run() {
|
||||
StitchImageCommandOutput outputter;
|
||||
_command_file.process(outputter);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
StitchCommandProgram prog;
|
||||
prog.parse_command_line(argc, argv);
|
||||
prog.run();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// Filename: stitchCommandProgram.h
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHCOMMANDPROGRAM_H
|
||||
#define STITCHCOMMANDPROGRAM_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "stitchCommandReader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchCommandProgram
|
||||
// Description : A program to read a stitch command file, process it
|
||||
// without actually manipulating any images, and write
|
||||
// the processed command file out.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchCommandProgram : public StitchCommandReader {
|
||||
public:
|
||||
StitchCommandProgram();
|
||||
|
||||
void run();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
// Filename: stitchImageProgram.cxx
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchImageProgram.h"
|
||||
#include "stitchImageRasterizer.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageProgram::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchImageProgram::
|
||||
StitchImageProgram() {
|
||||
set_program_description
|
||||
("This program reads a stitch command file, performs whatever processing "
|
||||
"is indicated by the command file, and generates an output image for "
|
||||
"each image listed in an output_image section.\n"
|
||||
|
||||
"The images are generated internally using a CPU-based rasterization "
|
||||
"algorithm (no graphics hardware is used).");
|
||||
|
||||
add_option
|
||||
("f", "factor", 0,
|
||||
"Scale the output images internally by the indicated factor in each "
|
||||
"dimension while generating them, and then reduce them to their final "
|
||||
"size on output. This provides a simple mechanism for filtering "
|
||||
"the result. The default is 1.0, or unfiltered, which runs relatively "
|
||||
"quickly but can give highly aliased results; specifying a larger number "
|
||||
"increases quality but also increases runtime and memory requirements "
|
||||
"roughly by the square of factor. Usually 2 or 3 provide satisfactory "
|
||||
"results.",
|
||||
&StitchImageProgram::dispatch_double, NULL, &_filter_factor);
|
||||
|
||||
add_option
|
||||
("o", "name", 0,
|
||||
"Generates only the named output image. This may be repeated to "
|
||||
"generate multiple images in one run. If omitted, all output images "
|
||||
"in the file are generated. The name may include filename globbing "
|
||||
"symbols, e.g. 'grid*'. You should quote such names to protect them "
|
||||
"from shell expansion.",
|
||||
&StitchImageProgram::dispatch_output_name);
|
||||
|
||||
add_option
|
||||
("i", "name", 0,
|
||||
"Generates only the named input image or images, as above.",
|
||||
&StitchImageProgram::dispatch_input_name);
|
||||
|
||||
add_option
|
||||
("s", "xsize,ysize", 0,
|
||||
"Generates the output image(s) at the specified size, rather than the "
|
||||
"size specified within the .st file.",
|
||||
&StitchImageProgram::dispatch_int_pair, &_got_output_size, &_output_size);
|
||||
|
||||
_filter_factor = 1.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageProgram::run
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageProgram::
|
||||
run() {
|
||||
if (_got_output_size) {
|
||||
_outputter.set_output_size(_output_size[0], _output_size[1]);
|
||||
}
|
||||
_outputter.set_filter_factor(_filter_factor);
|
||||
_command_file.process(_outputter);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageProgram::dispatch_output_name
|
||||
// Access: Protected, Static
|
||||
// Description: Dispatch function for an output image name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchImageProgram::
|
||||
dispatch_output_name(ProgramBase *self, const string &opt,
|
||||
const string &arg, void *) {
|
||||
StitchImageProgram *prog = (StitchImageProgram *)self;
|
||||
prog->_outputter.add_output_name(arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageProgram::dispatch_input_name
|
||||
// Access: Protected, Static
|
||||
// Description: Dispatch function for an input image name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchImageProgram::
|
||||
dispatch_input_name(ProgramBase *self, const string &opt,
|
||||
const string &arg, void *) {
|
||||
StitchImageProgram *prog = (StitchImageProgram *)self;
|
||||
prog->_outputter.add_input_name(arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
StitchImageProgram prog;
|
||||
prog.parse_command_line(argc, argv);
|
||||
prog.run();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
// Filename: stitchImageProgram.h
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHIMAGEPROGRAM_H
|
||||
#define STITCHIMAGEPROGRAM_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "stitchCommandReader.h"
|
||||
#include "stitchImageRasterizer.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchImageProgram
|
||||
// Description : A program to read a stitch command file, perform the
|
||||
// image manipulations in the CPU, and write output
|
||||
// images for each processed image.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchImageProgram : public StitchCommandReader {
|
||||
public:
|
||||
StitchImageProgram();
|
||||
|
||||
void run();
|
||||
|
||||
protected:
|
||||
static bool dispatch_output_name(ProgramBase *self, const string &opt,
|
||||
const string &arg, void *);
|
||||
static bool dispatch_input_name(ProgramBase *self, const string &opt,
|
||||
const string &arg, void *);
|
||||
|
||||
private:
|
||||
double _filter_factor;
|
||||
bool _got_output_size;
|
||||
int _output_size[2];
|
||||
|
||||
StitchImageRasterizer _outputter;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// Filename: stitchViewerProgram.cxx
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchViewerProgram.h"
|
||||
#include "stitchImageConverter.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchViewerProgram::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchViewerProgram::
|
||||
StitchViewerProgram() {
|
||||
set_program_description
|
||||
("This program reads a stitch command file, performs whatever processing "
|
||||
"is indicated by the command file, and draws a 3-d representation of "
|
||||
"all of the input images described in the command file. The output "
|
||||
"images are ignored.\n"
|
||||
|
||||
"This program is primarily useful for showing the 3-d relationship "
|
||||
"between images that has been inferred from the stitch command file.");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchViewerProgram::run
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchViewerProgram::
|
||||
run() {
|
||||
StitchImageVisualizer outputter;
|
||||
_command_file.process(outputter);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
StitchViewerProgram prog;
|
||||
prog.parse_command_line(argc, argv);
|
||||
prog.run();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// Filename: stitchViewerProgram.h
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHVIEWERPROGRAM_H
|
||||
#define STITCHVIEWERPROGRAM_H
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
|
||||
#include "stitchCommandReader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchViewerProgram
|
||||
// Description : A program to read a stitch command file, and draw a
|
||||
// 3-d representation of all of the input images.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchViewerProgram : public StitchCommandReader {
|
||||
public:
|
||||
StitchViewerProgram();
|
||||
|
||||
void run();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#define YACC_PREFIX stitchyy
|
||||
#define LFLAGS -i
|
||||
|
||||
#begin ss_lib_target
|
||||
#define TARGET stitchbase
|
||||
#define LOCAL_LIBS pandaappbase
|
||||
#define OTHER_LIBS \
|
||||
progbase \
|
||||
putil:c express:c mathutil:c linmath:c pnmimage:c panda:m
|
||||
#define UNIX_SYS_LIBS \
|
||||
m
|
||||
|
||||
#define SOURCES \
|
||||
config_stitch.cxx config_stitch.h \
|
||||
fadeImagePool.I fadeImagePool.cxx fadeImagePool.h \
|
||||
fixedPoint.h \
|
||||
layeredImage.cxx layeredImage.h \
|
||||
morphGrid.cxx morphGrid.h stitchCommand.cxx stitchCommand.h \
|
||||
stitchCommandReader.cxx stitchCommandReader.h \
|
||||
stitchCylindricalLens.cxx stitchCylindricalLens.h stitchFile.cxx \
|
||||
stitchFile.h stitchFisheyeLens.cxx stitchFisheyeLens.h \
|
||||
stitchImage.cxx stitchImage.h stitchImageCommandOutput.cxx \
|
||||
stitchImageCommandOutput.h stitchImageOutputter.cxx \
|
||||
stitchImageOutputter.h stitchImageRasterizer.cxx \
|
||||
stitchImageRasterizer.h stitchLens.cxx stitchLens.h \
|
||||
stitchPSphereLens.cxx stitchPSphereLens.h stitchPerspectiveLens.cxx \
|
||||
stitchPerspectiveLens.h stitchPoint.cxx stitchPoint.h stitcher.cxx \
|
||||
stitcher.h triangle.cxx triangle.h triangleRasterizer.cxx \
|
||||
triangleRasterizer.h \
|
||||
stitchParserDefs.h stitchParser.yxx stitchLexerDefs.h stitchLexer.lxx \
|
||||
stitchCylindricalScreen.cxx stitchCylindricalScreen.h \
|
||||
stitchFlatScreen.cxx stitchFlatScreen.h \
|
||||
stitchMultiScreen.cxx stitchMultiScreen.h \
|
||||
stitchScreen.cxx stitchScreen.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
config_stitch.h \
|
||||
fadeImagePool.I fadeImagePool.h \
|
||||
fixedPoint.h layeredImage.h morphGrid.h stitchCommand.h \
|
||||
stitchCommandReader.h stitchCylindricalLens.h stitchFile.h \
|
||||
stitchFisheyeLens.h stitchImage.h stitchImageCommandOutput.h \
|
||||
stitchImageOutputter.h stitchImageRasterizer.h stitchLens.h \
|
||||
stitchLexerDefs.h stitchPSphereLens.h stitchParser.h \
|
||||
stitchParserDefs.h stitchPerspectiveLens.h stitchPoint.h \
|
||||
stitcher.h triangle.h triangleRasterizer.h \
|
||||
stitchCylindricalScreen.h \
|
||||
stitchFlatScreen.h \
|
||||
stitchMultiScreen.h \
|
||||
stitchScreen.h
|
||||
|
||||
|
||||
#end ss_lib_target
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// Filename: config_stitch.cxx
|
||||
// Created by: drose (05Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_stitch.h"
|
||||
#include "stitchScreen.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_stitch);
|
||||
|
||||
ConfigureFn(config_stitch) {
|
||||
StitchScreen::init_type();
|
||||
}
|
||||
|
||||
string chan_cfg = config_stitch.GetString("chan-config", "single");
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// Filename: config_stitch.h
|
||||
// Created by: drose (05Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_STITCH_H
|
||||
#define CONFIG_STITCH_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
extern string chan_cfg;
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// Filename: fadeImagePool.I
|
||||
// Created by: drose (30Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FadeImagePool::get_image
|
||||
// Access: Public
|
||||
// Description: Returns a pointer to the fade image of the indicated
|
||||
// filename, scaled to the indicated size, or NULL if
|
||||
// the image cannot be loaded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const PNMImage *FadeImagePool::
|
||||
get_image(const Filename &filename, int x_size, int y_size) {
|
||||
return get_ptr()->ns_get_image(filename, x_size, y_size);
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
// Filename: fadeImagePool.cxx
|
||||
// Created by: drose (30Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "fadeImagePool.h"
|
||||
#include "pnmImage.h"
|
||||
|
||||
FadeImagePool *FadeImagePool::_global_ptr = (FadeImagePool *)NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FadeImagePool::Constructor
|
||||
// Access: Private
|
||||
// Description: The constructor is never called explicitly; there is
|
||||
// only one FadeImagePool and it constructs itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FadeImagePool::
|
||||
FadeImagePool() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FadeImagePool::ns_get_image
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of get_image(). This
|
||||
// loads up the image if it is not already, scales it to
|
||||
// the indicated size if it is not already, and returns
|
||||
// it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const PNMImage *FadeImagePool::
|
||||
ns_get_image(const Filename &filename, int x_size, int y_size) {
|
||||
Images::iterator ii = _images.find(filename);
|
||||
if (ii == _images.end()) {
|
||||
// The image has not yet been loaded. Load it.
|
||||
cerr << "Reading fade image " << filename << "\n";
|
||||
PNMImage *image = new PNMImage(filename);
|
||||
if (!image->is_valid()) {
|
||||
cerr << "Unable to read fade image.\n";
|
||||
delete image;
|
||||
return (const PNMImage *)NULL;
|
||||
}
|
||||
|
||||
// Make sure it's a grayscale image. This will save a bit of time
|
||||
// later.
|
||||
image->set_color_type(PNMImage::CT_grayscale);
|
||||
|
||||
ii = _images.insert(Images::value_type(filename, ImageSizes())).first;
|
||||
(*ii).second.push_back(image);
|
||||
}
|
||||
|
||||
// Now see if we have a fade image of the requested size.
|
||||
ImageSizes &sizes = (*ii).second;
|
||||
ImageSizes::iterator si;
|
||||
for (si = sizes.begin(); si != sizes.end(); ++si) {
|
||||
PNMImage *image = (*si);
|
||||
if (image->get_x_size() == x_size && image->get_y_size() == y_size) {
|
||||
// Here's one that suits!
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
// None of our images were of a suitable size, so make one.
|
||||
nassertr(!sizes.empty(), NULL);
|
||||
|
||||
PNMImage *orig_image = sizes.front();
|
||||
cerr << "Resizing fade image to " << x_size << " by " << y_size << "\n";
|
||||
PNMImage *resized_image =
|
||||
new PNMImage(x_size, y_size, PNMImage::CT_grayscale,
|
||||
orig_image->get_maxval());
|
||||
resized_image->quick_filter_from(*orig_image);
|
||||
|
||||
sizes.push_back(resized_image);
|
||||
return resized_image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: FadeImagePool::get_ptr
|
||||
// Access: Private, Static
|
||||
// Description: Returns the global FadeImagePool pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
FadeImagePool *FadeImagePool::
|
||||
get_ptr() {
|
||||
if (_global_ptr == (FadeImagePool *)NULL) {
|
||||
_global_ptr = new FadeImagePool;
|
||||
}
|
||||
return _global_ptr;
|
||||
}
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
// Filename: fadeImagePool.h
|
||||
// Created by: drose (30Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FADEIMAGEPOOL_H
|
||||
#define FADEIMAGEPOOL_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "filename.h"
|
||||
#include "pvector.h"
|
||||
#include "pmap.h"
|
||||
|
||||
class PNMImage;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : FadeImagePool
|
||||
// Description : This maintains a list of images loaded up as "fade"
|
||||
// images--that is, grayscale images whose only purpose
|
||||
// is to adjust the source image to dark at the edges.
|
||||
// It guarantees that each named image is only loaded
|
||||
// once.
|
||||
//
|
||||
// Images are never freed from this pool. The
|
||||
// assumption is that you have plenty of RAM for dealing
|
||||
// with images.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class FadeImagePool {
|
||||
public:
|
||||
INLINE static const PNMImage *get_image(const Filename &filename,
|
||||
int x_size, int y_size);
|
||||
|
||||
private:
|
||||
FadeImagePool();
|
||||
|
||||
const PNMImage *ns_get_image(const Filename &filename, int x_size, int y_size);
|
||||
|
||||
static FadeImagePool *get_ptr();
|
||||
|
||||
typedef pvector<PNMImage *> ImageSizes;
|
||||
typedef pmap<Filename, ImageSizes> Images;
|
||||
Images _images;
|
||||
|
||||
static FadeImagePool *_global_ptr;
|
||||
};
|
||||
|
||||
#include "fadeImagePool.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// Filename: fixedPoint.h
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FIXEDPOINT_H
|
||||
#define FIXEDPOINT_H
|
||||
|
||||
// Simple fixed-point arithmetic definitions, for support of
|
||||
// TriangleRasterizer. Totally ripped off from Mesa.
|
||||
|
||||
typedef int FixedPoint;
|
||||
|
||||
#define FIXED_ONE 0x00000800
|
||||
#define FIXED_HALF 0x00000400
|
||||
#define FIXED_FRAC_MASK 0x000007FF
|
||||
#define FIXED_INT_MASK (~FIXED_FRAC_MASK)
|
||||
#define FIXED_EPSILON 1
|
||||
#define FIXED_SCALE 2048.0
|
||||
#define FIXED_SHIFT 11
|
||||
#define FloatToFixed(X) ((FixedPoint) ((X) * FIXED_SCALE))
|
||||
#define IntToFixed(I) ((I) << FIXED_SHIFT)
|
||||
#define FixedToInt(X) ((X) >> FIXED_SHIFT)
|
||||
#define FixedToUns(X) (((unsigned int)(X)) >> 11)
|
||||
#define FixedCeil(X) (((X) + FIXED_ONE - FIXED_EPSILON) & FIXED_INT_MASK)
|
||||
#define FixedFloor(X) ((X) & FIXED_INT_MASK)
|
||||
/* 0.00048828125 = 1/FIXED_SCALE */
|
||||
#define FixedToFloat(X) ((X) * 0.00048828125)
|
||||
#define PosFloatToFixed(X) FloatToFixed(X)
|
||||
#define SignedFloatToFixed(X) FloatToFixed(X)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,763 +0,0 @@
|
|||
// Filename: layeredImage.cxx
|
||||
// Created by: drose (29Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "layeredImage.h"
|
||||
|
||||
#include "pnmImage.h"
|
||||
#include "datagram.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
// Constants taken from various header files in Gimp.
|
||||
#define TILE_WIDTH 64
|
||||
#define TILE_HEIGHT 64
|
||||
|
||||
#define RGB_GIMAGE 0
|
||||
#define RGBA_GIMAGE 1
|
||||
|
||||
LayeredImage::TileManager::
|
||||
TileManager(const PNMImage *image, int channel) :
|
||||
_data(image), _channel(channel)
|
||||
{
|
||||
int width = image->get_x_size();
|
||||
int height = image->get_y_size();
|
||||
|
||||
while (width > TILE_WIDTH || height > TILE_WIDTH) {
|
||||
_levels.push_back(Level());
|
||||
Level &l = _levels.back();
|
||||
|
||||
l._width = width;
|
||||
l._height = height;
|
||||
l._ntile_rows = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
|
||||
l._ntile_cols = (width + TILE_WIDTH - 1) / TILE_WIDTH;
|
||||
|
||||
width /= 2;
|
||||
height /= 2;
|
||||
}
|
||||
|
||||
_levels.push_back(Level());
|
||||
Level &l = _levels.back();
|
||||
|
||||
l._width = width;
|
||||
l._height = height;
|
||||
l._ntile_rows = (height + TILE_HEIGHT - 1) / TILE_HEIGHT;
|
||||
l._ntile_cols = (width + TILE_WIDTH - 1) / TILE_WIDTH;
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_nlevels() const {
|
||||
return _levels.size();
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_level_width(int level) const {
|
||||
assert(level >= 0 && level < (int)_levels.size());
|
||||
return _levels[level]._width;
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_level_height(int level) const {
|
||||
assert(level >= 0 && level < (int)_levels.size());
|
||||
return _levels[level]._height;
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_ntiles(int level) const {
|
||||
assert(level >= 0 && level < (int)_levels.size());
|
||||
return _levels[level]._ntile_rows * _levels[level]._ntile_cols;
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_tile_left(int level, int tile) const {
|
||||
// int ntile_rows = _levels[level]._ntile_rows;
|
||||
int ntile_cols = _levels[level]._ntile_cols;
|
||||
|
||||
// int r = tile / ntile_cols;
|
||||
int c = tile % ntile_cols;
|
||||
return c * TILE_WIDTH;
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_tile_top(int level, int tile) const {
|
||||
// int ntile_rows = _levels[level]._ntile_rows;
|
||||
int ntile_cols = _levels[level]._ntile_cols;
|
||||
|
||||
int r = tile / ntile_cols;
|
||||
// int c = tile % ntile_cols;
|
||||
return r * TILE_HEIGHT;
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_tile_width(int level, int tile) const {
|
||||
return min(TILE_WIDTH, _data->get_x_size() - get_tile_left(level, tile));
|
||||
}
|
||||
|
||||
int LayeredImage::TileManager::
|
||||
get_tile_height(int level, int tile) const {
|
||||
return min(TILE_HEIGHT, _data->get_y_size() - get_tile_top(level, tile));
|
||||
}
|
||||
|
||||
// Trims off the invisible (alpha-0) border around the layer. Returns
|
||||
// true if there is anything left, false if the layer would be empty.
|
||||
bool LayeredImage::Layer::
|
||||
trim() {
|
||||
assert(_data != NULL);
|
||||
if (_data->has_alpha()) {
|
||||
int xsize = _data->get_x_size();
|
||||
int ysize = _data->get_y_size();
|
||||
|
||||
int top = xsize - 1;
|
||||
int left = ysize - 1;
|
||||
int bottom = 0;
|
||||
int right = 0;
|
||||
|
||||
for (int y = 0; y < ysize; y++) {
|
||||
for (int x = 0; x < xsize; x++) {
|
||||
if (_data->get_alpha_val(x, y) != 0) {
|
||||
top = min(top, y);
|
||||
left = min(left, x);
|
||||
bottom = max(bottom, y);
|
||||
right = max(right, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (top > bottom || left > right) {
|
||||
// The layer is completely empty.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (top > 0 || left > 0 || bottom < ysize - 1 || right < xsize - 1) {
|
||||
xsize = right - left + 1;
|
||||
ysize = bottom - top + 1;
|
||||
PNMImage *sub = new PNMImage(xsize, ysize, 4);
|
||||
sub->copy_sub_image(*_data, 0, 0, left, top);
|
||||
delete _data;
|
||||
_data = sub;
|
||||
_offset[0] += left;
|
||||
_offset[1] += top;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LayeredImage::
|
||||
LayeredImage(int xsize, int ysize) :
|
||||
_xsize(xsize), _ysize(ysize) {
|
||||
}
|
||||
|
||||
LayeredImage::
|
||||
~LayeredImage() {
|
||||
Layers::const_iterator li;
|
||||
for (li = _layers.begin(); li != _layers.end(); ++li) {
|
||||
delete (*li)._data;
|
||||
}
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
add_layer(const string &name, const LVector2d &offset,
|
||||
PNMImage *data) {
|
||||
_layers.push_back(Layer());
|
||||
Layer &l = _layers.back();
|
||||
|
||||
l._name = name;
|
||||
l._offset = offset;
|
||||
l._data = data;
|
||||
|
||||
if (!l.trim()) {
|
||||
// If trimming the layer reveals that it is empty, delete it.
|
||||
delete l._data;
|
||||
_layers.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool LayeredImage::
|
||||
write_file(const Filename &filename) {
|
||||
ofstream out(filename.c_str());
|
||||
|
||||
// Maybe in the future, if we support more than one kind of file
|
||||
// here, we'll decide based on the filename extension which kind to
|
||||
// write out.
|
||||
|
||||
return write_xcf(out);
|
||||
}
|
||||
|
||||
bool LayeredImage::
|
||||
write_xcf(ostream &out) {
|
||||
_out = &out;
|
||||
_pos = 0;
|
||||
|
||||
// Write out the version tag
|
||||
static const int version_tag_len = 14;
|
||||
int8_t version_tag[version_tag_len];
|
||||
memset(version_tag, 0, version_tag_len);
|
||||
strcpy((char *)version_tag, "gimp xcf file");
|
||||
xcf_write_int8(version_tag, version_tag_len);
|
||||
|
||||
// Write out the width, height, and type.
|
||||
int32_t width = _xsize;
|
||||
int32_t height = _ysize;
|
||||
int32_t base_type = RGB_GIMAGE;
|
||||
xcf_write_int32(&width, 1);
|
||||
xcf_write_int32(&height, 1);
|
||||
xcf_write_int32(&base_type, 1);
|
||||
|
||||
xcf_save_image_props();
|
||||
|
||||
// Save the current file position; we'll return here to place the
|
||||
// layer offset information.
|
||||
int saved_pos = _pos;
|
||||
|
||||
int nlayers = _layers.size();
|
||||
int nchannels = 0;
|
||||
|
||||
// Seek to after the offset lists.
|
||||
xcf_seek_pos(_pos + (nlayers + nchannels + 2) * 4);
|
||||
|
||||
// Write out each layer. Since the layers were added to the
|
||||
// LayeredImage object from the bottom up (to me, the intuitive
|
||||
// order), and since they are stored in the XCF file from the top
|
||||
// down, we must reverse the order here.
|
||||
Layers::reverse_iterator li;
|
||||
for (li = _layers.rbegin(); li != _layers.rend(); ++li) {
|
||||
int32_t offset = _pos;
|
||||
xcf_save_layer(*li);
|
||||
|
||||
// Go back to write this layer offset.
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
saved_pos = _pos;
|
||||
|
||||
xcf_seek_end();
|
||||
}
|
||||
|
||||
// Write out '0' offset to indicate the end of the layer offsets.
|
||||
int32_t offset = 0;
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
saved_pos = _pos;
|
||||
xcf_seek_end();
|
||||
|
||||
/*
|
||||
No need to explicitly write out the channels.
|
||||
|
||||
// Write out each channel.
|
||||
static const char *channel_name[3] = { "red", "green", "blue" };
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// save the start offset of where we are writing
|
||||
// out the next channel.
|
||||
int32_t offset = _pos;
|
||||
|
||||
// write out the channel.
|
||||
xcf_save_channel(channel_name[i], _layers.front()._data, i);
|
||||
|
||||
// seek back to where we are to write out the next
|
||||
// channel offset and write it out.
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
|
||||
// increment the location we are to write out the
|
||||
// next offset.
|
||||
saved_pos = _pos;
|
||||
|
||||
// seek to the end of the file which is where
|
||||
// we will write out the next channel.
|
||||
xcf_seek_end();
|
||||
}
|
||||
*/
|
||||
|
||||
// Write out '0' offset to indicate the end of the channel offsets.
|
||||
offset = 0;
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
saved_pos = _pos;
|
||||
xcf_seek_end();
|
||||
|
||||
return !_out->fail();
|
||||
}
|
||||
|
||||
int LayeredImage::
|
||||
xcf_write_int8(const int8_t *data, int num) {
|
||||
_out->write((const char *)data, num);
|
||||
return _pos += num;
|
||||
}
|
||||
|
||||
int LayeredImage::
|
||||
xcf_write_int32(const int32_t *data, int num) {
|
||||
// We need to write a bunch of big-endian int32's.
|
||||
Datagram dg;
|
||||
for (int i = 0; i < num; i++) {
|
||||
dg.add_be_int32(data[i]);
|
||||
}
|
||||
_out->write((const char *)dg.get_data(), dg.get_length());
|
||||
return _pos += dg.get_length();
|
||||
}
|
||||
|
||||
int LayeredImage::
|
||||
xcf_write_string(const string &str) {
|
||||
int32_t size = (int32_t)str.size() + 1;
|
||||
if (str.empty()) {
|
||||
size = 0;
|
||||
}
|
||||
xcf_write_int32(&size, 1);
|
||||
return xcf_write_int8((const int8_t *)str.c_str(), size);
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_image_props() {
|
||||
xcf_save_prop(PROP_END);
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_layer_props(const LayeredImage::Layer &layer) {
|
||||
if (&layer == &_layers.front()) {
|
||||
xcf_save_prop(PROP_ACTIVE_LAYER);
|
||||
}
|
||||
xcf_save_prop(PROP_OPACITY, 255);
|
||||
xcf_save_prop(PROP_VISIBLE, 1);
|
||||
xcf_save_prop(PROP_LINKED, 0);
|
||||
xcf_save_prop(PROP_PRESERVE_TRANSPARENCY, 0);
|
||||
xcf_save_prop(PROP_APPLY_MASK, 1);
|
||||
xcf_save_prop(PROP_EDIT_MASK, 0);
|
||||
xcf_save_prop(PROP_SHOW_MASK, 0);
|
||||
xcf_save_prop(PROP_MODE, 0);
|
||||
|
||||
xcf_save_prop(PROP_OFFSETS,
|
||||
(int32_t)layer._offset[0],
|
||||
(int32_t)layer._offset[1]);
|
||||
xcf_save_prop(PROP_END);
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_channel_props() {
|
||||
xcf_save_prop(PROP_OPACITY, 255);
|
||||
xcf_save_prop(PROP_VISIBLE, 1);
|
||||
xcf_save_prop(PROP_SHOW_MASKED, 0);
|
||||
// xcf_save_prop(PROP_COLOR, channel->col);
|
||||
|
||||
xcf_save_prop(PROP_END);
|
||||
}
|
||||
|
||||
// This odd function is lifted from Gimp's xcf.c.
|
||||
void LayeredImage::
|
||||
xcf_save_prop(LayeredImage::PropType prop_type, ...) {
|
||||
int32_t size;
|
||||
va_list args;
|
||||
|
||||
va_start(args, prop_type);
|
||||
|
||||
switch (prop_type) {
|
||||
case PROP_END:
|
||||
size = 0;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
break;
|
||||
case PROP_COLORMAP:
|
||||
{
|
||||
int32_t ncolors;
|
||||
int8_t *colors;
|
||||
|
||||
ncolors = va_arg(args, int32_t);
|
||||
colors = va_arg(args, int8_t*);
|
||||
size = 4 + ncolors;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&ncolors, 1);
|
||||
xcf_write_int8(colors, ncolors * 3);
|
||||
}
|
||||
break;
|
||||
case PROP_ACTIVE_LAYER:
|
||||
case PROP_ACTIVE_CHANNEL:
|
||||
case PROP_SELECTION:
|
||||
size = 0;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
break;
|
||||
case PROP_FLOATING_SELECTION:
|
||||
assert(false);
|
||||
break;
|
||||
case PROP_OPACITY:
|
||||
{
|
||||
int32_t opacity;
|
||||
|
||||
opacity = va_arg(args, int32_t);
|
||||
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32((int32_t*)&opacity, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_MODE:
|
||||
{
|
||||
int32_t mode;
|
||||
|
||||
mode = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32((int32_t*)&mode, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
{
|
||||
int32_t visible;
|
||||
|
||||
visible = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&visible, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_LINKED:
|
||||
{
|
||||
int32_t linked;
|
||||
|
||||
linked = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&linked, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_PRESERVE_TRANSPARENCY:
|
||||
{
|
||||
int32_t preserve_trans;
|
||||
|
||||
preserve_trans = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&preserve_trans, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_APPLY_MASK:
|
||||
{
|
||||
int32_t apply_mask;
|
||||
|
||||
apply_mask = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&apply_mask, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_EDIT_MASK:
|
||||
{
|
||||
int32_t edit_mask;
|
||||
|
||||
edit_mask = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&edit_mask, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_SHOW_MASK:
|
||||
{
|
||||
int32_t show_mask;
|
||||
|
||||
show_mask = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&show_mask, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_SHOW_MASKED:
|
||||
{
|
||||
int32_t show_masked;
|
||||
|
||||
show_masked = va_arg(args, int32_t);
|
||||
size = 4;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32(&show_masked, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_OFFSETS:
|
||||
{
|
||||
int32_t offsets[2];
|
||||
|
||||
offsets[0] = va_arg(args, int32_t);
|
||||
offsets[1] = va_arg(args, int32_t);
|
||||
size = 8;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int32((int32_t*) offsets, 2);
|
||||
}
|
||||
break;
|
||||
case PROP_COLOR:
|
||||
{
|
||||
int8_t *color;
|
||||
|
||||
color = va_arg(args, int8_t*);
|
||||
size = 3;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int8(color, 3);
|
||||
}
|
||||
break;
|
||||
case PROP_COMPRESSION:
|
||||
{
|
||||
int8_t compression;
|
||||
|
||||
compression =(int8_t) va_arg(args, int32_t);
|
||||
size = 1;
|
||||
|
||||
xcf_write_int32((int32_t*)&prop_type, 1);
|
||||
xcf_write_int32(&size, 1);
|
||||
xcf_write_int8(&compression, 1);
|
||||
}
|
||||
break;
|
||||
case PROP_GUIDES:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_layer(const LayeredImage::Layer &layer) {
|
||||
// write out the width, height and image type information for the layer
|
||||
int32_t width = layer._data->get_x_size();
|
||||
int32_t height = layer._data->get_y_size();
|
||||
int32_t type = RGBA_GIMAGE;
|
||||
xcf_write_int32((int32_t*)&width, 1);
|
||||
xcf_write_int32((int32_t*)&height, 1);
|
||||
xcf_write_int32((int32_t*)&type, 1);
|
||||
|
||||
// write out the layer's name
|
||||
xcf_write_string(layer._name);
|
||||
|
||||
// write out the layer properties
|
||||
xcf_save_layer_props(layer);
|
||||
|
||||
// save the current position which is where the hierarchy offset
|
||||
// will be stored.
|
||||
int saved_pos = _pos;
|
||||
|
||||
// write out the layer tile hierarchy
|
||||
xcf_seek_pos(_pos + 8);
|
||||
int32_t offset = _pos;
|
||||
|
||||
xcf_save_hierarchy(layer._data, -1);
|
||||
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
saved_pos = _pos;
|
||||
|
||||
// write out the layer mask. We write out the alpha channel here
|
||||
// instead of as a proper alpha channel, since it's more convenient
|
||||
// in The Gimp to edit the alpha channel in the layer mask.
|
||||
|
||||
if (layer._data->has_alpha()) {
|
||||
xcf_seek_end();
|
||||
offset = _pos;
|
||||
xcf_save_channel("mask", layer._data, 3);
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_channel(const string &name, const PNMImage *image, int channel) {
|
||||
int32_t saved_pos;
|
||||
int32_t offset;
|
||||
|
||||
// write out the width and height information for the channel
|
||||
int32_t width = image->get_x_size();
|
||||
int32_t height = image->get_y_size();
|
||||
xcf_write_int32(&width, 1);
|
||||
xcf_write_int32(&height, 1);
|
||||
|
||||
// write out the channels name
|
||||
xcf_write_string(name);
|
||||
|
||||
// write out the channel properties
|
||||
xcf_save_channel_props();
|
||||
|
||||
// save the current position which is where the hierarchy offset
|
||||
// will be stored.
|
||||
saved_pos = _pos;
|
||||
|
||||
/* write out the channel tile hierarchy */
|
||||
xcf_seek_pos(_pos + 4);
|
||||
offset = _pos;
|
||||
|
||||
xcf_save_hierarchy(image, channel);
|
||||
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
saved_pos = _pos;
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_hierarchy(const PNMImage *image, int channel) {
|
||||
int32_t width = image->get_x_size();
|
||||
int32_t height = image->get_y_size();
|
||||
int32_t bpp = (channel < 0) ? 4 : 1;
|
||||
xcf_write_int32(&width, 1);
|
||||
xcf_write_int32(&height, 1);
|
||||
xcf_write_int32(&bpp, 1);
|
||||
|
||||
int saved_pos = _pos;
|
||||
|
||||
TileManager tm(image, channel);
|
||||
int nlevels = tm.get_nlevels();
|
||||
|
||||
xcf_seek_pos(_pos + (nlevels + 1) * 4);
|
||||
|
||||
for (int i = 0; i < nlevels; i++) {
|
||||
// save the start offset of where we are writing
|
||||
// out the next level.
|
||||
int32_t offset = _pos;
|
||||
|
||||
// write out the level.
|
||||
xcf_save_level(tm, i);
|
||||
|
||||
// seek back to where we are to write out the next
|
||||
// level offset and write it out.
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
|
||||
// increment the location we are to write out the
|
||||
// next offset.
|
||||
saved_pos = _pos;
|
||||
|
||||
// seek to the end of the file which is where
|
||||
// we will write out the next level.
|
||||
xcf_seek_end();
|
||||
}
|
||||
|
||||
// write out a '0' offset position to indicate the end
|
||||
// of the level offsets.
|
||||
int32_t offset = 0;
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_level(const LayeredImage::TileManager &tm, int level) {
|
||||
// write out the width and height information for the channel
|
||||
int32_t width = tm.get_level_width(level);
|
||||
int32_t height = tm.get_level_height(level);
|
||||
xcf_write_int32(&width, 1);
|
||||
xcf_write_int32(&height, 1);
|
||||
|
||||
int saved_pos = _pos;
|
||||
|
||||
int ntiles = tm.get_ntiles(level);
|
||||
xcf_seek_pos(_pos + (ntiles + 1) * 4);
|
||||
|
||||
for (int i = 0; i < ntiles; i++) {
|
||||
// save the start offset of where we are writing
|
||||
// out the next tile.
|
||||
int32_t offset = _pos;
|
||||
|
||||
// write out the tile.
|
||||
xcf_save_tile(tm, level, i);
|
||||
|
||||
// seek back to where we are to write out the next
|
||||
// tile offset and write it out.
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
|
||||
// increment the location we are to write out the
|
||||
// next offset.
|
||||
saved_pos = _pos;
|
||||
|
||||
xcf_seek_end();
|
||||
}
|
||||
|
||||
// write out a '0' offset position to indicate the end
|
||||
// of the level offsets.
|
||||
int32_t offset = 0;
|
||||
xcf_seek_pos(saved_pos);
|
||||
xcf_write_int32(&offset, 1);
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_save_tile(const LayeredImage::TileManager &tm, int level, int tile) {
|
||||
int xoff = tm.get_tile_left(level, tile);
|
||||
int yoff = tm.get_tile_top(level, tile);
|
||||
int xsize = tm.get_tile_width(level, tile);
|
||||
int ysize = tm.get_tile_height(level, tile);
|
||||
|
||||
if (tm._channel < 0) {
|
||||
int size = xsize * ysize * 4;
|
||||
int8_t *array = new int8_t[size];
|
||||
int i = 0;
|
||||
for (int y = yoff; y < yoff + ysize; y++) {
|
||||
for (int x = xoff; x < xoff + xsize; x++) {
|
||||
array[i++] = tm._data->get_red_val(x, y);
|
||||
array[i++] = tm._data->get_green_val(x, y);
|
||||
array[i++] = tm._data->get_blue_val(x, y);
|
||||
array[i++] = -1;
|
||||
}
|
||||
}
|
||||
assert(i == size);
|
||||
xcf_write_int8(array, size);
|
||||
delete[] array;
|
||||
|
||||
} else {
|
||||
int size = xsize * ysize;
|
||||
int8_t *array = new int8_t[size];
|
||||
int i = 0;
|
||||
for (int y = yoff; y < yoff + ysize; y++) {
|
||||
for (int x = xoff; x < xoff + xsize; x++) {
|
||||
array[i++] = tm._data->get_channel_val(x, y, tm._channel);
|
||||
}
|
||||
}
|
||||
assert(i == size);
|
||||
xcf_write_int8(array, size);
|
||||
delete[] array;
|
||||
}
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_seek_pos(int to_pos) {
|
||||
_out->seekp(to_pos);
|
||||
_pos = to_pos;
|
||||
}
|
||||
|
||||
void LayeredImage::
|
||||
xcf_seek_end() {
|
||||
_out->seekp(0, ios::end);
|
||||
_pos = _out->tellp();
|
||||
}
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
// Filename: layeredImage.h
|
||||
// Created by: drose (29Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LAYEREDIMAGE_H
|
||||
#define LAYEREDIMAGE_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "luse.h"
|
||||
#include "filename.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
//#include <stdint.h>
|
||||
|
||||
class PNMImage;
|
||||
|
||||
class LayeredImage {
|
||||
public:
|
||||
typedef char int8_t;
|
||||
typedef long int32_t;
|
||||
|
||||
LayeredImage(int xsize, int ysize);
|
||||
~LayeredImage();
|
||||
|
||||
void add_layer(const string &name, const LVector2d &offset,
|
||||
PNMImage *data);
|
||||
|
||||
bool write_file(const Filename &filename);
|
||||
|
||||
bool write_xcf(ostream &out);
|
||||
|
||||
private:
|
||||
// XCF property types. From Gimp's xcf.c.
|
||||
enum PropType {
|
||||
PROP_END = 0,
|
||||
PROP_COLORMAP = 1,
|
||||
PROP_ACTIVE_LAYER = 2,
|
||||
PROP_ACTIVE_CHANNEL = 3,
|
||||
PROP_SELECTION = 4,
|
||||
PROP_FLOATING_SELECTION = 5,
|
||||
PROP_OPACITY = 6,
|
||||
PROP_MODE = 7,
|
||||
PROP_VISIBLE = 8,
|
||||
PROP_LINKED = 9,
|
||||
PROP_PRESERVE_TRANSPARENCY = 10,
|
||||
PROP_APPLY_MASK = 11,
|
||||
PROP_EDIT_MASK = 12,
|
||||
PROP_SHOW_MASK = 13,
|
||||
PROP_SHOW_MASKED = 14,
|
||||
PROP_OFFSETS = 15,
|
||||
PROP_COLOR = 16,
|
||||
PROP_COMPRESSION = 17,
|
||||
PROP_GUIDES = 18
|
||||
};
|
||||
|
||||
class Layer {
|
||||
public:
|
||||
bool trim();
|
||||
|
||||
string _name;
|
||||
LVector2d _offset;
|
||||
PNMImage *_data;
|
||||
};
|
||||
|
||||
class TileManager {
|
||||
public:
|
||||
TileManager(const PNMImage *image, int channel);
|
||||
int get_nlevels() const;
|
||||
int get_level_width(int level) const;
|
||||
int get_level_height(int level) const;
|
||||
int get_ntiles(int level) const;
|
||||
int get_tile_left(int level, int tile) const;
|
||||
int get_tile_top(int level, int tile) const;
|
||||
int get_tile_width(int level, int tile) const;
|
||||
int get_tile_height(int level, int tile) const;
|
||||
|
||||
const PNMImage *_data;
|
||||
int _channel;
|
||||
|
||||
private:
|
||||
class Level {
|
||||
public:
|
||||
int _width;
|
||||
int _height;
|
||||
int _ntile_rows;
|
||||
int _ntile_cols;
|
||||
};
|
||||
typedef vector<Level> Levels;
|
||||
Levels _levels;
|
||||
};
|
||||
|
||||
int xcf_write_int8(const int8_t *data, int num);
|
||||
int xcf_write_int32(const int32_t *data, int num);
|
||||
int xcf_write_string(const string &str);
|
||||
void xcf_save_image_props();
|
||||
void xcf_save_layer_props(const Layer &layer);
|
||||
void xcf_save_channel_props();
|
||||
void xcf_save_prop(PropType prop_type, ...);
|
||||
void xcf_save_layer(const Layer &layer);
|
||||
void xcf_save_channel(const string &name, const PNMImage *image,
|
||||
int channel);
|
||||
void xcf_save_hierarchy(const PNMImage *image, int channel);
|
||||
void xcf_save_level(const TileManager &tm, int level);
|
||||
void xcf_save_tile(const TileManager &tm, int level, int tile);
|
||||
void xcf_seek_pos(int to_pos);
|
||||
void xcf_seek_end();
|
||||
|
||||
typedef vector<Layer> Layers;
|
||||
Layers _layers;
|
||||
int _xsize;
|
||||
int _ysize;
|
||||
|
||||
ostream *_out;
|
||||
int _pos;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,485 +0,0 @@
|
|||
// Filename: morphGrid.cxx
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "morphGrid.h"
|
||||
#include "triangle.h"
|
||||
|
||||
#include "mathNumbers.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
MorphGrid::Vertex::
|
||||
Vertex(const LPoint2d &p) {
|
||||
for (int i = 0; i < (int)TT_num; i++) {
|
||||
_p[i] = p;
|
||||
}
|
||||
_alpha = 1.0;
|
||||
_over_another = false;
|
||||
|
||||
// -1 on the distance counter is a flag that the value hasn't yet
|
||||
// been computed.
|
||||
_dist_from_interior = -1;
|
||||
}
|
||||
|
||||
MorphGrid::Triangle::
|
||||
Triangle(Vertex *v0, Vertex *v1, Vertex *v2) {
|
||||
_v[0] = v0;
|
||||
_v[1] = v1;
|
||||
_v[2] = v2;
|
||||
}
|
||||
|
||||
bool MorphGrid::Triangle::
|
||||
contains_point(const LPoint2d &p, TableType from) const {
|
||||
if ((p[0] < _min_p[from][0] || p[0] > _max_p[from][0]) ||
|
||||
(p[1] < _min_p[from][1] || p[1] > _max_p[from][1])) {
|
||||
// Doesn't pass the minmax test.
|
||||
return false;
|
||||
}
|
||||
|
||||
return triangle_contains_point(p, _v[0]->_p[from], _v[1]->_p[from],
|
||||
_v[2]->_p[from]);
|
||||
}
|
||||
|
||||
LPoint2d MorphGrid::Triangle::
|
||||
morph_point(const LPoint2d &p, TableType from, TableType to) const {
|
||||
return (p * _inv[from]) * _mat[to];
|
||||
}
|
||||
|
||||
double MorphGrid::Triangle::
|
||||
get_alpha(const LPoint2d &p, TableType from) const {
|
||||
LPoint2d q = p * _inv[from];
|
||||
|
||||
// Now q is a point in a right triangle, where (0,1) is v0, (0,0) is
|
||||
// v1, and (1,0) is v2. Interpolate the appropriate alpha value
|
||||
// based on this coordinate system.
|
||||
|
||||
double alpha01 = (_v[0]->_alpha + q[1] * (_v[1]->_alpha - _v[0]->_alpha));
|
||||
return (alpha01 + q[0] * (_v[2]->_alpha - alpha01));
|
||||
}
|
||||
|
||||
void MorphGrid::Triangle::
|
||||
recompute() {
|
||||
for (int i = 0; i < (int)TT_num; i++) {
|
||||
for (int a = 0; a < 2; a++) {
|
||||
_min_p[i][a] = min(min(_v[0]->_p[i][a], _v[1]->_p[i][a]),
|
||||
_v[2]->_p[i][a]);
|
||||
_max_p[i][a] = max(max(_v[0]->_p[i][a], _v[1]->_p[i][a]),
|
||||
_v[2]->_p[i][a]);
|
||||
}
|
||||
|
||||
LPoint2d origin = _v[1]->_p[i];
|
||||
LVector2d yaxis = _v[0]->_p[i] - origin;
|
||||
LVector2d xaxis = _v[2]->_p[i] - origin;
|
||||
|
||||
_mat[i] = LMatrix3d(xaxis[0], xaxis[1], 0.0,
|
||||
yaxis[0], yaxis[1], 0.0,
|
||||
origin[0], origin[1], 1.0);
|
||||
|
||||
_inv[i] = invert(_mat[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MorphGrid::TriangleTree::
|
||||
TriangleTree(Triangle *a, Triangle *b) {
|
||||
_has_tris = true;
|
||||
_u._tri[0] = a;
|
||||
_u._tri[1] = b;
|
||||
}
|
||||
|
||||
MorphGrid::TriangleTree::
|
||||
TriangleTree(TriangleTree *a, TriangleTree *b) {
|
||||
_has_tris = false;
|
||||
_u._tree[0] = a;
|
||||
_u._tree[1] = b;
|
||||
}
|
||||
|
||||
MorphGrid::TriangleTree::
|
||||
~TriangleTree() {
|
||||
if (!_has_tris) {
|
||||
delete _u._tree[0];
|
||||
delete _u._tree[1];
|
||||
}
|
||||
}
|
||||
|
||||
void MorphGrid::TriangleTree::
|
||||
recompute() {
|
||||
if (_has_tris) {
|
||||
_u._tri[0]->recompute();
|
||||
_u._tri[1]->recompute();
|
||||
|
||||
for (int i = 0; i < (int)TT_num; i++) {
|
||||
for (int a = 0; a < 2; a++) {
|
||||
_min_p[i][a] =
|
||||
min(_u._tri[0]->_min_p[i][a], _u._tri[1]->_min_p[i][a]);
|
||||
_max_p[i][a] =
|
||||
max(_u._tri[0]->_max_p[i][a], _u._tri[1]->_max_p[i][a]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_u._tree[0]->recompute();
|
||||
_u._tree[1]->recompute();
|
||||
|
||||
for (int i = 0; i < (int)TT_num; i++) {
|
||||
for (int a = 0; a < 2; a++) {
|
||||
_min_p[i][a] =
|
||||
min(_u._tree[0]->_min_p[i][a], _u._tree[1]->_min_p[i][a]);
|
||||
_max_p[i][a] =
|
||||
max(_u._tree[0]->_max_p[i][a], _u._tree[1]->_max_p[i][a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MorphGrid::Triangle *MorphGrid::TriangleTree::
|
||||
find_triangle(const LPoint2d &p, TableType from) const {
|
||||
if ((p[0] < _min_p[from][0] || p[0] > _max_p[from][0]) ||
|
||||
(p[1] < _min_p[from][1] || p[1] > _max_p[from][1])) {
|
||||
// Doesn't pass the minmax test.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_has_tris) {
|
||||
if (_u._tri[0]->contains_point(p, from)) {
|
||||
return _u._tri[0];
|
||||
}
|
||||
if (_u._tri[1]->contains_point(p, from)) {
|
||||
return _u._tri[1];
|
||||
}
|
||||
return NULL;
|
||||
} else {
|
||||
Triangle *t = _u._tree[0]->find_triangle(p, from);
|
||||
if (t == NULL) {
|
||||
t = _u._tree[1]->find_triangle(p, from);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
MorphGrid::
|
||||
MorphGrid() {
|
||||
_x_verts = 0;
|
||||
_y_verts = 0;
|
||||
_last_triangle = NULL;
|
||||
_tree = NULL;
|
||||
}
|
||||
|
||||
MorphGrid::
|
||||
~MorphGrid() {
|
||||
if (_tree != NULL) {
|
||||
delete _tree;
|
||||
}
|
||||
}
|
||||
|
||||
bool MorphGrid::
|
||||
is_empty() const {
|
||||
return _x_verts <= 0 || _y_verts <= 0;
|
||||
}
|
||||
|
||||
void MorphGrid::
|
||||
clear() {
|
||||
init(0, 0);
|
||||
}
|
||||
|
||||
void MorphGrid::
|
||||
init(int x_verts, int y_verts) {
|
||||
_x_verts = x_verts;
|
||||
_y_verts = y_verts;
|
||||
|
||||
if (_tree != NULL) {
|
||||
delete _tree;
|
||||
_tree = NULL;
|
||||
}
|
||||
_triangles.clear();
|
||||
_last_triangle = NULL;
|
||||
_table.clear();
|
||||
|
||||
if (is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a 2-d table of vertices.
|
||||
_table.reserve(_y_verts);
|
||||
int x, y;
|
||||
for (y = 0; y < _y_verts; y++) {
|
||||
_table.push_back(Row());
|
||||
_table[y].clear();
|
||||
_table[y].reserve(_x_verts);
|
||||
for (x = 0; x < _x_verts; x++) {
|
||||
LPoint2d p((double)x / (double)(_x_verts - 1),
|
||||
1.0 - (double)y / (double)(_y_verts - 1));
|
||||
_table[y].push_back(Vertex(p));
|
||||
}
|
||||
}
|
||||
|
||||
// Now create a bunch of triangles for these vertices.
|
||||
int num_tris = (_y_verts - 1) * (_x_verts - 1) * 2;
|
||||
|
||||
_triangles.reserve(num_tris);
|
||||
for (y = 0; y + 1 < _y_verts; y++) {
|
||||
for (x = 0; x + 1 < _x_verts; x++) {
|
||||
_triangles.push_back(Triangle(&_table[y][x],
|
||||
&_table[y + 1][x],
|
||||
&_table[y + 1][x + 1]));
|
||||
_triangles.push_back(Triangle(&_table[y][x],
|
||||
&_table[y + 1][x + 1],
|
||||
&_table[y][x + 1]));
|
||||
}
|
||||
}
|
||||
assert((int)_triangles.size() == num_tris);
|
||||
|
||||
// Now create a 2-d table of TriangleTree nodes, each of which
|
||||
// points to a pair of triangles. We'll use this to build up the
|
||||
// TriangleTree structure.
|
||||
typedef vector<TriangleTree *> TRow;
|
||||
typedef vector<TRow> TTable;
|
||||
|
||||
TTable tree;
|
||||
|
||||
int x_tree = _x_verts - 1;
|
||||
int y_tree = _y_verts - 1;
|
||||
tree.reserve(y_tree);
|
||||
int i = 0;
|
||||
for (y = 0; y < y_tree; y++) {
|
||||
tree.push_back(TRow());
|
||||
tree[y].clear();
|
||||
tree[y].reserve(x_tree);
|
||||
for (x = 0; x < x_tree; x++) {
|
||||
tree[y].push_back(new TriangleTree(&_triangles[i],
|
||||
&_triangles[i + 1]));
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
assert(i == num_tris);
|
||||
|
||||
// Now repeatedly pair up adjacent TriangleTree nodes, each time
|
||||
// making a new level with half the number of nodes, until we end up
|
||||
// with a single node.
|
||||
while (x_tree > 1 || y_tree > 1) {
|
||||
// Collapse horizontal pairs.
|
||||
int tx = 0;
|
||||
for (int y = 0; y < y_tree; y++) {
|
||||
tx = 0;
|
||||
int fx = 0;
|
||||
while (fx + 1 < x_tree) {
|
||||
tree[y][tx++] = new TriangleTree(tree[y][fx], tree[y][fx + 1]);
|
||||
fx += 2;
|
||||
}
|
||||
if (fx < x_tree) {
|
||||
// One more odd element remaining, just copy it up.
|
||||
tree[y][tx++] = tree[y][fx];
|
||||
fx++;
|
||||
}
|
||||
assert(fx == x_tree);
|
||||
}
|
||||
x_tree = tx;
|
||||
|
||||
// Collapse vertical pairs.
|
||||
int ty = 0;
|
||||
for (int x = 0; x < x_tree; x++) {
|
||||
ty = 0;
|
||||
int fy = 0;
|
||||
while (fy + 1 < y_tree) {
|
||||
tree[ty++][x] = new TriangleTree(tree[fy][x], tree[fy + 1][x]);
|
||||
fy += 2;
|
||||
}
|
||||
if (fy < y_tree) {
|
||||
// One more odd element remaining, just copy it up.
|
||||
tree[ty++][x] = tree[fy][x];
|
||||
fy++;
|
||||
}
|
||||
assert(fy == y_tree);
|
||||
}
|
||||
y_tree = ty;
|
||||
}
|
||||
|
||||
assert(x_tree == 1 && y_tree == 1);
|
||||
_tree = tree[0][0];
|
||||
}
|
||||
|
||||
void MorphGrid::
|
||||
recompute() {
|
||||
_tree->recompute();
|
||||
}
|
||||
|
||||
void MorphGrid::
|
||||
fill_alpha() {
|
||||
// The stitcher has already made a distinction between interior
|
||||
// points (that is, points which are over no other image, and must
|
||||
// be 100% opaque) and exterior points (points which lay over
|
||||
// another image, and should be feathered). We now need to
|
||||
// determine the distance each exterior point is from this
|
||||
// interior/exterior dividing line.
|
||||
|
||||
// To do this, we first find an interior point.
|
||||
bool found_interior = false;
|
||||
int x, y;
|
||||
for (y = 0; y < _y_verts && !found_interior; y++) {
|
||||
for (x = 0; x < _x_verts && !found_interior; x++) {
|
||||
if (!_table[y][x]._over_another) {
|
||||
// Here's one!
|
||||
found_interior = true;
|
||||
count_dist_from_interior(x, y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_interior) {
|
||||
// There are no interior points in this image--it entirely covers
|
||||
// other images. (Doesn't seem to be much point to it, does
|
||||
// there?) We'll just feather the edges a little.
|
||||
for (y = 0; y < _y_verts; y++) {
|
||||
_table[y][0]._alpha = 0.0;
|
||||
_table[y][_x_verts - 1]._alpha = 0.0;
|
||||
}
|
||||
for (x = 0; x < _x_verts; x++) {
|
||||
_table[0][x]._alpha = 0.0;
|
||||
_table[_y_verts - 1][x]._alpha = 0.0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Now go back through and assign the alpha based on the relative
|
||||
// distance of each point from the edge and from the interior.
|
||||
for (y = 0; y < _y_verts; y++) {
|
||||
for (x = 0; x < _x_verts; x++) {
|
||||
if (!_table[y][x]._over_another) {
|
||||
_table[y][x]._alpha = 1.0;
|
||||
|
||||
} else {
|
||||
int dist_from_edge =
|
||||
min(min(x, y),
|
||||
min(_x_verts - 1 - x, _y_verts - 1 - y));
|
||||
|
||||
assert(_table[y][x]._dist_from_interior >= 0);
|
||||
|
||||
// We subtract one from dist_from_interior to give us a bit of
|
||||
// comfort zone around the interior edge--we're not precisely
|
||||
// sure where the actual edge is.
|
||||
int dist_from_interior =
|
||||
max(_table[y][x]._dist_from_interior - 1, 0);
|
||||
|
||||
// Now if dist_from_edge is 0, it must be transparent; if
|
||||
// dist_from_interior is 0, it must be opaque. Any other
|
||||
// combination should be some value in between.
|
||||
if (dist_from_interior == 0) {
|
||||
_table[y][x]._alpha = 1.0;
|
||||
|
||||
} else if (dist_from_edge == 0) {
|
||||
_table[y][x]._alpha = 0.0;
|
||||
|
||||
} else {
|
||||
double ratio = (double)dist_from_interior /
|
||||
(double)(dist_from_interior + dist_from_edge);
|
||||
|
||||
_table[y][x]._alpha = (cos(ratio * MathNumbers::pi) + 1.0) / 2.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LPoint2d MorphGrid::
|
||||
morph_point(const LPoint2d &p, TableType from, TableType to) {
|
||||
if (is_empty()) {
|
||||
return p;
|
||||
}
|
||||
|
||||
if (_last_triangle != NULL) {
|
||||
// First, check to see if the point is within the same triangle as
|
||||
// the last point was. This will save a bit of time if it is.
|
||||
if (_last_triangle->contains_point(p, from)) {
|
||||
return _last_triangle->morph_point(p, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
// Nope, we just blew cache. We'll have to look for the containing
|
||||
// triangle the hard way.
|
||||
assert(_tree != NULL);
|
||||
_last_triangle = _tree->find_triangle(p, from);
|
||||
|
||||
if (_last_triangle == NULL) {
|
||||
return p;
|
||||
} else {
|
||||
return _last_triangle->morph_point(p, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
double MorphGrid::
|
||||
get_alpha(const LPoint2d &p, TableType from) {
|
||||
if (is_empty()) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (_last_triangle != NULL) {
|
||||
// First, check to see if the point is within the same triangle as
|
||||
// the last point was. This will save a bit of time if it is.
|
||||
if (_last_triangle->contains_point(p, from)) {
|
||||
return _last_triangle->get_alpha(p, from);
|
||||
}
|
||||
}
|
||||
|
||||
// Nope, we just blew cache. We'll have to look for the containing
|
||||
// triangle the hard way.
|
||||
assert(_tree != NULL);
|
||||
_last_triangle = _tree->find_triangle(p, from);
|
||||
|
||||
if (_last_triangle == NULL) {
|
||||
return 1.0;
|
||||
} else {
|
||||
return _last_triangle->get_alpha(p, from);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LPoint2d MorphGrid::
|
||||
morph_in(const LPoint2d &p) const {
|
||||
return ((MorphGrid *)this)->morph_point(p, TT_out, TT_in);
|
||||
}
|
||||
|
||||
LPoint2d MorphGrid::
|
||||
morph_out(const LPoint2d &p) const {
|
||||
return ((MorphGrid *)this)->morph_point(p, TT_in, TT_out);
|
||||
}
|
||||
|
||||
double MorphGrid::
|
||||
get_alpha(const LPoint2d &p) const {
|
||||
return ((MorphGrid *)this)->get_alpha(p, TT_in);
|
||||
}
|
||||
|
||||
void MorphGrid::
|
||||
count_dist_from_interior(int x, int y, int dist) {
|
||||
if (x >= 0 && x < _x_verts &&
|
||||
y >= 0 && y < _y_verts) {
|
||||
Vertex &v = _table[y][x];
|
||||
if (!v._over_another) {
|
||||
// Here we are in the interior.
|
||||
dist = 0;
|
||||
}
|
||||
|
||||
if (v._dist_from_interior < 0 || dist < v._dist_from_interior) {
|
||||
// Update this point, and recurse to our neighbors.
|
||||
v._dist_from_interior = dist;
|
||||
|
||||
count_dist_from_interior(x + 1, y, dist + 1);
|
||||
count_dist_from_interior(x - 1, y, dist + 1);
|
||||
count_dist_from_interior(x, y + 1, dist + 1);
|
||||
count_dist_from_interior(x, y - 1, dist + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
// Filename: morphGrid.h
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MORPHGRID_H
|
||||
#define MORPHGRID_H
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
class MorphGrid {
|
||||
public:
|
||||
MorphGrid();
|
||||
~MorphGrid();
|
||||
|
||||
enum TableType {
|
||||
TT_in = 0,
|
||||
TT_out = 1,
|
||||
TT_num = 2
|
||||
};
|
||||
|
||||
bool is_empty() const;
|
||||
void clear();
|
||||
|
||||
void init(int x_verts, int y_verts);
|
||||
void recompute();
|
||||
void fill_alpha();
|
||||
|
||||
LPoint2d morph_point(const LPoint2d &p, TableType from, TableType to);
|
||||
double get_alpha(const LPoint2d &p, TableType from);
|
||||
|
||||
LPoint2d morph_in(const LPoint2d &p) const;
|
||||
LPoint2d morph_out(const LPoint2d &p) const;
|
||||
double get_alpha(const LPoint2d &p) const;
|
||||
|
||||
private:
|
||||
class Triangle;
|
||||
public:
|
||||
|
||||
class Vertex {
|
||||
public:
|
||||
Vertex(const LPoint2d &p);
|
||||
|
||||
LPoint2d _p[TT_num]; // TT_in, TT_out
|
||||
|
||||
// These members are used to feather the edges of the images where
|
||||
// they overlap other images. Once the Stitcher sets the
|
||||
// _over_another flags appropriately, MorphGrid::fill_alpha() will
|
||||
// assign the alpha values to feather the edges.
|
||||
double _alpha;
|
||||
bool _over_another;
|
||||
int _dist_from_interior;
|
||||
};
|
||||
|
||||
int _x_verts, _y_verts;
|
||||
typedef vector<Vertex> Row;
|
||||
typedef vector<Row> Table;
|
||||
Table _table;
|
||||
|
||||
private:
|
||||
void count_dist_from_interior(int x, int y, int dist);
|
||||
|
||||
class Triangle {
|
||||
public:
|
||||
Triangle(Vertex *v0, Vertex *v1, Vertex *v2);
|
||||
bool contains_point(const LPoint2d &p, TableType from) const;
|
||||
LPoint2d morph_point(const LPoint2d &p, TableType from, TableType to) const;
|
||||
double get_alpha(const LPoint2d &p, TableType from) const;
|
||||
void recompute();
|
||||
|
||||
Vertex *_v[3];
|
||||
LPoint2d _min_p[TT_num], _max_p[TT_num];
|
||||
LMatrix3d _mat[TT_num], _inv[TT_num];
|
||||
};
|
||||
|
||||
typedef vector<Triangle> Triangles;
|
||||
Triangles _triangles;
|
||||
Triangle *_last_triangle;
|
||||
|
||||
class TriangleTree {
|
||||
public:
|
||||
TriangleTree(Triangle *a, Triangle *b);
|
||||
TriangleTree(TriangleTree *a, TriangleTree *b);
|
||||
~TriangleTree();
|
||||
void recompute();
|
||||
Triangle *find_triangle(const LPoint2d &p, TableType from) const;
|
||||
|
||||
bool _has_tris;
|
||||
union {
|
||||
Triangle *_tri[2];
|
||||
TriangleTree *_tree[2];
|
||||
} _u;
|
||||
|
||||
LPoint2d _min_p[TT_num], _max_p[TT_num];
|
||||
};
|
||||
|
||||
TriangleTree *_tree;
|
||||
friend class TriangleTree;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,813 +0,0 @@
|
|||
// Filename: stitchCommand.cxx
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchCommand.h"
|
||||
#include "stitchImage.h"
|
||||
#include "stitchLens.h"
|
||||
#include "stitchPerspectiveLens.h"
|
||||
#include "stitchFisheyeLens.h"
|
||||
#include "stitchCylindricalLens.h"
|
||||
#include "stitchPSphereLens.h"
|
||||
#include "stitchImageOutputter.h"
|
||||
#include "stitchCylindricalScreen.h"
|
||||
#include "stitchFlatScreen.h"
|
||||
#include "stitcher.h"
|
||||
|
||||
#include "compose_matrix.h"
|
||||
#include "indent.h"
|
||||
#include "pnmImage.h"
|
||||
|
||||
ostream &
|
||||
operator << (ostream &out, StitchCommand::Command c) {
|
||||
switch (c) {
|
||||
case StitchCommand::C_global:
|
||||
return out << "global";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_define:
|
||||
return out << "define";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_lens:
|
||||
return out << "lens";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_input_image:
|
||||
return out << "input_image";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_output_image:
|
||||
return out << "output_image";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_eyepoint:
|
||||
return out << "eyepoint";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_perspective:
|
||||
return out << "perspective";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_fisheye:
|
||||
return out << "fisheye";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_cylindrical:
|
||||
return out << "cylindrical";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_psphere:
|
||||
return out << "psphere";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_focal_length:
|
||||
return out << "focal_length";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_fov:
|
||||
return out << "fov";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_singularity_tolerance:
|
||||
return out << "singularity_tolerance";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_resolution:
|
||||
return out << "resolution";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_filename:
|
||||
return out << "filename";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_fade:
|
||||
return out << "fade";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_point2d:
|
||||
case StitchCommand::C_point3d:
|
||||
return out << "point";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_show_points:
|
||||
return out << "show_points";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_image_size:
|
||||
return out << "image_size";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_film_size:
|
||||
return out << "film_size";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_film_offset:
|
||||
return out << "film_offset";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_grid:
|
||||
return out << "grid";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_untextured_color:
|
||||
return out << "untextured_color";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_hpr:
|
||||
return out << "hpr";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_pos:
|
||||
return out << "pos";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_radius:
|
||||
return out << "radius";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_angle:
|
||||
return out << "angle";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_height:
|
||||
return out << "height";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_layers:
|
||||
return out << "layers";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_stitch:
|
||||
return out << "stitch";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_screen:
|
||||
return out << "screen";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_using:
|
||||
return out << "using";
|
||||
break;
|
||||
|
||||
case StitchCommand::C_user_command:
|
||||
return out << "user_command";
|
||||
break;
|
||||
|
||||
default:
|
||||
return out << "(**unknown command**)";
|
||||
}
|
||||
}
|
||||
|
||||
StitchCommand::
|
||||
StitchCommand(StitchCommand *parent, StitchCommand::Command command) :
|
||||
_parent(parent),
|
||||
_command(command)
|
||||
{
|
||||
_params = 0;
|
||||
_lens = NULL;
|
||||
if (parent != NULL) {
|
||||
parent->add_nested(this);
|
||||
}
|
||||
}
|
||||
|
||||
StitchCommand::
|
||||
~StitchCommand() {
|
||||
Commands::iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
delete (*ci);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
clear() {
|
||||
Commands::iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
delete (*ci);
|
||||
}
|
||||
_nested.clear();
|
||||
_using.clear();
|
||||
_params = 0;
|
||||
_command = C_global;
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_name(const string &name) {
|
||||
if (!name.empty()) {
|
||||
_params |= P_name;
|
||||
_name = name;
|
||||
}
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_length(double number) {
|
||||
_params |= P_length;
|
||||
_number = number;
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_resolution(double number) {
|
||||
_params |= P_resolution;
|
||||
_number = number;
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_number(double number) {
|
||||
_params |= P_number;
|
||||
_number = number;
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_point2d(const LVecBase2d &point) {
|
||||
_params |= P_point2d;
|
||||
_n[0] = point[0];
|
||||
_n[1] = point[1];
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_point3d(const LVecBase3d &point) {
|
||||
_params |= P_point3d;
|
||||
_n[0] = point[0];
|
||||
_n[1] = point[1];
|
||||
_n[2] = point[2];
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_length_pair(const LVecBase2d &length_pair) {
|
||||
_params |= P_length_pair;
|
||||
_n[0] = length_pair[0];
|
||||
_n[1] = length_pair[1];
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_color(const Colord &color) {
|
||||
_params |= P_color;
|
||||
_n[0] = color[0];
|
||||
_n[1] = color[1];
|
||||
_n[2] = color[2];
|
||||
_n[3] = color[3];
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
set_str(const string &str) {
|
||||
_params |= P_str;
|
||||
_str = str;
|
||||
}
|
||||
|
||||
bool StitchCommand::
|
||||
add_using(const string &name) {
|
||||
StitchCommand *def = find_definition(name);
|
||||
if (def != NULL) {
|
||||
_params |= P_using;
|
||||
_using.push_back(def);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
add_nested(StitchCommand *nested) {
|
||||
_params |= P_nested;
|
||||
_nested.push_back(nested);
|
||||
}
|
||||
|
||||
string StitchCommand::
|
||||
get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
double StitchCommand::
|
||||
get_number() const {
|
||||
return _number;
|
||||
}
|
||||
|
||||
LVecBase2d StitchCommand::
|
||||
get_point2d() const {
|
||||
return LVecBase2d(_n[0], _n[1]);
|
||||
}
|
||||
|
||||
LVecBase3d StitchCommand::
|
||||
get_point3d() const {
|
||||
return LVecBase3d(_n[0], _n[1], _n[2]);
|
||||
}
|
||||
|
||||
LVector3d StitchCommand::
|
||||
get_vector3d() const {
|
||||
return LVector3d(_n[0], _n[1], _n[2]);
|
||||
}
|
||||
|
||||
Colord StitchCommand::
|
||||
get_color() const {
|
||||
return Colord(_n[0], _n[1], _n[2], _n[3]);
|
||||
}
|
||||
|
||||
string StitchCommand::
|
||||
get_str() const {
|
||||
return _str;
|
||||
}
|
||||
|
||||
bool StitchCommand::
|
||||
has_name() const {
|
||||
return (_params & P_name) != 0;
|
||||
}
|
||||
|
||||
bool StitchCommand::
|
||||
has_number() const {
|
||||
return (_params & P_number) != 0;
|
||||
}
|
||||
|
||||
bool StitchCommand::
|
||||
has_point2d() const {
|
||||
return (_params & P_point2d) != 0;
|
||||
}
|
||||
|
||||
bool StitchCommand::
|
||||
has_point3d() const {
|
||||
return (_params & P_point3d) != 0;
|
||||
}
|
||||
|
||||
bool StitchCommand::
|
||||
has_color() const {
|
||||
return (_params & P_color) != 0;
|
||||
}
|
||||
|
||||
bool StitchCommand::
|
||||
has_str() const {
|
||||
return (_params & P_str) != 0;
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
process(StitchImageOutputter &outputter, Stitcher *stitcher,
|
||||
StitchFile &file) {
|
||||
if (_command == C_input_image) {
|
||||
StitchImage *image = create_image();
|
||||
|
||||
if (stitcher != NULL) {
|
||||
stitcher->add_image(image);
|
||||
} else {
|
||||
outputter.add_input_image(image);
|
||||
}
|
||||
|
||||
} else if (_command == C_output_image) {
|
||||
StitchImage *image = create_image();
|
||||
outputter.add_output_image(image);
|
||||
|
||||
} else if (_command == C_eyepoint) {
|
||||
set_eyepoint(outputter);
|
||||
|
||||
} else if (_command == C_stitch) {
|
||||
Stitcher *new_stitcher = new Stitcher;
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
(*ci)->process(outputter, new_stitcher, file);
|
||||
}
|
||||
new_stitcher->stitch();
|
||||
|
||||
// Now add all of the stitched images to the outputter, in order.
|
||||
Stitcher::Images::const_iterator ii;
|
||||
for (ii = new_stitcher->_placed.begin();
|
||||
ii != new_stitcher->_placed.end();
|
||||
++ii) {
|
||||
outputter.add_input_image(*ii);
|
||||
}
|
||||
outputter.add_stitcher(new_stitcher);
|
||||
|
||||
} else if (_command == C_screen) {
|
||||
PT(StitchScreen) screen = create_screen();
|
||||
outputter.add_screen(screen);
|
||||
|
||||
} else if (_command == C_point3d) {
|
||||
if (stitcher != NULL) {
|
||||
stitcher->add_point(_name, get_vector3d());
|
||||
}
|
||||
|
||||
} else if (_command == C_show_points) {
|
||||
if (stitcher != NULL) {
|
||||
stitcher->show_points(get_number(), get_color());
|
||||
}
|
||||
|
||||
} else if (_params & P_nested) {
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
(*ci)->process(outputter, stitcher, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StitchCommand::
|
||||
write(ostream &out, int indent_level) const {
|
||||
if (_command == C_user_command) {
|
||||
assert(_using.size() == 1);
|
||||
indent(out, indent_level) << _using.front()->_name << ";\n";
|
||||
|
||||
} else if (_command == C_global) {
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
(*ci)->write(out, indent_level );
|
||||
}
|
||||
|
||||
} else {
|
||||
indent(out, indent_level) << _command;
|
||||
if (_params & P_name) {
|
||||
out << " " << _name;
|
||||
}
|
||||
if (_params & P_length) {
|
||||
out << " " << get_number() << "mm";
|
||||
}
|
||||
if (_params & P_resolution) {
|
||||
out << " " << get_number() << "p/mm";
|
||||
}
|
||||
if (_params & P_number) {
|
||||
out << " " << get_number();
|
||||
}
|
||||
if (_params & P_point2d) {
|
||||
out << " (" << get_point2d() << ")";
|
||||
}
|
||||
if (_params & P_point3d) {
|
||||
out << " (" << get_point3d() << ")";
|
||||
}
|
||||
if (_params & P_length_pair) {
|
||||
out << " (" << _n[0] << "mm " << _n[1] << "mm)";
|
||||
}
|
||||
if (_params & P_color) {
|
||||
out << " (" << get_color() << ")";
|
||||
}
|
||||
if (_params & P_str) {
|
||||
out << " \"" << _str << "\"";
|
||||
}
|
||||
if (_params & P_using) {
|
||||
Commands::const_iterator ci;
|
||||
ci = _using.begin();
|
||||
if (ci != _using.end()) {
|
||||
out << " " << (*ci)->_name;
|
||||
++ci;
|
||||
while (ci != _using.end()) {
|
||||
out << ", " << (*ci)->_name;
|
||||
++ci;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_params & P_nested) {
|
||||
out << " {\n";
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
(*ci)->write(out, indent_level + 2);
|
||||
}
|
||||
indent(out, indent_level) << "}\n";
|
||||
} else {
|
||||
out << ";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
StitchCommand *StitchCommand::
|
||||
find_definition(const string &name) {
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
if (((*ci)->_command == C_define || (*ci)->_command == C_lens) &&
|
||||
(*ci)->_name == name) {
|
||||
return (*ci);
|
||||
}
|
||||
}
|
||||
if (_parent != NULL) {
|
||||
return _parent->find_definition(name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StitchLens *StitchCommand::
|
||||
find_using_lens() {
|
||||
if (!_using.empty()) {
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _using.begin(); ci != _using.end(); ++ci) {
|
||||
StitchLens *lens = (*ci)->find_lens();
|
||||
if (lens != NULL) {
|
||||
return lens;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_parent != NULL) {
|
||||
return _parent->find_using_lens();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StitchLens *StitchCommand::
|
||||
find_lens() {
|
||||
if (_command == C_lens) {
|
||||
return make_lens();
|
||||
}
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
if ((*ci)->_command == C_lens) {
|
||||
return (*ci)->make_lens();
|
||||
}
|
||||
}
|
||||
if (_parent != NULL) {
|
||||
return _parent->find_using_lens();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StitchLens *StitchCommand::
|
||||
make_lens() {
|
||||
if (_lens != NULL) {
|
||||
return _lens;
|
||||
}
|
||||
|
||||
if (find_command(C_fisheye) != NULL) {
|
||||
_lens = new StitchFisheyeLens();
|
||||
} else if (find_command(C_cylindrical) != NULL) {
|
||||
_lens = new StitchCylindricalLens();
|
||||
} else if (find_command(C_psphere) != NULL) {
|
||||
_lens = new StitchPSphereLens();
|
||||
} else {
|
||||
_lens = new StitchPerspectiveLens();
|
||||
}
|
||||
|
||||
StitchCommand *cmd = find_command(C_focal_length);
|
||||
if (cmd != NULL) {
|
||||
_lens->set_focal_length(cmd->get_number());
|
||||
}
|
||||
cmd = find_command(C_fov);
|
||||
if (cmd != NULL) {
|
||||
_lens->set_hfov(cmd->get_number());
|
||||
}
|
||||
|
||||
if (!_lens->is_defined()) {
|
||||
_lens->set_hfov(60.0);
|
||||
}
|
||||
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
switch ((*ci)->_command) {
|
||||
case C_singularity_tolerance:
|
||||
_lens->set_singularity_tolerance((*ci)->get_number());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _lens;
|
||||
}
|
||||
|
||||
|
||||
StitchCommand *StitchCommand::
|
||||
find_using_command(Command command) {
|
||||
if (!_using.empty()) {
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _using.begin(); ci != _using.end(); ++ci) {
|
||||
StitchCommand *cmd = (*ci)->find_command(command);
|
||||
if (cmd != NULL) {
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_parent != NULL) {
|
||||
return _parent->find_using_command(command);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StitchCommand *StitchCommand::
|
||||
find_command(Command command) {
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
if ((*ci)->_command == command) {
|
||||
return (*ci);
|
||||
}
|
||||
}
|
||||
|
||||
if (_parent != NULL) {
|
||||
return _parent->find_using_command(command);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
string StitchCommand::
|
||||
find_parameter(Command command, const string &dflt) {
|
||||
StitchCommand *cmd = find_command(command);
|
||||
if (cmd != NULL) {
|
||||
return cmd->_str;
|
||||
} else {
|
||||
return dflt;
|
||||
}
|
||||
}
|
||||
|
||||
double StitchCommand::
|
||||
find_parameter(Command command, double dflt) {
|
||||
StitchCommand *cmd = find_command(command);
|
||||
if (cmd != NULL) {
|
||||
return cmd->get_number();
|
||||
} else {
|
||||
return dflt;
|
||||
}
|
||||
}
|
||||
|
||||
LVecBase2d StitchCommand::
|
||||
find_parameter(Command command, const LVecBase2d &dflt) {
|
||||
StitchCommand *cmd = find_command(command);
|
||||
if (cmd != NULL) {
|
||||
return cmd->get_point2d();
|
||||
} else {
|
||||
return dflt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
StitchImage *StitchCommand::
|
||||
create_image() {
|
||||
string filename = find_parameter(C_filename, "");
|
||||
LVecBase2d size_pixels(256, 256);
|
||||
LVecBase2d resolution(72.0 / 25.4, 72.0 / 25.4);
|
||||
StitchLens *lens = find_lens();
|
||||
if (lens == NULL) {
|
||||
nout << "Warning: No lens defined for " << filename << "\n";
|
||||
lens = make_lens();
|
||||
}
|
||||
|
||||
StitchCommand *cmd;
|
||||
cmd = find_command(C_image_size);
|
||||
if (cmd != NULL) {
|
||||
size_pixels = cmd->get_point2d();
|
||||
|
||||
} else if (!filename.empty()) {
|
||||
// If we don't get an explicit image size, try to determine it
|
||||
// from the image file.
|
||||
PNMImageHeader header;
|
||||
if (header.read_header(filename)) {
|
||||
size_pixels.set(header.get_x_size(), header.get_y_size());
|
||||
}
|
||||
}
|
||||
|
||||
cmd = find_command(C_film_size);
|
||||
if (cmd != NULL) {
|
||||
LVecBase2d size_mm = cmd->get_point2d();
|
||||
resolution.set((size_pixels[0]-1) / size_mm[0],
|
||||
(size_pixels[1]-1) / size_mm[1]);
|
||||
} else {
|
||||
cmd = find_command(C_resolution);
|
||||
if (cmd != NULL) {
|
||||
resolution.set(cmd->get_number(), cmd->get_number());
|
||||
}
|
||||
}
|
||||
|
||||
LVecBase2d film_offset_mm(0.0, 0.0);
|
||||
cmd = find_command(C_film_offset);
|
||||
if (cmd != NULL) {
|
||||
film_offset_mm = cmd->get_point2d();
|
||||
}
|
||||
|
||||
StitchImage *image =
|
||||
new StitchImage(get_name(), filename, lens, size_pixels, resolution,
|
||||
film_offset_mm);
|
||||
image->setup_grid(50, 50);
|
||||
|
||||
// Also look for points and other stuff.
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
switch ((*ci)->_command) {
|
||||
case C_point2d:
|
||||
image->add_point((*ci)->_name, (*ci)->get_point2d());
|
||||
break;
|
||||
|
||||
case C_show_points:
|
||||
image->show_points((*ci)->get_number(), (*ci)->get_color());
|
||||
break;
|
||||
|
||||
case C_untextured_color:
|
||||
image->_untextured_color = (*ci)->get_color();
|
||||
break;
|
||||
|
||||
case C_hpr:
|
||||
image->set_hpr((*ci)->get_point3d());
|
||||
break;
|
||||
|
||||
case C_pos:
|
||||
image->set_pos((*ci)->get_point3d());
|
||||
break;
|
||||
|
||||
case C_layers:
|
||||
image->_layered_type = StitchImage::LT_separate;
|
||||
break;
|
||||
|
||||
case C_grid:
|
||||
image->setup_grid((int)(*ci)->_n[0], (int)(*ci)->_n[1]);
|
||||
break;
|
||||
|
||||
case C_fade:
|
||||
image->set_fade_filename((*ci)->get_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCommand::set_eyepoint
|
||||
// Access: Protected
|
||||
// Description: Sets the eyepoint on the outputter according to the
|
||||
// eyepoint entry in the command file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchCommand::
|
||||
set_eyepoint(StitchImageOutputter &outputter) {
|
||||
LVecBase3d hpr(0.0, 0.0, 0.0);
|
||||
LPoint3d pos(0.0, 0.0, 0.0);
|
||||
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
switch ((*ci)->_command) {
|
||||
case C_hpr:
|
||||
hpr = (*ci)->get_point3d();
|
||||
break;
|
||||
|
||||
case C_pos:
|
||||
pos = (*ci)->get_point3d();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LMatrix4d mat;
|
||||
compose_matrix(mat, LVecBase3d(1.0, 1.0, 1.0), hpr, pos);
|
||||
outputter.set_eyepoint(mat);
|
||||
}
|
||||
|
||||
|
||||
PT(StitchScreen) StitchCommand::
|
||||
create_screen() {
|
||||
PT(StitchScreen) screen;
|
||||
|
||||
StitchCommand *cmd;
|
||||
if (find_command(C_cylindrical) != NULL) {
|
||||
StitchCylindricalScreen *cscreen = new StitchCylindricalScreen();
|
||||
screen = cscreen;
|
||||
|
||||
cmd = find_command(C_radius);
|
||||
if (cmd != NULL) {
|
||||
cscreen->set_radius(cmd->get_number());
|
||||
}
|
||||
cmd = find_command(C_height);
|
||||
if (cmd != NULL) {
|
||||
LPoint2d p = cmd->get_point2d();
|
||||
cscreen->set_height(p[0], p[1]);
|
||||
}
|
||||
cmd = find_command(C_angle);
|
||||
if (cmd != NULL) {
|
||||
LPoint2d p = cmd->get_point2d();
|
||||
cscreen->set_angle(p[0], p[1]);
|
||||
}
|
||||
|
||||
} else {
|
||||
screen = new StitchFlatScreen();
|
||||
}
|
||||
|
||||
screen->set_name(get_name());
|
||||
|
||||
// Also look for pos and hpr and stuff.
|
||||
Commands::const_iterator ci;
|
||||
for (ci = _nested.begin(); ci != _nested.end(); ++ci) {
|
||||
switch ((*ci)->_command) {
|
||||
case C_hpr:
|
||||
screen->set_hpr((*ci)->get_point3d());
|
||||
break;
|
||||
|
||||
case C_pos:
|
||||
screen->set_pos((*ci)->get_point3d());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
// Filename: stitchCommand.h
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHCOMMAND_H
|
||||
#define STITCHCOMMAND_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
#include "stitchScreen.h"
|
||||
|
||||
#include "luse.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pvector.h"
|
||||
|
||||
class StitchLens;
|
||||
class StitchImage;
|
||||
class StitchScreen;
|
||||
class StitchImageOutputter;
|
||||
class StitchFile;
|
||||
class Stitcher;
|
||||
|
||||
class StitchCommand {
|
||||
public:
|
||||
enum Command {
|
||||
C_global,
|
||||
C_define,
|
||||
C_lens,
|
||||
C_input_image,
|
||||
C_output_image,
|
||||
C_eyepoint,
|
||||
C_perspective,
|
||||
C_fisheye,
|
||||
C_cylindrical,
|
||||
C_psphere,
|
||||
C_focal_length,
|
||||
C_fov,
|
||||
C_singularity_tolerance,
|
||||
C_resolution,
|
||||
C_filename,
|
||||
C_fade,
|
||||
C_point2d,
|
||||
C_point3d,
|
||||
C_show_points,
|
||||
C_image_size,
|
||||
C_film_size,
|
||||
C_film_offset,
|
||||
C_grid,
|
||||
C_untextured_color,
|
||||
C_hpr,
|
||||
C_pos,
|
||||
C_radius,
|
||||
C_angle,
|
||||
C_height,
|
||||
C_layers,
|
||||
C_stitch,
|
||||
C_screen,
|
||||
C_using,
|
||||
C_user_command,
|
||||
};
|
||||
|
||||
StitchCommand(StitchCommand *parent = NULL,
|
||||
Command command = C_global);
|
||||
~StitchCommand();
|
||||
|
||||
void clear();
|
||||
|
||||
void set_name(const string &name);
|
||||
void set_length(double number);
|
||||
void set_resolution(double number);
|
||||
void set_number(double number);
|
||||
void set_point2d(const LVecBase2d &point);
|
||||
void set_point3d(const LVecBase3d &point);
|
||||
void set_length_pair(const LVecBase2d &point);
|
||||
void set_color(const Colord &color);
|
||||
void set_str(const string &str);
|
||||
bool add_using(const string &name);
|
||||
void add_nested(StitchCommand *nested);
|
||||
|
||||
string get_name() const;
|
||||
double get_number() const;
|
||||
LVecBase2d get_point2d() const;
|
||||
LVecBase3d get_point3d() const;
|
||||
LVector3d get_vector3d() const;
|
||||
Colord get_color() const;
|
||||
string get_str() const;
|
||||
|
||||
bool has_name() const;
|
||||
bool has_number() const;
|
||||
bool has_point2d() const;
|
||||
bool has_point3d() const;
|
||||
bool has_color() const;
|
||||
bool has_str() const;
|
||||
|
||||
StitchCommand *find_definition(const string &name);
|
||||
|
||||
void process(StitchImageOutputter &outputter, Stitcher *stitcher,
|
||||
StitchFile &file);
|
||||
|
||||
void write(ostream &out, int indent) const;
|
||||
|
||||
|
||||
private:
|
||||
StitchLens *find_using_lens();
|
||||
StitchLens *find_lens();
|
||||
StitchLens *make_lens();
|
||||
|
||||
StitchCommand *find_using_command(Command command);
|
||||
StitchCommand *find_command(Command command);
|
||||
string find_parameter(Command command, const string &dflt);
|
||||
double find_parameter(Command command, double dflt);
|
||||
LVecBase2d find_parameter(Command command, const LVecBase2d &dflt);
|
||||
|
||||
StitchImage *create_image();
|
||||
void set_eyepoint(StitchImageOutputter &outputter);
|
||||
PT(StitchScreen) create_screen();
|
||||
|
||||
|
||||
StitchCommand *_parent;
|
||||
Command _command;
|
||||
|
||||
enum Parameters {
|
||||
P_name = 0x001,
|
||||
P_length = 0x002,
|
||||
P_resolution = 0x004,
|
||||
P_number = 0x008,
|
||||
P_point2d = 0x010,
|
||||
P_point3d = 0x020,
|
||||
P_length_pair = 0x040,
|
||||
P_color = 0x080,
|
||||
P_str = 0x100,
|
||||
P_using = 0x200,
|
||||
P_nested = 0x400
|
||||
};
|
||||
|
||||
int _params;
|
||||
|
||||
string _name;
|
||||
double _number;
|
||||
double _n[4];
|
||||
string _str;
|
||||
|
||||
// This will only get filled in by make_lens().
|
||||
StitchLens *_lens;
|
||||
|
||||
typedef pvector<StitchCommand *> Commands;
|
||||
Commands _using;
|
||||
Commands _nested;
|
||||
};
|
||||
|
||||
inline ostream &operator << (ostream &out, const StitchCommand &c) {
|
||||
c.write(out, 0);
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream &operator << (ostream &out, StitchCommand::Command c);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// Filename: stitchCommandReader.cxx
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchCommandReader.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCommandReader::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchCommandReader::
|
||||
StitchCommandReader() {
|
||||
clear_runlines();
|
||||
add_runline("[opts] input.st");
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCommandReader::handle_args
|
||||
// Access: Protected, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchCommandReader::
|
||||
handle_args(ProgramBase::Args &args) {
|
||||
if (args.empty()) {
|
||||
nout << "You must specify the stitch command file to read on the\n"
|
||||
<< "command line.\n";
|
||||
return false;
|
||||
}
|
||||
if (args.size() > 1) {
|
||||
nout << "You must specify only one stitch command file to read on the\n"
|
||||
<< "command line.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return _command_file.read(args[0]);
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Filename: stitchCommandReader.h
|
||||
// Created by: drose (16Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHCOMMANDREADER_H
|
||||
#define STITCHCOMMANDREADER_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "stitchFile.h"
|
||||
|
||||
#include <programBase.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchCommandReader
|
||||
// Description : This specialization of ProgramBase is intended for
|
||||
// programs in this directory that read and process a
|
||||
// stitch command file.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
class StitchCommandReader : public ProgramBase {
|
||||
public:
|
||||
StitchCommandReader();
|
||||
|
||||
protected:
|
||||
virtual bool handle_args(Args &args);
|
||||
|
||||
protected:
|
||||
StitchFile _command_file;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
// Filename: stitchCylindricalLens.cxx
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchCylindricalLens.h"
|
||||
#include "stitchCommand.h"
|
||||
#include "triangleRasterizer.h"
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "deg_2_rad.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// This is the focal-length constant for fisheye lenses. See
|
||||
// stitchFisheyeLens.h.
|
||||
static const double cylindrical_k = 60.0;
|
||||
|
||||
StitchCylindricalLens::
|
||||
StitchCylindricalLens() {
|
||||
}
|
||||
|
||||
double StitchCylindricalLens::
|
||||
get_focal_length(double width_mm) const {
|
||||
if (_flags & F_focal_length) {
|
||||
return _focal_length;
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
return width_mm * cylindrical_k / _fov;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double StitchCylindricalLens::
|
||||
get_hfov(double width_mm) const {
|
||||
if (_flags & F_fov) {
|
||||
return _fov;
|
||||
}
|
||||
if (_flags & F_focal_length) {
|
||||
return width_mm * cylindrical_k / _focal_length;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double StitchCylindricalLens::
|
||||
get_vfov(double height_mm) const {
|
||||
return 2.0 * rad_2_deg(atan(height_mm /
|
||||
(2.0 * get_focal_length(height_mm))));
|
||||
}
|
||||
|
||||
LVector3d StitchCylindricalLens::
|
||||
extrude(const LPoint2d &point_mm, double width_mm) const {
|
||||
LVector2d v2 = point_mm;
|
||||
|
||||
double fl = get_focal_length(width_mm);
|
||||
return LVector3d(sin(deg_2_rad(v2[0] * cylindrical_k / fl)) * fl,
|
||||
cos(deg_2_rad(v2[0] * cylindrical_k / fl)) * fl,
|
||||
v2[1]);
|
||||
}
|
||||
|
||||
|
||||
LPoint2d StitchCylindricalLens::
|
||||
project(const LVector3d &vec, double width_mm) const {
|
||||
// A cylindrical lens is a cross between a fisheye and a normal
|
||||
// lens. It is curved in the horizontal direction, and straight in
|
||||
// the vertical direction.
|
||||
|
||||
LVector3d v3 = vec * LMatrix4d::convert_mat(CS_default, CS_zup_right);
|
||||
|
||||
// To compute the x position on the frame, we only need to consider
|
||||
// the angle of the vector about the Z axis. Project the vector
|
||||
// into the XY plane to do this.
|
||||
|
||||
LVector2d xy(v3[0], v3[1]);
|
||||
|
||||
// The x position is the angle about the Z axis.
|
||||
double x =
|
||||
rad_2_deg(atan2(xy[0], xy[1])) * get_focal_length(width_mm) / cylindrical_k;
|
||||
|
||||
// The y position is the Z height divided by the perspective
|
||||
// distance.
|
||||
double y = v3[2] / length(xy) * get_focal_length(width_mm);
|
||||
|
||||
return LPoint2d(x, y);
|
||||
}
|
||||
|
||||
LPoint2d StitchCylindricalLens::
|
||||
project_left(const LVector3d &vec, double width_mm) const {
|
||||
// This is just like project(), except that if the vertex extends
|
||||
// below -180 degrees, it remains on the left side of the film
|
||||
// (instead of wrapping around to the right side).
|
||||
|
||||
LVector3d v3 = vec * LMatrix4d::convert_mat(CS_default, CS_zup_right);
|
||||
LVector2d xy(v3[0], v3[1]);
|
||||
double x =
|
||||
(rad_2_deg(atan2(-xy[0], -xy[1])) - 180.0) *
|
||||
get_focal_length(width_mm) / cylindrical_k;
|
||||
|
||||
double y = v3[2] / length(xy) * get_focal_length(width_mm);
|
||||
return LPoint2d(x, y);
|
||||
}
|
||||
|
||||
LPoint2d StitchCylindricalLens::
|
||||
project_right(const LVector3d &vec, double width_mm) const {
|
||||
// This is just like project(), except that if the vertex extends
|
||||
// above 180 degrees, it remains on the right side of the film
|
||||
// (instead of wrapping around to the left side).
|
||||
|
||||
LVector3d v3 = vec * LMatrix4d::convert_mat(CS_default, CS_zup_right);
|
||||
LVector2d xy(v3[0], v3[1]);
|
||||
double x =
|
||||
(rad_2_deg(atan2(-xy[0], -xy[1])) + 180.0) *
|
||||
get_focal_length(width_mm) / cylindrical_k;
|
||||
|
||||
double y = v3[2] / length(xy) * get_focal_length(width_mm);
|
||||
return LPoint2d(x, y);
|
||||
}
|
||||
|
||||
void StitchCylindricalLens::
|
||||
draw_triangle(TriangleRasterizer &rast, const LMatrix3d &mm_to_pixels,
|
||||
double width_mm, const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1, const RasterizerVertex *v2) {
|
||||
// A cylindrical lens has a seam at 180 and -180 degrees (regardless
|
||||
// of its field of view). If the triangle crosses that seam, we'll
|
||||
// simply draw it twice: once at each side.
|
||||
|
||||
// Determine which quadrant each of the vertices is in. The
|
||||
// triangle crosses the seam if no vertices are in quadrants I and
|
||||
// II, and some vertices are in quadrant III and others are in
|
||||
// quadrant IV.
|
||||
|
||||
LVector2d xy0(dot(v0->_space, LVector3d::right()),
|
||||
dot(v0->_space, LVector3d::forward()));
|
||||
LVector2d xy1(dot(v1->_space, LVector3d::right()),
|
||||
dot(v1->_space, LVector3d::forward()));
|
||||
LVector2d xy2(dot(v2->_space, LVector3d::right()),
|
||||
dot(v2->_space, LVector3d::forward()));
|
||||
|
||||
if (xy0[1] >= 0.0 || xy1[1] >= 0.0 || xy2[1] >= 0.0) {
|
||||
// Some vertices are in quadrants I or II.
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
|
||||
} else if (xy0[0] > 0.0 && xy1[0] > 0.0 && xy2[0] > 0.0) {
|
||||
// All vertices are in quadrant IV.
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
|
||||
} else if (xy0[0] < 0.0 && xy1[0] < 0.0 && xy2[0] < 0.0) {
|
||||
// All vertices are in quadrant III.
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
|
||||
} else {
|
||||
// The triangle crosses the seam. Draw it twice.
|
||||
RasterizerVertex v0a = *v0;
|
||||
RasterizerVertex v1a = *v1;
|
||||
RasterizerVertex v2a = *v2;
|
||||
|
||||
v0a._p = project_left(v0a._space, width_mm) * mm_to_pixels;
|
||||
v1a._p = project_left(v1a._space, width_mm) * mm_to_pixels;
|
||||
v2a._p = project_left(v2a._space, width_mm) * mm_to_pixels;
|
||||
rast.draw_triangle(&v0a, &v1a, &v2a);
|
||||
|
||||
v0a._p = project_right(v0a._space, width_mm) * mm_to_pixels;
|
||||
v1a._p = project_right(v1a._space, width_mm) * mm_to_pixels;
|
||||
v2a._p = project_right(v2a._space, width_mm) * mm_to_pixels;
|
||||
rast.draw_triangle(&v0a, &v1a, &v2a);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchCylindricalLens::
|
||||
make_lens_command(StitchCommand *parent) {
|
||||
StitchCommand *lens_cmd = new StitchCommand(parent, StitchCommand::C_lens);
|
||||
StitchCommand *cmd;
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_cylindrical);
|
||||
if (_flags & F_focal_length) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_focal_length);
|
||||
cmd->set_length(_focal_length);
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_fov);
|
||||
cmd->set_number(_fov);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
// Filename: stitchCylindricalLens.h
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHCYLINDRICALLENS_H
|
||||
#define STITCHCYLINDRICALLENS_H
|
||||
|
||||
#include "stitchLens.h"
|
||||
|
||||
class StitchCylindricalLens : public StitchLens {
|
||||
public:
|
||||
StitchCylindricalLens();
|
||||
|
||||
virtual double get_focal_length(double width_mm) const;
|
||||
virtual double get_hfov(double width_mm) const;
|
||||
virtual double get_vfov(double height_mm) const;
|
||||
|
||||
virtual LVector3d extrude(const LPoint2d &point_mm, double width_mm) const;
|
||||
virtual LPoint2d project(const LVector3d &vec, double width_mm) const;
|
||||
|
||||
LPoint2d project_left(const LVector3d &vec, double width_mm) const;
|
||||
LPoint2d project_right(const LVector3d &vec, double width_mm) const;
|
||||
|
||||
virtual void draw_triangle(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
double width_mm,
|
||||
const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1,
|
||||
const RasterizerVertex *v2);
|
||||
|
||||
virtual void make_lens_command(StitchCommand *parent);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
// Filename: stitchCylindricalScreen.cxx
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchCylindricalScreen.h"
|
||||
#include "deg_2_rad.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCylindricalScreen::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchCylindricalScreen::
|
||||
StitchCylindricalScreen() {
|
||||
// The full-circle range is -pi to pi; we round up here to ensure we
|
||||
// get the full circle.
|
||||
_start_angle = -4.0;
|
||||
_end_angle = 4.0;
|
||||
|
||||
_bottom = -1.0;
|
||||
_top = 1.0;
|
||||
_radius = 1.0;
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCylindricalScreen::set_angle
|
||||
// Access: Public
|
||||
// Description: Sets the angular range of the screen. The range is
|
||||
// in degrees, from -180 to 180, where 0 degrees is
|
||||
// directly ahead, -90 is to the left, and +90 is to the
|
||||
// right.
|
||||
//
|
||||
// If this is unset, the default is a full-circle
|
||||
// cylinder.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchCylindricalScreen::
|
||||
set_angle(double start, double end) {
|
||||
// We store the angles in radians.
|
||||
_start_angle = deg_2_rad(start);
|
||||
_end_angle = deg_2_rad(end);
|
||||
_flags |= F_angle;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCylindricalScreen::set_height
|
||||
// Access: Public
|
||||
// Description: Sets the bottom and top limits of the screen. These
|
||||
// are the heights above (or below) the XY plane for the
|
||||
// bottom edge and top edge of the screen.
|
||||
//
|
||||
// If this is unset, the default is an infinitely tall
|
||||
// cylinder.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchCylindricalScreen::
|
||||
set_height(double bottom, double top) {
|
||||
_bottom = bottom;
|
||||
_top = top;
|
||||
_flags |= F_height;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCylindricalScreen::set_radius
|
||||
// Access: Public
|
||||
// Description: Sets the radius of the screen. The default is 1.0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchCylindricalScreen::
|
||||
set_radius(double radius) {
|
||||
_radius = radius;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchCylindricalScreen::compute_intersect
|
||||
// Access: Protected, Virtual
|
||||
// Description: Computes the intersection point for the ray beginning
|
||||
// at the indicated origin point and continuing in the
|
||||
// indicated direction, to infinity. The return value
|
||||
// is a number >= 0.0 that indicates the parametric
|
||||
// intersection point along the ray with the screen
|
||||
// geometry, or a number < 0.0 if there is no
|
||||
// intersection with the screen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double StitchCylindricalScreen::
|
||||
compute_intersect(const LPoint3d &origin, const LVector3d &direction) const {
|
||||
LPoint3d p = origin * _inv_transform;
|
||||
LVector3d d = direction * _inv_transform;
|
||||
|
||||
// The cylinder is always centered on the origin with its axis
|
||||
// parallel to the Z axis. Project our ray into the XY plane and
|
||||
// determine the point of intersection with the circular
|
||||
// cross-section.
|
||||
|
||||
double Px = p[0];
|
||||
double Py = p[1];
|
||||
double Dx = d[0];
|
||||
double Dy = d[1];
|
||||
|
||||
// Now use the quadratic equation to solve for the intersection of
|
||||
// the line passing thing p2 and (p2+d2), and the circle centered at
|
||||
// the origin with the radius _radius.
|
||||
|
||||
double a = Dx * Dx + Dy * Dy;
|
||||
double b = 2 * (Px * Dx + Py * Dy);
|
||||
double c = Px * Px + Py * Py - _radius * _radius;
|
||||
|
||||
// If the radical is negative, there is no intersection with the
|
||||
// circle.
|
||||
double radical = b * b - 4.0 * a * c;
|
||||
if (radical < 0.0) {
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
// There are two possible intersection points. We have to consider
|
||||
// both, and if both are valid, we return the closer.
|
||||
double sqrt_radical = sqrt(radical);
|
||||
double t1 = (-b + sqrt_radical) / (2.0 * a);
|
||||
double t2 = (-b - sqrt_radical) / (2.0 * a);
|
||||
|
||||
validate_point(t1, p, d);
|
||||
validate_point(t2, p, d);
|
||||
|
||||
if (t1 >= 0.0) {
|
||||
if (t2 >= 0.0) {
|
||||
return min(t1, t2);
|
||||
} else {
|
||||
return t1;
|
||||
}
|
||||
} else {
|
||||
return t2;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the given intersection point defines a point in front of
|
||||
// the ray and on the surface of the cylindrical screen. If it is off
|
||||
// the screen, resets t to -1; otherwise, leaves it alone.
|
||||
void StitchCylindricalScreen::
|
||||
validate_point(double &t,
|
||||
const LPoint3d &origin,
|
||||
const LVector3d &direction) const {
|
||||
// Only test points that are in front of the ray anyway.
|
||||
if (t >= 0.0) {
|
||||
// Now get the 3-d point of intersection.
|
||||
LPoint3d p = origin + direction * t;
|
||||
|
||||
// If this is above the top of the cylinder, or below the bottom
|
||||
// of it, there's no intersection.
|
||||
if ((_flags & F_height) != 0) {
|
||||
if (p[2] < _bottom || p[2] > _top) {
|
||||
t = -1.0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((_flags & F_angle) != 0) {
|
||||
// Project the point into the XY plane and get the angle from
|
||||
// the Y axis, in radians.
|
||||
double angle = atan2(p[0], p[1]);
|
||||
|
||||
// If the angle is outside of the range of the screen, reject it
|
||||
// also.
|
||||
if (angle < _start_angle || angle > _end_angle) {
|
||||
t = -1.0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// Filename: stitchCylindricalScreen.h
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHCYLINDRICALSCREEN_H
|
||||
#define STITCHCYLINDRICALSCREEN_H
|
||||
|
||||
#include "stitchScreen.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchCylindricalScreen
|
||||
// Description : A cylindrical screen shape, axis-aligned with the Z
|
||||
// axis (which is normally the up axis), and with an
|
||||
// arbitrary height and radius. The screen may also
|
||||
// consist of only a portion of the cylinder, specified
|
||||
// by an angle limit.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchCylindricalScreen : public StitchScreen {
|
||||
public:
|
||||
StitchCylindricalScreen();
|
||||
|
||||
void set_angle(double start, double end);
|
||||
void set_height(double bottom, double top);
|
||||
void set_radius(double radius);
|
||||
|
||||
protected:
|
||||
virtual double compute_intersect(const LPoint3d &origin,
|
||||
const LVector3d &direction) const;
|
||||
|
||||
void validate_point(double &t,
|
||||
const LPoint3d &origin,
|
||||
const LVector3d &direction) const;
|
||||
|
||||
private:
|
||||
double _start_angle, _end_angle;
|
||||
double _bottom, _top;
|
||||
double _radius;
|
||||
|
||||
enum {
|
||||
F_angle = 0x001,
|
||||
F_height = 0x002
|
||||
};
|
||||
|
||||
int _flags;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
// Filename: stitchFile.cxx
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchFile.h"
|
||||
#include "stitchImage.h"
|
||||
#include "stitchImageOutputter.h"
|
||||
#include "stitchParserDefs.h"
|
||||
#include "stitchLexerDefs.h"
|
||||
|
||||
StitchFile::
|
||||
StitchFile() {
|
||||
}
|
||||
|
||||
StitchFile::
|
||||
~StitchFile() {
|
||||
}
|
||||
|
||||
bool StitchFile::
|
||||
read(const string &filename) {
|
||||
_root.clear();
|
||||
|
||||
ifstream in(filename.c_str());
|
||||
if (!in) {
|
||||
nout << "Unable to read " << filename << "\n";
|
||||
return false;
|
||||
}
|
||||
stitch_init_parser(in, filename, &_root);
|
||||
stitchyyparse();
|
||||
if (stitch_error_count() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StitchFile::
|
||||
write(ostream &out) const {
|
||||
_root.write(out, 0);
|
||||
}
|
||||
|
||||
void StitchFile::
|
||||
process(StitchImageOutputter &outputter) {
|
||||
_root.process(outputter, (Stitcher *)NULL, *this);
|
||||
outputter.execute();
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Filename: stitchFile.h
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHFILE_H
|
||||
#define STITCHFILE_H
|
||||
|
||||
#include "stitchCommand.h"
|
||||
|
||||
class StitchImage;
|
||||
class StitchImageOutputter;
|
||||
|
||||
class StitchFile {
|
||||
public:
|
||||
StitchFile();
|
||||
~StitchFile();
|
||||
|
||||
bool read(const string &filename);
|
||||
void write(ostream &out) const;
|
||||
|
||||
void process(StitchImageOutputter &outputter);
|
||||
|
||||
StitchCommand _root;
|
||||
};
|
||||
|
||||
inline ostream &operator << (ostream &out, const StitchFile &f) {
|
||||
f.write(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,327 +0,0 @@
|
|||
// Filename: stitchFisheyeLens.cxx
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchFisheyeLens.h"
|
||||
#include "stitchImage.h"
|
||||
#include "stitchCommand.h"
|
||||
#include "triangleRasterizer.h"
|
||||
#include "triangle.h"
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "deg_2_rad.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// This is the focal-length constant for fisheye lenses. The focal
|
||||
// length of a fisheye lens relates to its fov by the equation:
|
||||
|
||||
// w = Fd/k
|
||||
|
||||
// Where w is the width of the negative, F is the focal length, and d
|
||||
// is the total field of view in degrees.
|
||||
|
||||
// k is chosen here by simple examination of a couple of actual lenses
|
||||
// for 35mm film. Don't know how well this extends to other lenses
|
||||
// and other negative sizes.
|
||||
|
||||
static const double fisheye_k = 60.0;
|
||||
|
||||
StitchFisheyeLens::
|
||||
StitchFisheyeLens() {
|
||||
}
|
||||
|
||||
double StitchFisheyeLens::
|
||||
get_focal_length(double width_mm) const {
|
||||
if (_flags & F_focal_length) {
|
||||
return _focal_length;
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
return width_mm * fisheye_k / _fov;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double StitchFisheyeLens::
|
||||
get_hfov(double width_mm) const {
|
||||
if (_flags & F_fov) {
|
||||
return _fov;
|
||||
}
|
||||
if (_flags & F_focal_length) {
|
||||
return width_mm * fisheye_k / _focal_length;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
LVector3d StitchFisheyeLens::
|
||||
extrude(const LPoint2d &point_mm, double width_mm) const {
|
||||
// This operation is essentially a conversion from Cartesian to
|
||||
// polar coordinates.
|
||||
|
||||
// First, get the vector from the center of the film to the point,
|
||||
// and normalize it.
|
||||
LVector2d v2 = point_mm;
|
||||
|
||||
double r = length(v2);
|
||||
if (r == 0.0) {
|
||||
// Special case: directly forward.
|
||||
return LVector3d::forward();
|
||||
}
|
||||
|
||||
v2 /= r;
|
||||
|
||||
// Now get the point r units around the circle in the YZ plane.
|
||||
double dist = r * fisheye_k / get_focal_length(width_mm);
|
||||
LVector3d p(0.0, cos(deg_2_rad(dist)), sin(deg_2_rad(dist)));
|
||||
|
||||
// And rotate this point around the Y axis.
|
||||
LVector3d result = LVector3d::rfu(p[0]*v2[1] + p[2]*v2[0],
|
||||
p[1],
|
||||
p[2]*v2[1] - p[0]*v2[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
LPoint2d StitchFisheyeLens::
|
||||
project(const LVector3d &vec, double width_mm) const {
|
||||
// A fisheye lens projection has the property that the distance from
|
||||
// the center point to any other point on the projection is
|
||||
// proportional to the actual distance on the sphere along the great
|
||||
// circle. Also, the angle to the point on the projection is equal
|
||||
// to the angle to the point on the sphere.
|
||||
|
||||
// First, discard the distance by normalizing the vector.
|
||||
LVector3d v2 = normalize(vec * LMatrix4d::convert_mat(CS_default,
|
||||
CS_zup_right));
|
||||
|
||||
// Now, project the point into the XZ plane and measure its angle
|
||||
// to the Z axis. This is the same angle it will have to the
|
||||
// vertical axis on the film.
|
||||
LVector2d y(v2[0], v2[2]);
|
||||
y = normalize(y);
|
||||
|
||||
if (y == LVector2d(0.0, 0.0)) {
|
||||
// Special case. This point is either directly ahead or directly
|
||||
// behind.
|
||||
return LPoint2d(0.0, 0.0);
|
||||
}
|
||||
|
||||
// Now bring the vector into the YZ plane by rotating about the Y
|
||||
// axis.
|
||||
LVector2d x(v2[1], v2[0]*y[0]+v2[2]*y[1]);
|
||||
x = normalize(x);
|
||||
|
||||
// Now the angle of x to the forward vector represents the distance
|
||||
// along the great circle to the point.
|
||||
double r = 90.0 - rad_2_deg(atan2(x[0], x[1]));
|
||||
|
||||
return y * (r * get_focal_length(width_mm) / fisheye_k);
|
||||
}
|
||||
|
||||
void StitchFisheyeLens::
|
||||
draw_triangle(TriangleRasterizer &rast, const LMatrix3d &,
|
||||
double, const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1, const RasterizerVertex *v2) {
|
||||
// A fisheye lens has a singularity at 180 degrees--this point maps
|
||||
// to the entire outer rim of the circle. Near this singularity,
|
||||
// small distances in space map to very large distances on the film,
|
||||
// meaning that our use of triangles to approximate curvature
|
||||
// becomes very bad near the singularity. Furthermore, triangles
|
||||
// that cross the singularity will be incorrectly drawn across the
|
||||
// entire image on the film.
|
||||
|
||||
// We resolve this by simply not drawing any triangles that come
|
||||
// with a user-specified angle (the _singularity_tolerance) from the
|
||||
// singularity point.
|
||||
|
||||
|
||||
// Determine which quadrant each of the vertices is in. The
|
||||
// triangle crosses the singularity if all vertices' y coordinate is
|
||||
// negative, and if the projection of the triangle into the x, z
|
||||
// plane intersects the origin. It comes within
|
||||
// _singularity_tolerance of the singularity if the projection into
|
||||
// x, z intersects a circle about the origin with radius
|
||||
// _singularity_radius.
|
||||
|
||||
if (dot(v0->_space, LVector3d::forward()) < 0.0 &&
|
||||
dot(v1->_space, LVector3d::forward()) < 0.0 &&
|
||||
dot(v2->_space, LVector3d::forward()) < 0.0) {
|
||||
LPoint2d xz0(dot(v0->_space, LVector3d::right()),
|
||||
dot(v0->_space, LVector3d::up()));
|
||||
LPoint2d xz1(dot(v1->_space, LVector3d::right()),
|
||||
dot(v1->_space, LVector3d::up()));
|
||||
LPoint2d xz2(dot(v2->_space, LVector3d::right()),
|
||||
dot(v2->_space, LVector3d::up()));
|
||||
|
||||
// This projection will reverse the vertex order.
|
||||
if (triangle_contains_circle(LPoint2d(0.0, 0.0),
|
||||
_singularity_radius,
|
||||
xz0, xz2, xz1)) {
|
||||
// The triangle does cross the singularity! Reject it.
|
||||
/*
|
||||
nout << "Rejecting:\n"
|
||||
<< " " << v0->_space << "\n"
|
||||
<< " " << v1->_space << "\n"
|
||||
<< " " << v2->_space << "\n\n";
|
||||
*/
|
||||
_singularity_detected = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
}
|
||||
|
||||
void StitchFisheyeLens::
|
||||
pick_up_singularity(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
const LMatrix3d &pixels_to_mm,
|
||||
const LMatrix3d &rotate,
|
||||
double width_mm, StitchImage *input) {
|
||||
if (_singularity_detected) {
|
||||
nout << "Picking up singularity\n";
|
||||
|
||||
// We will be drawing all the pixels between the circle
|
||||
// representing points 180 degrees from forward, and the circle
|
||||
// represent points (180 - _singularity_tolerance * 2) degrees
|
||||
// from forward.
|
||||
|
||||
double outer_mm =
|
||||
(180 * get_focal_length(width_mm) / fisheye_k);
|
||||
double inner_mm =
|
||||
((180 - _singularity_tolerance * 2) * get_focal_length(width_mm) / fisheye_k);
|
||||
|
||||
int xsize = rast._output->get_x_size();
|
||||
int ysize = rast._output->get_y_size();
|
||||
|
||||
LPoint2d py = LPoint2d(0.0, outer_mm) * mm_to_pixels;
|
||||
int top_y = max((int)floor(py[1]), 0);
|
||||
py = LPoint2d(0.0, -outer_mm) * mm_to_pixels;
|
||||
int bot_y = min((int)ceil(py[1]), ysize - 1);
|
||||
|
||||
py = LPoint2d(0.0, inner_mm) * mm_to_pixels;
|
||||
int inner_top_y = (int)floor(py[1]);
|
||||
py = LPoint2d(0.0, -inner_mm) * mm_to_pixels;
|
||||
int inner_bot_y = (int)ceil(py[1]);
|
||||
|
||||
RasterizerVertex v0;
|
||||
v0._p.set(0.0, 0.0);
|
||||
v0._uv.set(0.0, 0.0);
|
||||
v0._space.set(0.0, 0.0, 0.0);
|
||||
v0._alpha = 1.0;
|
||||
v0._visibility = 0;
|
||||
|
||||
int xi, yi;
|
||||
for (yi = top_y; yi <= bot_y; yi++) {
|
||||
int left_x_1, right_x_1;
|
||||
int left_x_2, right_x_2;
|
||||
|
||||
// Where are the left and right X pixels at this slice?
|
||||
if (yi <= inner_top_y) {
|
||||
// This is the top slice of the ring: between the top of the
|
||||
// outer circle and the top of the inner circle.
|
||||
|
||||
LPoint2d pmm = LPoint2d(0.0, yi) * pixels_to_mm;
|
||||
pmm[0] = sqrt(outer_mm * outer_mm - pmm[1] * pmm[1]);
|
||||
|
||||
LPoint2d px = LPoint2d(-pmm[0], pmm[1]) * mm_to_pixels;
|
||||
left_x_1 = max((int)floor(px[0]), 0);
|
||||
px = LPoint2d(pmm[0], pmm[1]) * mm_to_pixels;
|
||||
right_x_1 = min((int)ceil(px[0]), xsize - 1);
|
||||
|
||||
right_x_2 = right_x_1;
|
||||
left_x_2 = right_x_2 + 1;
|
||||
|
||||
} else if (yi < inner_bot_y) {
|
||||
// This is the inner section: within the inner circle area.
|
||||
// We have both a left and a right section here.
|
||||
|
||||
LPoint2d pmm = LPoint2d(0.0, yi) * pixels_to_mm;
|
||||
pmm[0] = sqrt(outer_mm * outer_mm - pmm[1] * pmm[1]);
|
||||
|
||||
LPoint2d px = LPoint2d(-pmm[0], pmm[1]) * mm_to_pixels;
|
||||
left_x_1 = max((int)floor(px[0]), 0);
|
||||
px = LPoint2d(pmm[0], pmm[1]) * mm_to_pixels;
|
||||
right_x_2 = min((int)ceil(px[0]), xsize - 1);
|
||||
|
||||
pmm[0] = sqrt(inner_mm * inner_mm - pmm[1] * pmm[1]);
|
||||
px = LPoint2d(-pmm[0], pmm[1]) * mm_to_pixels;
|
||||
right_x_1 = max((int)floor(px[0]), 0);
|
||||
px = LPoint2d(pmm[0], pmm[1]) * mm_to_pixels;
|
||||
left_x_2 = min((int)ceil(px[0]), xsize - 1);
|
||||
|
||||
} else {
|
||||
// This is the bottom slice of the ring: between the bottom of
|
||||
// the inner circle and the bottom of the outer circle.
|
||||
|
||||
LPoint2d pmm = LPoint2d(0.0, yi) * pixels_to_mm;
|
||||
pmm[0] = sqrt(outer_mm * outer_mm - pmm[1] * pmm[1]);
|
||||
|
||||
LPoint2d px = LPoint2d(-pmm[0], pmm[1]) * mm_to_pixels;
|
||||
left_x_1 = max((int)floor(px[0]), 0);
|
||||
px = LPoint2d(pmm[0], pmm[1]) * mm_to_pixels;
|
||||
right_x_1 = min((int)ceil(px[0]), xsize - 1);
|
||||
|
||||
right_x_2 = right_x_1;
|
||||
left_x_2 = right_x_2 + 1;
|
||||
|
||||
}
|
||||
|
||||
// Project xi point 1 to determine the radius.
|
||||
v0._p.set(left_x_1 + 1, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
|
||||
for (xi = left_x_1; xi <= right_x_1; xi++) {
|
||||
double last_u = v0._uv[0];
|
||||
|
||||
v0._p.set(xi, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
rast.draw_pixel(&v0, fabs(v0._uv[0] - last_u));
|
||||
}
|
||||
|
||||
// Project xi point 1 to determine the radius.
|
||||
v0._p.set(left_x_2 + 1, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
|
||||
for (xi = left_x_2; xi <= right_x_2; xi++) {
|
||||
double last_u = v0._uv[0];
|
||||
|
||||
v0._p.set(xi, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
rast.draw_pixel(&v0, fabs(v0._uv[0] - last_u));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StitchFisheyeLens::
|
||||
make_lens_command(StitchCommand *parent) {
|
||||
StitchCommand *lens_cmd = new StitchCommand(parent, StitchCommand::C_lens);
|
||||
StitchCommand *cmd;
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_fisheye);
|
||||
if (_flags & F_focal_length) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_focal_length);
|
||||
cmd->set_length(_focal_length);
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_fov);
|
||||
cmd->set_number(_fov);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// Filename: stitchFisheyeLens.h
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHFISHEYELENS_H
|
||||
#define STITCHFISHEYELENS_H
|
||||
|
||||
#include "stitchLens.h"
|
||||
|
||||
class StitchFisheyeLens : public StitchLens {
|
||||
public:
|
||||
StitchFisheyeLens();
|
||||
|
||||
virtual double get_focal_length(double width_mm) const;
|
||||
virtual double get_hfov(double width_mm) const;
|
||||
|
||||
virtual LVector3d extrude(const LPoint2d &point_mm, double width_mm) const;
|
||||
virtual LPoint2d project(const LVector3d &vec, double width_mm) const;
|
||||
|
||||
virtual void draw_triangle(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
double width_mm,
|
||||
const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1,
|
||||
const RasterizerVertex *v2);
|
||||
|
||||
virtual void pick_up_singularity(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
const LMatrix3d &pixels_to_mm,
|
||||
const LMatrix3d &rotate,
|
||||
double width_mm,
|
||||
StitchImage *input);
|
||||
|
||||
virtual void make_lens_command(StitchCommand *parent);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
// Filename: stitchFlatScreen.cxx
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchFlatScreen.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchFlatScreen::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchFlatScreen::
|
||||
StitchFlatScreen() :
|
||||
_plane(LVector3d::back(), LPoint3d::origin() + LVector3d::forward())
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchFlatScreen::set_plane
|
||||
// Access: Public
|
||||
// Description: Specifies the plane that defines the screen. This
|
||||
// plane may, of course, be transformed by whatever
|
||||
// transform matrix is specified via set_transform(),
|
||||
// etc.
|
||||
//
|
||||
// The default plane is one unit along the forward axis,
|
||||
// facing back toward the origin.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchFlatScreen::
|
||||
set_plane(const Planed &plane) {
|
||||
_plane = plane;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchFlatScreen::compute_intersect
|
||||
// Access: Protected, Virtual
|
||||
// Description: Computes the intersection point for the ray beginning
|
||||
// at the indicated origin point and continuing in the
|
||||
// indicated direction, to infinity. The return value
|
||||
// is a number >= 0.0 that indicates the parametric
|
||||
// intersection point along the ray with the screen
|
||||
// geometry, or a number < 0.0 if there is no
|
||||
// intersection with the screen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double StitchFlatScreen::
|
||||
compute_intersect(const LPoint3d &origin, const LVector3d &direction) const {
|
||||
LPoint3d p = origin * _inv_transform;
|
||||
LVector3d d = direction * _inv_transform;
|
||||
|
||||
double t;
|
||||
if (!_plane.intersects_line(t, p, d)) {
|
||||
t = -1.0;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Filename: stitchFlatScreen.h
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHFLATSCREEN_H
|
||||
#define STITCHFLATSCREEN_H
|
||||
|
||||
#include "stitchScreen.h"
|
||||
#include "plane.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchFlatScreen
|
||||
// Description : A simple flat screen. This is really an infinite
|
||||
// plane.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchFlatScreen : public StitchScreen {
|
||||
public:
|
||||
StitchFlatScreen();
|
||||
|
||||
void set_plane(const Planed &plane);
|
||||
|
||||
protected:
|
||||
virtual double compute_intersect(const LPoint3d &origin,
|
||||
const LVector3d &direction) const;
|
||||
|
||||
private:
|
||||
Planed _plane;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,549 +0,0 @@
|
|||
// Filename: stitchImage.cxx
|
||||
// Created by: drose (04Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchImage.h"
|
||||
#include "stitchLens.h"
|
||||
#include "layeredImage.h"
|
||||
#include "fadeImagePool.h"
|
||||
|
||||
#include "compose_matrix.h"
|
||||
#include "rotate_to.h"
|
||||
#include "executionEnvironment.h"
|
||||
|
||||
#include <stdio.h> // for sprintf()
|
||||
|
||||
StitchImage::
|
||||
StitchImage(const string &name, const string &filename,
|
||||
StitchLens *lens, const LVecBase2d &size_pixels,
|
||||
const LVecBase2d &pixels_per_mm,
|
||||
const LVecBase2d &film_offset_mm) :
|
||||
_lens(lens),
|
||||
_size_pixels(size_pixels),
|
||||
_pixels_per_mm(pixels_per_mm),
|
||||
_film_offset_mm(film_offset_mm),
|
||||
_transform(LMatrix4d::ident_mat()),
|
||||
_inv_transform(LMatrix4d::ident_mat()),
|
||||
_name(name)
|
||||
{
|
||||
_filename = ExecutionEnvironment::expand_string(filename);
|
||||
if (_name.empty()) {
|
||||
_name = _filename.get_basename_wo_extension();
|
||||
}
|
||||
|
||||
_size_mm.set((_size_pixels[0] - 1.0) / _pixels_per_mm[0],
|
||||
(_size_pixels[1] - 1.0) / _pixels_per_mm[1]);
|
||||
_orig_size_pixels = _size_pixels;
|
||||
_orig_pixels_per_mm = _pixels_per_mm;
|
||||
|
||||
// There are several coordinate systems to talk about points on the
|
||||
// image.
|
||||
|
||||
// UV's are used for doing most operations. They range from (0, 0)
|
||||
// at the lower-left corner to (1, 1) at the upper-right.
|
||||
|
||||
// Pixels are used when interfacing with the user. They range from
|
||||
// (0, 0) at the upper-left corner to (_size_pixels[0] - 1,
|
||||
// _size_pixels[1] - 1) at the lower-right.
|
||||
|
||||
// Millimeters are used when interfacing with the lens. They start
|
||||
// at film_offset_mm at the center, and range from
|
||||
// film_offset_mm-size_mm at the lower-left, to
|
||||
// film_offset_mm+size_mm at the upper-right.
|
||||
|
||||
/*
|
||||
nout << "_pixels_to_uv * _uv_to_pixels is\n"
|
||||
<< _pixels_to_uv * _uv_to_pixels << "\n"
|
||||
<< "Corners in pixels:\n"
|
||||
<< "ll " << LPoint2d(0.0, 0.0) * _uv_to_pixels
|
||||
<< " lr " << LPoint2d(1.0, 0.0) * _uv_to_pixels
|
||||
<< " ul " << LPoint2d(0.0, 1.0) * _uv_to_pixels
|
||||
<< " ur " << LPoint2d(1.0, 1.0) * _uv_to_pixels << "\n"
|
||||
<< "center " << LPoint2d(0.5, 0.5) * _uv_to_pixels << "\n\n";
|
||||
*/
|
||||
|
||||
LVector2d mm_per_uv = get_size_mm();
|
||||
|
||||
_uv_to_mm =
|
||||
LMatrix3d::translate_mat(LVector2d(-0.5, -0.5)) *
|
||||
LMatrix3d::scale_mat(mm_per_uv) *
|
||||
LMatrix3d::translate_mat(_film_offset_mm);
|
||||
|
||||
_mm_to_uv =
|
||||
LMatrix3d::translate_mat(-_film_offset_mm) *
|
||||
LMatrix3d::scale_mat(1.0 / mm_per_uv[0], 1.0 / mm_per_uv[1]) *
|
||||
LMatrix3d::translate_mat(LVector2d(0.5, 0.5));
|
||||
|
||||
setup_pixel_scales();
|
||||
|
||||
_show_points = false;
|
||||
setup_grid(2, 2);
|
||||
|
||||
_data = NULL;
|
||||
_untextured_color.set(1.0, 1.0, 1.0, 1.0);
|
||||
_index = 0;
|
||||
_hpr_set = false;
|
||||
_pos_set = false;
|
||||
_hpr.set(0.0, 0.0, 0.0);
|
||||
_pos.set(0.0, 0.0, 0.0);
|
||||
_layered_type = LT_flat;
|
||||
_layer_index = 0;
|
||||
_layered_image = NULL;
|
||||
|
||||
if (_filename.get_extension() == "xcf") {
|
||||
_layered_type = LT_combined;
|
||||
}
|
||||
}
|
||||
|
||||
bool StitchImage::
|
||||
has_name() const {
|
||||
return !_name.empty();
|
||||
}
|
||||
|
||||
string StitchImage::
|
||||
get_name() const {
|
||||
if (_name.empty()) {
|
||||
return _filename.get_basename_wo_extension();
|
||||
}
|
||||
return _name;
|
||||
}
|
||||
|
||||
bool StitchImage::
|
||||
has_filename() const {
|
||||
return !_filename.empty();
|
||||
}
|
||||
|
||||
string StitchImage::
|
||||
get_filename() const {
|
||||
return _filename.get_fullpath();
|
||||
}
|
||||
|
||||
bool StitchImage::
|
||||
has_fade_filename() const {
|
||||
return !_fade_filename.empty();
|
||||
}
|
||||
|
||||
string StitchImage::
|
||||
get_fade_filename() const {
|
||||
return _fade_filename.get_fullpath();
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
set_fade_filename(const Filename &filename) {
|
||||
_fade_filename = filename;
|
||||
}
|
||||
|
||||
bool StitchImage::
|
||||
read_file() {
|
||||
if (_data != NULL) {
|
||||
// The data is already available; no need to re-read it.
|
||||
return true;
|
||||
}
|
||||
if (!has_filename()) {
|
||||
return false;
|
||||
}
|
||||
_data = new PNMImage;
|
||||
nout << "Reading " << _filename << "\n";
|
||||
bool result = _data->read(_filename);
|
||||
if (!result) {
|
||||
delete _data;
|
||||
_data = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
clear_file() {
|
||||
if (_data != NULL) {
|
||||
delete _data;
|
||||
_data = NULL;
|
||||
}
|
||||
if (_layered_image != NULL) {
|
||||
delete _layered_image;
|
||||
_layered_image = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
open_output_file() {
|
||||
clear_file();
|
||||
if (_layered_type == LT_flat) {
|
||||
_data = new PNMImage(_size_pixels[0], _size_pixels[1], 4);
|
||||
|
||||
} else if (_layered_type == LT_combined) {
|
||||
_layered_image = new LayeredImage(_size_pixels[0], _size_pixels[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
open_layer(const string &layer_name) {
|
||||
_layer_name = layer_name;
|
||||
|
||||
if (_layered_type == LT_separate || _layered_type == LT_combined) {
|
||||
_data = new PNMImage(_size_pixels[0], _size_pixels[1], 4);
|
||||
}
|
||||
}
|
||||
|
||||
bool StitchImage::
|
||||
close_layer(bool nonempty) {
|
||||
bool result = true;
|
||||
|
||||
if (_layered_type == LT_separate) {
|
||||
if (_data == NULL) {
|
||||
result = false;
|
||||
} else {
|
||||
if (nonempty) {
|
||||
char buff[1024];
|
||||
_layer_index++;
|
||||
sprintf(buff, _filename.c_str(), _layer_index);
|
||||
nout << "Writing layer " << _layer_name << " as " << buff << "\n";
|
||||
resize_data();
|
||||
result = _data->write(buff);
|
||||
}
|
||||
}
|
||||
clear_file();
|
||||
|
||||
} else if (_layered_type == LT_combined) {
|
||||
if (_data == NULL) {
|
||||
result = false;
|
||||
} else {
|
||||
if (nonempty) {
|
||||
resize_data();
|
||||
_layered_image->add_layer(_layer_name, LVector2d(0.0, 0.0),
|
||||
_data);
|
||||
_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool StitchImage::
|
||||
close_output_file() {
|
||||
bool result = true;
|
||||
|
||||
if (_layered_type == LT_separate) {
|
||||
|
||||
} else if (_layered_type == LT_combined) {
|
||||
if (_layered_image == NULL) {
|
||||
result = false;
|
||||
} else {
|
||||
nout << "Writing " << _filename << "\n";
|
||||
result = _layered_image->write_file(_filename);
|
||||
}
|
||||
|
||||
} else { // _layered_type == LT_flat
|
||||
if (_data == NULL) {
|
||||
result = false;
|
||||
} else {
|
||||
resize_data();
|
||||
if (has_fade_filename()) {
|
||||
fade_out();
|
||||
}
|
||||
nout << "Writing " << _filename << "\n";
|
||||
result = _data->write(_filename);
|
||||
}
|
||||
}
|
||||
|
||||
clear_file();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void StitchImage::
|
||||
clear_transform() {
|
||||
_transform = LMatrix3d::ident_mat();
|
||||
_inv_transform = LMatrix3d::ident_mat();
|
||||
_hpr_set = false;
|
||||
_pos_set = false;
|
||||
_hpr.set(0.0, 0.0, 0.0);
|
||||
_pos.set(0.0, 0.0, 0.0);
|
||||
_morph.clear();
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
set_transform(const LMatrix4d &trans) {
|
||||
_transform = trans;
|
||||
_inv_transform = invert(trans);
|
||||
LVecBase3d scale;
|
||||
decompose_matrix(_transform, scale, _hpr, _pos);
|
||||
_hpr_set = false;
|
||||
_pos_set = false;
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
set_hpr(const LVecBase3d &hpr) {
|
||||
compose_matrix(_transform, LVecBase3d(1.0, 1.0, 1.0), hpr, _pos);
|
||||
_inv_transform.invert_from(_transform);
|
||||
_hpr_set = true;
|
||||
_hpr = hpr;
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
set_pos(const LPoint3d &pos) {
|
||||
compose_matrix(_transform, LVecBase3d(1.0, 1.0, 1.0), _hpr, pos);
|
||||
_inv_transform.invert_from(_transform);
|
||||
_pos_set = true;
|
||||
_pos = pos;
|
||||
}
|
||||
|
||||
const LVecBase3d &StitchImage::
|
||||
get_hpr() const {
|
||||
return _hpr;
|
||||
}
|
||||
|
||||
const LPoint3d &StitchImage::
|
||||
get_pos() const {
|
||||
return _pos;
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
show_points(double radius, const Colord &color) {
|
||||
_show_points = true;
|
||||
_point_radius = radius;
|
||||
_point_color = color;
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
setup_grid(int x_verts, int y_verts) {
|
||||
_x_verts = x_verts;
|
||||
_y_verts = y_verts;
|
||||
}
|
||||
|
||||
int StitchImage::
|
||||
get_x_verts() const {
|
||||
return _x_verts;
|
||||
}
|
||||
|
||||
int StitchImage::
|
||||
get_y_verts() const {
|
||||
return _y_verts;
|
||||
}
|
||||
|
||||
LPoint2d StitchImage::
|
||||
get_grid_uv(int xv, int yv) {
|
||||
return LPoint2d((double)xv / (double)(_x_verts - 1),
|
||||
1.0 - (double)yv / (double)(_y_verts - 1));
|
||||
|
||||
}
|
||||
|
||||
LVector3d StitchImage::
|
||||
get_grid_vector(int xv, int yv) {
|
||||
return extrude(get_grid_uv(xv, yv));
|
||||
}
|
||||
|
||||
double StitchImage::
|
||||
get_grid_alpha(int xv, int yv) {
|
||||
return get_alpha(get_grid_uv(xv, yv));
|
||||
}
|
||||
|
||||
const LVecBase2d &StitchImage::
|
||||
get_size_pixels() const {
|
||||
return _size_pixels;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImage::set_size_pixels
|
||||
// Access: Public
|
||||
// Description: Redefines the image to be the indicated size in
|
||||
// pixels, without changing its size in mm.
|
||||
//
|
||||
// This may only be called before open_output_file() has
|
||||
// been called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImage::
|
||||
set_size_pixels(const LVecBase2d &size_pixels) {
|
||||
assert(_data == (PNMImage *)NULL);
|
||||
|
||||
_size_pixels = size_pixels;
|
||||
_orig_size_pixels = _size_pixels;
|
||||
_pixels_per_mm.set((_size_pixels[0] - 1.0) / _size_mm[0],
|
||||
(_size_pixels[1] - 1.0) / _size_mm[1]);
|
||||
}
|
||||
|
||||
LVecBase2d StitchImage::
|
||||
get_size_mm() const {
|
||||
return _size_mm;
|
||||
}
|
||||
|
||||
LVector3d StitchImage::
|
||||
extrude(const LPoint2d &point_uv) const {
|
||||
LPoint2d p = _morph.morph_out(point_uv);
|
||||
return _lens->extrude(p * _uv_to_mm, _size_mm[0]) * _transform;
|
||||
}
|
||||
|
||||
LPoint2d StitchImage::
|
||||
project(const LVector3d &vec) const {
|
||||
LPoint2d m = _lens->project(vec * _inv_transform, _size_mm[0]);
|
||||
return _morph.morph_in(m * _mm_to_uv);
|
||||
}
|
||||
|
||||
double StitchImage::
|
||||
get_alpha(const LPoint2d &point_uv) const {
|
||||
return _morph.get_alpha(point_uv);
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
reset_singularity_detected() {
|
||||
_lens->reset_singularity_detected();
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
draw_triangle(TriangleRasterizer &rast, const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1, const RasterizerVertex *v2) {
|
||||
_lens->draw_triangle(rast, _mm_to_pixels, _size_mm[0], v0, v1, v2);
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
pick_up_singularity(TriangleRasterizer &rast, StitchImage *input) {
|
||||
_lens->pick_up_singularity(rast, _mm_to_pixels, _pixels_to_mm,
|
||||
_transform.get_upper_3(), _size_mm[0], input);
|
||||
}
|
||||
|
||||
void StitchImage::
|
||||
add_point(const string &name, const LPoint2d &pixel) {
|
||||
_points[name] = pixel * _pixels_to_uv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImage::set_output_scale_factor
|
||||
// Access: Private
|
||||
// Description: Sets up the image to inflate its output image by the
|
||||
// given factor in each dimension during rasterization,
|
||||
// and then reduce it back to its original size just
|
||||
// before writing it out, as a poor man's pixel filter.
|
||||
//
|
||||
// This may only be called before open_output_file() has
|
||||
// been called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImage::
|
||||
set_output_scale_factor(double factor) {
|
||||
assert(_data == (PNMImage *)NULL);
|
||||
|
||||
_size_pixels = _orig_size_pixels * factor;
|
||||
_pixels_per_mm = _orig_pixels_per_mm * factor;
|
||||
setup_pixel_scales();
|
||||
}
|
||||
|
||||
|
||||
void StitchImage::
|
||||
output(ostream &out) const {
|
||||
out << "image " << get_name() << ":\n"
|
||||
<< get_size_pixels() << " pixels, or " << get_size_mm()
|
||||
<< " mm\n";
|
||||
|
||||
LVecBase3d scale, hpr, trans;
|
||||
if (decompose_matrix(_transform, scale, hpr, trans)) {
|
||||
if (!scale.almost_equal(LVecBase3d(1.0, 1.0, 1.0))) {
|
||||
out << "scale " << scale << "\n";
|
||||
}
|
||||
out << "hpr " << hpr << "\n";
|
||||
if (!trans.almost_equal(LVecBase3d::zero())) {
|
||||
out << "translate " << trans << "\n";
|
||||
}
|
||||
} else {
|
||||
out << "Invalid transform:\n";
|
||||
_transform.write(out);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImage::setup_pixel_scales
|
||||
// Access: Private
|
||||
// Description: Sets up the pixel-based transform matrices, according
|
||||
// to _pixel_size and _pixels_per_mm.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImage::
|
||||
setup_pixel_scales() {
|
||||
LVector2d pixels_per_uv(_size_pixels[0] - 1.0, _size_pixels[1] - 1.0);
|
||||
|
||||
_pixels_to_uv =
|
||||
LMatrix3d::translate_mat(LVector2d(0.0, -pixels_per_uv[1])) *
|
||||
LMatrix3d::scale_mat(1.0 / pixels_per_uv[0], -1.0 / pixels_per_uv[1]);
|
||||
|
||||
_uv_to_pixels =
|
||||
LMatrix3d::scale_mat(pixels_per_uv[0], -pixels_per_uv[1]) *
|
||||
LMatrix3d::translate_mat(LVector2d(0.0, pixels_per_uv[1]));
|
||||
|
||||
_pixels_to_mm = _pixels_to_uv * _uv_to_mm;
|
||||
_mm_to_pixels = _mm_to_uv * _uv_to_pixels;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImage::resize_data
|
||||
// Access: Private
|
||||
// Description: Resizes the image generated in _data back to
|
||||
// _orig_size_pixels, if it has been generated larger,
|
||||
// in preparation to writing it out.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImage::
|
||||
resize_data() {
|
||||
assert(_data != (PNMImage *)NULL);
|
||||
if (_orig_size_pixels == _size_pixels) {
|
||||
return;
|
||||
}
|
||||
|
||||
PNMImage *reduced =
|
||||
new PNMImage(_orig_size_pixels[0], _orig_size_pixels[1],
|
||||
_data->get_color_type());
|
||||
|
||||
cerr << "Filtering to " << reduced->get_x_size() << " by "
|
||||
<< reduced->get_y_size() << "\n";
|
||||
|
||||
reduced->box_filter_from(0.5, *_data);
|
||||
delete _data;
|
||||
_data = reduced;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImage::fade_out
|
||||
// Access: Private
|
||||
// Description: Fades out the image (presumably at the edges) by
|
||||
// multiplying each pixel by the corresponding pixel in
|
||||
// the named fade image.
|
||||
//
|
||||
// This is generally useful for generating output images
|
||||
// that are intended to overlap meaningfully, for
|
||||
// instance when projected through overlapping
|
||||
// projectors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImage::
|
||||
fade_out() {
|
||||
assert(_data != (PNMImage *)NULL);
|
||||
|
||||
const PNMImage *fade =
|
||||
FadeImagePool::get_image(get_fade_filename(),
|
||||
_data->get_x_size(), _data->get_y_size());
|
||||
if (fade == (PNMImage *)NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now apply the fade factor to darken each of our pixels.
|
||||
cerr << "Applying fade image.\n";
|
||||
for (int y = 0; y < _data->get_y_size(); y++) {
|
||||
for (int x = 0; x < _data->get_x_size(); x++) {
|
||||
// Because we know the fade image is guaranteed to be grayscale,
|
||||
// we can simply ask for its gray component rather than
|
||||
// computing its bright component.
|
||||
double bright = fade->get_gray(x, y);
|
||||
_data->set_red_val(x, y, (xelval)_data->get_red_val(x, y) * bright);
|
||||
_data->set_green_val(x, y, (xelval)_data->get_green_val(x, y) * bright);
|
||||
_data->set_blue_val(x, y, (xelval)_data->get_blue_val(x, y) * bright);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
// Filename: stitchImage.h
|
||||
// Created by: drose (04Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHIMAGE_H
|
||||
#define STITCHIMAGE_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "stitchPoint.h"
|
||||
#include "morphGrid.h"
|
||||
|
||||
#include <lmatrix.h>
|
||||
#include "luse.h"
|
||||
#include <pnmImage.h>
|
||||
#include "filename.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class StitchLens;
|
||||
class TriangleRasterizer;
|
||||
class RasterizerVertex;
|
||||
class LayeredImage;
|
||||
|
||||
class StitchImage {
|
||||
public:
|
||||
StitchImage(const string &name, const string &filename,
|
||||
StitchLens *lens,
|
||||
const LVecBase2d &size_pixels,
|
||||
const LVecBase2d &pixels_per_mm,
|
||||
const LVecBase2d &film_offset_mm);
|
||||
|
||||
bool has_name() const;
|
||||
string get_name() const;
|
||||
bool has_filename() const;
|
||||
string get_filename() const;
|
||||
bool has_fade_filename() const;
|
||||
string get_fade_filename() const;
|
||||
void set_fade_filename(const Filename &filename);
|
||||
|
||||
// This function reads the image file if it is available.
|
||||
bool read_file();
|
||||
void clear_file();
|
||||
|
||||
// These functions handle the writing of the image file.
|
||||
// open_output_file() should be called first. open_layer() and
|
||||
// close_layer() should be called in pairs; after a call to
|
||||
// open_layer(), the _data member is guaranteed to contain a
|
||||
// PNMImage that may be empty or may contain the contents of
|
||||
// previous layers. close_layer() should be called as each layer is
|
||||
// filled, and close_output_file() should be called when the image
|
||||
// is completely done.
|
||||
void open_output_file();
|
||||
void open_layer(const string &layer_name);
|
||||
bool close_layer(bool nonempty);
|
||||
bool close_output_file();
|
||||
|
||||
void clear_transform();
|
||||
void set_transform(const LMatrix4d &transform);
|
||||
void set_hpr(const LVecBase3d &hpr);
|
||||
void set_pos(const LPoint3d &pos);
|
||||
const LVecBase3d &get_hpr() const;
|
||||
const LPoint3d &get_pos() const;
|
||||
|
||||
void show_points(double radius, const Colord &color);
|
||||
void setup_grid(int x_verts, int y_verts);
|
||||
int get_x_verts() const;
|
||||
int get_y_verts() const;
|
||||
|
||||
LPoint2d get_grid_uv(int xv, int yv);
|
||||
LPoint2d get_grid_pixel(int xv, int yv);
|
||||
LVector3d get_grid_vector(int xv, int yv);
|
||||
double get_grid_alpha(int xv, int yv);
|
||||
|
||||
const LVecBase2d &get_size_pixels() const;
|
||||
void set_size_pixels(const LVecBase2d &size_pixels);
|
||||
LVecBase2d get_size_mm() const;
|
||||
|
||||
LVector3d extrude(const LPoint2d &point_uv) const;
|
||||
LPoint2d project(const LVector3d &vec) const;
|
||||
double get_alpha(const LPoint2d &point_uv) const;
|
||||
|
||||
void reset_singularity_detected();
|
||||
|
||||
// This function simply passes the indicated triangle on to the
|
||||
// rasterizer. It exists here in the lens so that the lens may do
|
||||
// something special if the triangle crosses a seam or singularity
|
||||
// in the lens' coordinate space.
|
||||
void draw_triangle(TriangleRasterizer &rast,
|
||||
const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1,
|
||||
const RasterizerVertex *v2);
|
||||
|
||||
// This function is to be called after all triangles have been
|
||||
// drawn; it will draw pixel-by-pixel all the points within
|
||||
// _singularity_radius of any singularity points the lens may have
|
||||
// (these points were not draw by draw_triangle(), above).
|
||||
void pick_up_singularity(TriangleRasterizer &rast,
|
||||
StitchImage *input);
|
||||
|
||||
void add_point(const string &name, const LPoint2d &pixel);
|
||||
void set_output_scale_factor(double factor);
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
PNMImage *_data;
|
||||
StitchLens *_lens;
|
||||
LVecBase2d _size_pixels, _size_mm;
|
||||
LVecBase2d _pixels_per_mm;
|
||||
LVecBase2d _film_offset_mm;
|
||||
LMatrix3d _mm_to_uv, _uv_to_mm;
|
||||
LMatrix3d _pixels_to_mm, _mm_to_pixels;
|
||||
LMatrix3d _pixels_to_uv, _uv_to_pixels;
|
||||
bool _hpr_set;
|
||||
LVecBase3d _hpr;
|
||||
bool _pos_set;
|
||||
LPoint3d _pos;
|
||||
|
||||
enum LayeredType {
|
||||
LT_flat, // One flat image--no layers.
|
||||
LT_separate, // A separate image file for each layer.
|
||||
LT_combined, // A single image file with multiple layers.
|
||||
};
|
||||
LayeredType _layered_type;
|
||||
|
||||
bool _show_points;
|
||||
double _point_radius;
|
||||
Colord _point_color;
|
||||
Colord _untextured_color;
|
||||
|
||||
typedef map<string, LPoint2d> Points;
|
||||
Points _points;
|
||||
LMatrix4d _transform, _inv_transform;
|
||||
MorphGrid _morph;
|
||||
|
||||
// This index number is filled in by the Stitcher. It allows us to
|
||||
// sort the images in order as they are specified in the command
|
||||
// file.
|
||||
int _index;
|
||||
|
||||
private:
|
||||
void setup_pixel_scales();
|
||||
void resize_data();
|
||||
void fade_out();
|
||||
|
||||
private:
|
||||
Filename _filename;
|
||||
Filename _fade_filename;
|
||||
string _name;
|
||||
|
||||
int _x_verts, _y_verts;
|
||||
int _layer_index;
|
||||
string _layer_name;
|
||||
LayeredImage *_layered_image;
|
||||
LVecBase2d _orig_size_pixels;
|
||||
LVecBase2d _orig_pixels_per_mm;
|
||||
};
|
||||
|
||||
inline ostream &operator << (ostream &out, const StitchImage &i) {
|
||||
i.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// An STL function object to sort image pointers by index number.
|
||||
class StitchImageByIndex {
|
||||
public:
|
||||
bool operator()(const StitchImage *a, const StitchImage *b) const {
|
||||
return a->_index < b->_index;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
// Filename: stitchImageCommandOutput.cxx
|
||||
// Created by: drose (29Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchImageCommandOutput.h"
|
||||
#include "stitchImage.h"
|
||||
#include "stitchLens.h"
|
||||
#include "stitcher.h"
|
||||
#include "stitchCommand.h"
|
||||
|
||||
#include "pnmImage.h"
|
||||
#include "compose_matrix.h"
|
||||
|
||||
StitchImageCommandOutput::
|
||||
StitchImageCommandOutput() {
|
||||
}
|
||||
|
||||
|
||||
void StitchImageCommandOutput::
|
||||
add_input_image(StitchImage *image) {
|
||||
_input_images.push_back(image);
|
||||
}
|
||||
|
||||
void StitchImageCommandOutput::
|
||||
add_output_image(StitchImage *image) {
|
||||
_output_images.push_back(image);
|
||||
}
|
||||
|
||||
void StitchImageCommandOutput::
|
||||
add_stitcher(Stitcher *stitcher) {
|
||||
_stitchers.push_back(stitcher);
|
||||
}
|
||||
|
||||
void StitchImageCommandOutput::
|
||||
execute() {
|
||||
StitchCommand root;
|
||||
|
||||
Stitchers::const_iterator si;
|
||||
for (si = _stitchers.begin(); si != _stitchers.end(); ++si) {
|
||||
Stitcher *stitcher = (*si);
|
||||
Stitcher::LoosePoints::const_iterator pi;
|
||||
for (pi = stitcher->_loose_points.begin();
|
||||
pi != stitcher->_loose_points.end();
|
||||
++pi) {
|
||||
StitchCommand *cmd = new StitchCommand(&root, StitchCommand::C_point3d);
|
||||
cmd->set_name((*pi)->_name);
|
||||
cmd->set_point3d((*pi)->_space);
|
||||
}
|
||||
}
|
||||
|
||||
Images::const_iterator ii;
|
||||
for (ii = _input_images.begin(); ii != _input_images.end(); ++ii) {
|
||||
StitchImage *input = (*ii);
|
||||
StitchCommand *image_cmd = new StitchCommand(&root, StitchCommand::C_input_image);
|
||||
fill_image_cmd(image_cmd, input);
|
||||
}
|
||||
|
||||
for (ii = _output_images.begin(); ii != _output_images.end(); ++ii) {
|
||||
StitchImage *output = (*ii);
|
||||
StitchCommand *image_cmd = new StitchCommand(&root, StitchCommand::C_output_image);
|
||||
fill_image_cmd(image_cmd, output);
|
||||
}
|
||||
|
||||
cout << root << "\n";
|
||||
}
|
||||
|
||||
void StitchImageCommandOutput::
|
||||
fill_image_cmd(StitchCommand *image_cmd, StitchImage *image) {
|
||||
if (image->has_name()) {
|
||||
image_cmd->set_name(image->get_name());
|
||||
}
|
||||
|
||||
StitchCommand *cmd;
|
||||
cmd = new StitchCommand(image_cmd, StitchCommand::C_filename);
|
||||
cmd->set_str(image->get_filename());
|
||||
|
||||
cmd = new StitchCommand(image_cmd, StitchCommand::C_image_size);
|
||||
cmd->set_point2d(image->get_size_pixels());
|
||||
|
||||
cmd = new StitchCommand(image_cmd, StitchCommand::C_film_size);
|
||||
cmd->set_length_pair(image->get_size_mm());
|
||||
|
||||
image->_lens->make_lens_command(image_cmd);
|
||||
|
||||
LVecBase3d scale, hpr, trans;
|
||||
if (decompose_matrix(image->_transform, scale, hpr, trans)) {
|
||||
cmd = new StitchCommand(image_cmd, StitchCommand::C_hpr);
|
||||
cmd->set_point3d(hpr);
|
||||
|
||||
//**** Do something with translate here.
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// Filename: stitchImageCommandOutput.h
|
||||
// Created by: drose (29Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHIMAGECOMMANDOUTPUT_H
|
||||
#define STITCHIMAGECOMMANDOUTPUT_H
|
||||
|
||||
#include "stitchImageOutputter.h"
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
class Stitcher;
|
||||
class StitchImage;
|
||||
class StitchCommand;
|
||||
|
||||
class StitchImageCommandOutput : public StitchImageOutputter {
|
||||
public:
|
||||
StitchImageCommandOutput();
|
||||
|
||||
virtual void add_input_image(StitchImage *image);
|
||||
virtual void add_output_image(StitchImage *image);
|
||||
virtual void add_stitcher(Stitcher *stitcher);
|
||||
|
||||
virtual void execute();
|
||||
|
||||
protected:
|
||||
void fill_image_cmd(StitchCommand *image_cmd, StitchImage *image);
|
||||
|
||||
typedef vector<StitchImage *> Images;
|
||||
Images _input_images;
|
||||
Images _output_images;
|
||||
|
||||
typedef vector<Stitcher *> Stitchers;
|
||||
Stitchers _stitchers;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// Filename: stitchImageOutputter.cxx
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchImageOutputter.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageOutputter::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchImageOutputter::
|
||||
StitchImageOutputter() {
|
||||
_screen = new StitchMultiScreen;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageOutputter::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchImageOutputter::
|
||||
~StitchImageOutputter() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageOutputter::add_screen
|
||||
// Access: Public
|
||||
// Description: Adds a screen to the list of screens projected onto.
|
||||
// If there are no screens, the default is to project
|
||||
// the images to infinity; otherwise, the screens are
|
||||
// used.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageOutputter::
|
||||
add_screen(StitchScreen *screen) {
|
||||
_screen->add_screen(screen);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageOutputter::set_eyepoint
|
||||
// Access: Public, Virtual
|
||||
// Description: Sets the eye point to the indicated coordinate frame,
|
||||
// if it makes sense to this kind of outputter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageOutputter::
|
||||
set_eyepoint(const LMatrix4d &) {
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// Filename: stitchImageOutputter.h
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHIMAGEOUTPUTTER_H
|
||||
#define STITCHIMAGEOUTPUTTER_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "stitchMultiScreen.h"
|
||||
#include "luse.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
class StitchImage;
|
||||
class Stitcher;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchImageOutputter
|
||||
// Description : This is an abstract base class defining the interface
|
||||
// to accept a number of input images and process them,
|
||||
// possibly stitching them together based on their
|
||||
// points in common, and then generating a number of
|
||||
// output images.
|
||||
//
|
||||
// This is the highest level of interaction with this
|
||||
// module; it corresponds to the action performed by a
|
||||
// stitch-image, stitch-viewer, or stitch-command
|
||||
// program (and the distinction between the three
|
||||
// programs is primarily a question of which
|
||||
// specialization of StitchImageOutputter they use).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchImageOutputter {
|
||||
public:
|
||||
StitchImageOutputter();
|
||||
virtual ~StitchImageOutputter();
|
||||
|
||||
virtual void add_input_image(StitchImage *image)=0;
|
||||
virtual void add_output_image(StitchImage *image)=0;
|
||||
virtual void add_stitcher(Stitcher *stitcher)=0;
|
||||
void add_screen(StitchScreen *screen);
|
||||
|
||||
virtual void set_eyepoint(const LMatrix4d &mat);
|
||||
|
||||
virtual void execute()=0;
|
||||
|
||||
protected:
|
||||
PT(StitchMultiScreen) _screen;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,366 +0,0 @@
|
|||
// Filename: stitchImageRasterizer.cxx
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchImageRasterizer.h"
|
||||
#include "triangleRasterizer.h"
|
||||
#include "stitchImage.h"
|
||||
#include "stitcher.h"
|
||||
|
||||
#include "pnmImage.h"
|
||||
|
||||
StitchImageRasterizer::
|
||||
StitchImageRasterizer() {
|
||||
_filter_factor = 1.0;
|
||||
_got_output_size = false;
|
||||
}
|
||||
|
||||
|
||||
void StitchImageRasterizer::
|
||||
add_input_image(StitchImage *image) {
|
||||
if (has_input_name(image->get_name())) {
|
||||
cerr << "Input image " << image->get_name() << "\n";
|
||||
_input_images.push_back(image);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchImageRasterizer::
|
||||
add_output_image(StitchImage *image) {
|
||||
if (has_output_name(image->get_name())) {
|
||||
cerr << "Output image " << image->get_name() << "\n";
|
||||
if (_got_output_size) {
|
||||
image->set_size_pixels(LPoint2d(_output_xsize, _output_ysize));
|
||||
}
|
||||
image->set_output_scale_factor(_filter_factor);
|
||||
_output_images.push_back(image);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchImageRasterizer::
|
||||
add_stitcher(Stitcher *stitcher) {
|
||||
_stitchers.push_back(stitcher);
|
||||
}
|
||||
|
||||
void StitchImageRasterizer::
|
||||
execute() {
|
||||
Images::iterator oi;
|
||||
for (oi = _output_images.begin(); oi != _output_images.end(); ++oi) {
|
||||
StitchImage *output = (*oi);
|
||||
if (!output->has_filename()) {
|
||||
nout << "Output image has no filename; cannot generate.\n";
|
||||
} else {
|
||||
nout << "Generating " << output->get_name() << "\n";
|
||||
output->open_output_file();
|
||||
|
||||
Images::const_iterator ii;
|
||||
for (ii = _input_images.begin(); ii != _input_images.end(); ++ii) {
|
||||
StitchImage *input = (*ii);
|
||||
draw_image(output, input);
|
||||
}
|
||||
|
||||
output->open_layer("points");
|
||||
bool shown_points = false;
|
||||
Stitchers::const_iterator si;
|
||||
for (si = _stitchers.begin(); si != _stitchers.end(); ++si) {
|
||||
Stitcher *stitcher = (*si);
|
||||
if (stitcher->_show_points && !stitcher->_loose_points.empty()) {
|
||||
draw_points(output, stitcher, stitcher->_point_color,
|
||||
stitcher->_point_radius);
|
||||
shown_points = true;
|
||||
}
|
||||
}
|
||||
for (ii = _input_images.begin(); ii != _input_images.end(); ++ii) {
|
||||
StitchImage *input = (*ii);
|
||||
if (input->_show_points && !input->_points.empty()) {
|
||||
draw_points(output, input, input->_point_color,
|
||||
input->_point_radius);
|
||||
shown_points = true;
|
||||
}
|
||||
}
|
||||
output->close_layer(shown_points);
|
||||
|
||||
if (!output->close_output_file()) {
|
||||
nout << "Error in writing.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageRasterizer::add_input_name
|
||||
// Access: Public
|
||||
// Description: Adds the indicated name to the set of input image
|
||||
// names that will be generated. The name may include
|
||||
// globbing symbols. If no names are added, all input
|
||||
// images will be generated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageRasterizer::
|
||||
add_input_name(const string &name) {
|
||||
_input_names.push_back(GlobPattern(name));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageRasterizer::has_input_name
|
||||
// Access: Public
|
||||
// Description: Returns true if the indicated input image name is
|
||||
// one that should be generated. This will be true if
|
||||
// this name has been added via add_input_name(), or if
|
||||
// no names at all have been added.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchImageRasterizer::
|
||||
has_input_name(const string &name) const {
|
||||
if (_input_names.empty()) {
|
||||
// If no names have been added, all names are good.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, the name is good only if it matches a name on the list.
|
||||
Names::const_iterator ni;
|
||||
for (ni = _input_names.begin(); ni != _input_names.end(); ++ni) {
|
||||
if ((*ni).matches(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageRasterizer::add_output_name
|
||||
// Access: Public
|
||||
// Description: Adds the indicated name to the set of output image
|
||||
// names that will be generated. The name may include
|
||||
// globbing symbols. If no names are added, all output
|
||||
// images will be generated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageRasterizer::
|
||||
add_output_name(const string &name) {
|
||||
_output_names.push_back(GlobPattern(name));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageRasterizer::has_output_name
|
||||
// Access: Public
|
||||
// Description: Returns true if the indicated output image name is
|
||||
// one that should be generated. This will be true if
|
||||
// this name has been added via add_output_name(), or if
|
||||
// no names at all have been added.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchImageRasterizer::
|
||||
has_output_name(const string &name) const {
|
||||
if (_output_names.empty()) {
|
||||
// If no names have been added, all names are good.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, the name is good only if it matches a name on the list.
|
||||
Names::const_iterator ni;
|
||||
for (ni = _output_names.begin(); ni != _output_names.end(); ++ni) {
|
||||
if ((*ni).matches(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageRasterizer::set_filter_factor
|
||||
// Access: Public
|
||||
// Description: Sets the factor by which the output images will be
|
||||
// scaled internally in each dimension while generating
|
||||
// them. They will be reduced again to their original
|
||||
// size for writing the images out. This provides a
|
||||
// simple kind of pixel filtering.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageRasterizer::
|
||||
set_filter_factor(double filter_factor) {
|
||||
_filter_factor = filter_factor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageRasterizer::set_output_size
|
||||
// Access: Public
|
||||
// Description: Overrides the image size each output image specifies
|
||||
// with the indicated size.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageRasterizer::
|
||||
set_output_size(int xsize, int ysize) {
|
||||
_output_xsize = xsize;
|
||||
_output_ysize = ysize;
|
||||
_got_output_size = true;
|
||||
}
|
||||
|
||||
void StitchImageRasterizer::
|
||||
draw_points(StitchImage *output, StitchImage *input,
|
||||
const Colord &color, double radius) {
|
||||
StitchImage::Points::const_iterator pi;
|
||||
for (pi = input->_points.begin(); pi != input->_points.end(); ++pi) {
|
||||
LPoint2d to = output->project(input->extrude((*pi).second));
|
||||
draw_spot(output, to * output->_uv_to_pixels, color, radius);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchImageRasterizer::
|
||||
draw_points(StitchImage *output, Stitcher *input,
|
||||
const Colord &color, double radius) {
|
||||
Stitcher::LoosePoints::const_iterator pi;
|
||||
for (pi = input->_loose_points.begin();
|
||||
pi != input->_loose_points.end(); ++pi) {
|
||||
LPoint2d to = output->project((*pi)->_space);
|
||||
draw_spot(output, to * output->_uv_to_pixels, color, radius);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StitchImageRasterizer::
|
||||
draw_image(StitchImage *output, StitchImage *input) {
|
||||
nout << "Rasterizing " << input->get_name() << "\n";
|
||||
output->open_layer(input->get_name());
|
||||
|
||||
TriangleRasterizer rast;
|
||||
rast._output = output->_data;
|
||||
rast._input = input;
|
||||
rast._filter_output = false;
|
||||
rast._untextured_color = input->_untextured_color;
|
||||
|
||||
int x_verts = input->get_x_verts();
|
||||
int y_verts = input->get_y_verts();
|
||||
|
||||
// Build up the table of verts.
|
||||
typedef vector<RasterizerVertex> VRow;
|
||||
typedef vector<VRow> VTable;
|
||||
VTable table(x_verts, VRow());
|
||||
|
||||
int xi, yi;
|
||||
for (xi = 0; xi < x_verts; xi++) {
|
||||
table[xi] = VRow(y_verts, RasterizerVertex());
|
||||
|
||||
for (yi = 0; yi < y_verts; yi++) {
|
||||
LVector3d space = input->get_grid_vector(xi, yi);
|
||||
double alpha = input->get_grid_alpha(xi, yi);
|
||||
LPoint3d point;
|
||||
if (!_screen->intersect(point, input->get_pos(), space)) {
|
||||
// No intersection with the screen. What should we do now?
|
||||
LPoint2d from = input->get_grid_uv(xi, yi);
|
||||
|
||||
table[xi][yi]._p.set(0.0, 0.0);
|
||||
table[xi][yi]._uv = from;
|
||||
table[xi][yi]._space = point * output->_inv_transform;
|
||||
table[xi][yi]._alpha = alpha;
|
||||
|
||||
table[xi][yi]._space = normalize(table[xi][yi]._space);
|
||||
|
||||
// Tag any triangle including this vertex as totally invalid.
|
||||
table[xi][yi]._visibility = -1;
|
||||
|
||||
} else {
|
||||
LPoint2d to = output->project(point - output->get_pos());
|
||||
LPoint2d from = input->get_grid_uv(xi, yi);
|
||||
|
||||
table[xi][yi]._p = to * output->_uv_to_pixels;
|
||||
table[xi][yi]._uv = from;
|
||||
table[xi][yi]._space = point * output->_inv_transform;
|
||||
table[xi][yi]._alpha = alpha;
|
||||
|
||||
table[xi][yi]._space = normalize(table[xi][yi]._space);
|
||||
|
||||
// We assign one bit for each quadrant the vertex may be out of
|
||||
// bounds. If all three vertices of a triangle are out in the
|
||||
// same quadrant, then the entire triangle is out of bounds.
|
||||
table[xi][yi]._visibility =
|
||||
((to[0] < 0.0) |
|
||||
((to[0] > 1.0) << 1) |
|
||||
((to[1] < 0.0) << 2) |
|
||||
((to[1] > 1.0) << 3) |
|
||||
((from[0] < 0.0) << 4) |
|
||||
((from[0] > 1.0) << 5) |
|
||||
((from[1] < 0.0) << 6) |
|
||||
((from[1] > 1.0) << 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now draw all of the triangles, top-to-bottom.
|
||||
output->reset_singularity_detected();
|
||||
|
||||
for (yi = 0; yi < y_verts - 1; yi++) {
|
||||
for (xi = 0; xi < x_verts - 1; xi++) {
|
||||
output->draw_triangle(rast,
|
||||
&table[xi][yi],
|
||||
&table[xi][yi + 1],
|
||||
&table[xi + 1][yi + 1]);
|
||||
output->draw_triangle(rast,
|
||||
&table[xi][yi],
|
||||
&table[xi + 1][yi + 1],
|
||||
&table[xi + 1][yi]);
|
||||
}
|
||||
}
|
||||
output->pick_up_singularity(rast, input);
|
||||
output->close_layer(rast._read_input);
|
||||
|
||||
// We don't necessarily want to clear the input file now. Although
|
||||
// that would reduce memory consumption, maybe we've got plenty of
|
||||
// memory and we're more concerned with reducing load time.
|
||||
// input->clear_file();
|
||||
}
|
||||
|
||||
|
||||
void StitchImageRasterizer::
|
||||
draw_spot(StitchImage *output,
|
||||
const LPoint2d pixel_center, const Colord &color, double radius) {
|
||||
LPoint2d minp = pixel_center - LPoint2d(radius, radius);
|
||||
LPoint2d maxp = pixel_center + LPoint2d(radius, radius);
|
||||
|
||||
int min_x = (int)floor(minp[0]);
|
||||
int max_x = (int)ceil(maxp[0]);
|
||||
|
||||
int min_y = (int)floor(minp[1]);
|
||||
int max_y = (int)ceil(maxp[1]);
|
||||
|
||||
double r2 = radius * radius;
|
||||
|
||||
for (int yi = min_y; yi <= max_y; yi++) {
|
||||
if (yi >= 0 && yi < output->_data->get_y_size()) {
|
||||
for (int xi = min_x; xi <= max_x; xi++) {
|
||||
if (xi >= 0 && xi < output->_data->get_x_size()) {
|
||||
// Check the coverage of the four points around the pixel, and
|
||||
// the pixel center.
|
||||
LPoint2d ul = pixel_center - LPoint2d(xi - 0.5, yi - 0.5);
|
||||
LPoint2d ll = pixel_center - LPoint2d(xi - 0.5, yi + 0.5);
|
||||
LPoint2d ur = pixel_center - LPoint2d(xi + 0.5, yi - 0.5);
|
||||
LPoint2d lr = pixel_center - LPoint2d(xi + 0.5, yi + 0.5);
|
||||
LPoint2d pc = pixel_center - LPoint2d(xi, yi);
|
||||
|
||||
// Net coverage.
|
||||
int coverage =
|
||||
(dot(ul, ul) <= r2) +
|
||||
(dot(ll, ll) <= r2) +
|
||||
(dot(ur, ur) <= r2) +
|
||||
(dot(lr, lr) <= r2) +
|
||||
(dot(pc, pc) <= r2);
|
||||
|
||||
if (coverage != 0) {
|
||||
output->_data->blend(xi, yi, color[0], color[1], color[2],
|
||||
color[3] * (double)coverage / 5.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
// Filename: stitchImageRasterizer.h
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHIMAGERASTERIZER_H
|
||||
#define STITCHIMAGERASTERIZER_H
|
||||
|
||||
#include "stitchImageOutputter.h"
|
||||
|
||||
#include "pvector.h"
|
||||
#include "luse.h"
|
||||
#include "globPattern.h"
|
||||
|
||||
class Stitcher;
|
||||
class StitchImage;
|
||||
|
||||
class StitchImageRasterizer : public StitchImageOutputter {
|
||||
public:
|
||||
StitchImageRasterizer();
|
||||
|
||||
virtual void add_input_image(StitchImage *image);
|
||||
virtual void add_output_image(StitchImage *image);
|
||||
virtual void add_stitcher(Stitcher *stitcher);
|
||||
|
||||
virtual void execute();
|
||||
|
||||
void add_input_name(const string &name);
|
||||
bool has_input_name(const string &name) const;
|
||||
void add_output_name(const string &name);
|
||||
bool has_output_name(const string &name) const;
|
||||
|
||||
void set_filter_factor(double filter_factor);
|
||||
void set_output_size(int xsize, int ysize);
|
||||
|
||||
private:
|
||||
void draw_points(StitchImage *output, StitchImage *input,
|
||||
const Colord &color, double radius);
|
||||
void draw_points(StitchImage *output, Stitcher *input,
|
||||
const Colord &color, double radius);
|
||||
void draw_image(StitchImage *output, StitchImage *input);
|
||||
|
||||
void draw_spot(StitchImage *output,
|
||||
const LPoint2d pixel_center, const Colord &color,
|
||||
double radius);
|
||||
|
||||
typedef pvector<StitchImage *> Images;
|
||||
Images _input_images;
|
||||
Images _output_images;
|
||||
|
||||
typedef pvector<Stitcher *> Stitchers;
|
||||
Stitchers _stitchers;
|
||||
|
||||
typedef pvector<GlobPattern> Names;
|
||||
Names _input_names;
|
||||
Names _output_names;
|
||||
|
||||
double _filter_factor;
|
||||
|
||||
int _output_xsize;
|
||||
int _output_ysize;
|
||||
bool _got_output_size;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
// Filename: stitchLens.cxx
|
||||
// Created by: drose (04Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchLens.h"
|
||||
#include "triangleRasterizer.h"
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "deg_2_rad.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
StitchLens::
|
||||
StitchLens() {
|
||||
_flags = 0;
|
||||
_singularity_detected = 0;
|
||||
set_singularity_tolerance(5.0);
|
||||
}
|
||||
|
||||
StitchLens::
|
||||
~StitchLens() {
|
||||
}
|
||||
|
||||
void StitchLens::
|
||||
set_focal_length(double focal_length_mm) {
|
||||
_flags |= F_focal_length;
|
||||
_focal_length = focal_length_mm;
|
||||
}
|
||||
|
||||
void StitchLens::
|
||||
set_hfov(double fov_deg) {
|
||||
_flags |= F_fov;
|
||||
_fov = fov_deg;
|
||||
}
|
||||
|
||||
void StitchLens::
|
||||
set_singularity_tolerance(double tol) {
|
||||
_singularity_tolerance = tol;
|
||||
_singularity_radius = sin(deg_2_rad(tol));
|
||||
}
|
||||
|
||||
void StitchLens::
|
||||
reset_singularity_detected() {
|
||||
_singularity_detected = 0;
|
||||
}
|
||||
|
||||
bool StitchLens::
|
||||
is_defined() const {
|
||||
return (_flags != 0);
|
||||
}
|
||||
|
||||
double StitchLens::
|
||||
get_vfov(double height_mm) const {
|
||||
return get_hfov(height_mm);
|
||||
}
|
||||
|
||||
void StitchLens::
|
||||
draw_triangle(TriangleRasterizer &rast, const LMatrix3d &,
|
||||
double, const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1, const RasterizerVertex *v2) {
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
}
|
||||
|
||||
void StitchLens::
|
||||
pick_up_singularity(TriangleRasterizer &, const LMatrix3d &,
|
||||
const LMatrix3d &, const LMatrix3d &,
|
||||
double, StitchImage *) {
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
// Filename: stitchLens.h
|
||||
// Created by: drose (04Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHLENS_H
|
||||
#define STITCHLENS_H
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
class TriangleRasterizer;
|
||||
class RasterizerVertex;
|
||||
class StitchImage;
|
||||
class StitchCommand;
|
||||
|
||||
class StitchLens {
|
||||
public:
|
||||
StitchLens();
|
||||
virtual ~StitchLens();
|
||||
|
||||
virtual void set_focal_length(double focal_length_mm);
|
||||
virtual void set_hfov(double fov_deg);
|
||||
|
||||
void set_singularity_tolerance(double tol);
|
||||
void reset_singularity_detected();
|
||||
|
||||
bool is_defined() const;
|
||||
virtual double get_focal_length(double width_mm) const=0;
|
||||
virtual double get_hfov(double width_mm) const=0;
|
||||
virtual double get_vfov(double height_mm) const;
|
||||
|
||||
virtual LVector3d extrude(const LPoint2d &point_mm, double width_mm) const=0;
|
||||
virtual LPoint2d project(const LVector3d &vec, double width_mm) const=0;
|
||||
|
||||
// This function simply passes the indicated triangle on to the
|
||||
// rasterizer. It exists here in the lens so that the lens may do
|
||||
// something special if the triangle crosses a seam or singularity
|
||||
// in the lens' coordinate space.
|
||||
virtual void draw_triangle(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
double width_mm,
|
||||
const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1,
|
||||
const RasterizerVertex *v2);
|
||||
|
||||
// This function is to be called after all triangles have been
|
||||
// drawn; it will draw pixel-by-pixel all the points within
|
||||
// _singularity_radius of any singularity points the lens may have
|
||||
// (these points were not draw by draw_triangle(), above).
|
||||
virtual void pick_up_singularity(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
const LMatrix3d &pixels_to_mm,
|
||||
const LMatrix3d &rotate,
|
||||
double width_mm,
|
||||
StitchImage *input);
|
||||
|
||||
// This generates a StitchCommand that represents the given lens.
|
||||
virtual void make_lens_command(StitchCommand *parent)=0;
|
||||
|
||||
protected:
|
||||
enum Flags {
|
||||
F_focal_length = 0x01,
|
||||
F_fov = 0x02,
|
||||
};
|
||||
int _flags;
|
||||
int _singularity_detected;
|
||||
double _focal_length;
|
||||
double _fov;
|
||||
double _singularity_tolerance;
|
||||
double _singularity_radius;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,399 +0,0 @@
|
|||
/*
|
||||
// Filename: lexer.l
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
*/
|
||||
|
||||
%{
|
||||
#include "stitchLexerDefs.h"
|
||||
#include "stitchParserDefs.h"
|
||||
#include "stitchParser.h"
|
||||
|
||||
#include <indent.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
extern "C" int stitchyywrap(void); // declared below.
|
||||
|
||||
static int yyinput(void); // declared by flex.
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Static variables
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// We'll increment line_number and col_number as we parse the file, so
|
||||
// that we can report the position of an error.
|
||||
static int line_number = 0;
|
||||
static int col_number = 0;
|
||||
|
||||
// current_line holds as much of the current line as will fit. Its
|
||||
// only purpose is for printing it out to report an error to the user.
|
||||
static const int max_error_width = 1024;
|
||||
static char current_line[max_error_width + 1];
|
||||
|
||||
static int error_count = 0;
|
||||
static int warning_count = 0;
|
||||
|
||||
// This is the pointer to the current input stream.
|
||||
static istream *inp = NULL;
|
||||
|
||||
// This is the name of the stitch file we're parsing. We keep it so we
|
||||
// can print it out for error messages.
|
||||
static string stitch_filename;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Defining the interface to the lexer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
stitch_init_lexer(istream &in, const string &filename) {
|
||||
inp = ∈
|
||||
stitch_filename = filename;
|
||||
line_number = 0;
|
||||
col_number = 0;
|
||||
error_count = 0;
|
||||
warning_count = 0;
|
||||
}
|
||||
|
||||
int
|
||||
stitch_error_count() {
|
||||
return error_count;
|
||||
}
|
||||
|
||||
int
|
||||
stitch_warning_count() {
|
||||
return warning_count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Internal support functions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
int
|
||||
stitchyywrap(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
stitchyyerror(const string &msg) {
|
||||
nout << "\nError";
|
||||
if (!stitch_filename.empty()) {
|
||||
nout << " in " << stitch_filename;
|
||||
}
|
||||
nout
|
||||
<< " at line " << line_number << ", column " << col_number << ":\n"
|
||||
<< current_line << "\n";
|
||||
indent(nout, col_number-1)
|
||||
<< "^\n" << msg << "\n\n" << flush;
|
||||
error_count++;
|
||||
}
|
||||
|
||||
void
|
||||
stitchyyerror(ostringstream &strm) {
|
||||
stitchyyerror(strm.str());
|
||||
}
|
||||
|
||||
void
|
||||
stitchyywarning(const string &msg) {
|
||||
nout
|
||||
<< "\nWarning at line " << line_number << ", column " << col_number << ":\n"
|
||||
<< current_line << "\n";
|
||||
indent(nout, col_number-1)
|
||||
<< "^\n" << msg << "\n\n" << flush;
|
||||
warning_count++;
|
||||
}
|
||||
|
||||
void
|
||||
stitchyywarning(ostringstream &strm) {
|
||||
stitchyywarning(strm);
|
||||
}
|
||||
|
||||
// Now define a function to take input from an istream instead of a
|
||||
// stdio FILE pointer. This is flex-specific.
|
||||
static void
|
||||
input_chars(char *buffer, int &result, int max_size) {
|
||||
assert(inp != NULL);
|
||||
if (*inp) {
|
||||
inp->read(buffer, max_size);
|
||||
result = inp->gcount();
|
||||
|
||||
if (line_number == 0) {
|
||||
// This is a special case. If we are reading the very first bit
|
||||
// from the stream, copy it into the current_line array. This
|
||||
// is because the \n.* rule below, which fills current_line
|
||||
// normally, doesn't catch the first line.
|
||||
strncpy(current_line, yytext, max_error_width);
|
||||
current_line[max_error_width] = '\0';
|
||||
line_number++;
|
||||
col_number = 0;
|
||||
|
||||
// Truncate it at the newline.
|
||||
char *end = strchr(current_line, '\n');
|
||||
if (end != NULL) {
|
||||
*end = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// End of file or I/O error.
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buffer, result, max_size) input_chars(buffer, result, max_size)
|
||||
|
||||
// read_char reads and returns a single character, incrementing the
|
||||
// supplied line and column numbers as appropriate. A convenience
|
||||
// function for the scanning functions below.
|
||||
static int
|
||||
read_char(int &line, int &col) {
|
||||
int c = yyinput();
|
||||
if (c == '\n') {
|
||||
line++;
|
||||
col = 0;
|
||||
} else {
|
||||
col++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// scan_quoted_string reads a string delimited by quotation marks and
|
||||
// returns it.
|
||||
static string
|
||||
scan_quoted_string() {
|
||||
string result;
|
||||
|
||||
// We don't touch the current line number and column number during
|
||||
// scanning, so that if we detect an error while scanning the string
|
||||
// (e.g. an unterminated string), we'll report the error as
|
||||
// occurring at the start of the string, not at the end--somewhat
|
||||
// more convenient for the user.
|
||||
|
||||
// Instead of adjusting the global line_number and col_number
|
||||
// variables, we'll operate on our own local variables for the
|
||||
// interim.
|
||||
int line = line_number;
|
||||
int col = col_number;
|
||||
|
||||
int c;
|
||||
c = read_char(line, col);
|
||||
while (c != '"' && c != EOF) {
|
||||
result += c;
|
||||
c = read_char(line, col);
|
||||
}
|
||||
|
||||
if (c == EOF) {
|
||||
stitchyyerror("This quotation mark is unterminated.");
|
||||
}
|
||||
|
||||
line_number = line;
|
||||
col_number = col;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// eat_c_comment scans past all characters up until the first */
|
||||
// encountered.
|
||||
static void
|
||||
eat_c_comment() {
|
||||
// As above, we'll operate on our own local copies of line_number
|
||||
// and col_number within this function.
|
||||
|
||||
int line = line_number;
|
||||
int col = col_number;
|
||||
|
||||
int c, last_c;
|
||||
|
||||
last_c = '\0';
|
||||
c = read_char(line, col);
|
||||
while (c != EOF && !(last_c == '*' && c == '/')) {
|
||||
if (last_c == '/' && c == '*') {
|
||||
ostringstream errmsg;
|
||||
errmsg << "This comment contains a nested /* symbol at line "
|
||||
<< line << ", column " << col-1 << "--possibly unclosed?";
|
||||
stitchyywarning(errmsg);
|
||||
}
|
||||
last_c = c;
|
||||
c = read_char(line, col);
|
||||
}
|
||||
|
||||
if (c == EOF) {
|
||||
stitchyyerror("This comment marker is unclosed.");
|
||||
}
|
||||
|
||||
line_number = line;
|
||||
col_number = col;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// accept() is called below as each piece is pulled off and
|
||||
// accepted by the lexer; it increments the current column number.
|
||||
INLINE void accept() {
|
||||
col_number += yyleng;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
|
||||
|
||||
%%
|
||||
|
||||
\n.* {
|
||||
// New line. Save a copy of the line so we can print it out for the
|
||||
// benefit of the user in case we get an error.
|
||||
|
||||
strncpy(current_line, yytext+1, max_error_width);
|
||||
current_line[max_error_width] = '\0';
|
||||
line_number++;
|
||||
col_number=0;
|
||||
|
||||
// Return the whole line to the lexer, except the newline character,
|
||||
// which we eat.
|
||||
yyless(1);
|
||||
}
|
||||
|
||||
[ \t] {
|
||||
// Eat whitespace.
|
||||
accept();
|
||||
}
|
||||
|
||||
"//".* {
|
||||
// Eat C++-style comments.
|
||||
accept();
|
||||
}
|
||||
|
||||
"/*" {
|
||||
// Eat C-style comments.
|
||||
accept();
|
||||
eat_c_comment();
|
||||
}
|
||||
|
||||
|
||||
|
||||
{NUMERIC} {
|
||||
// An integer or floating-point number.
|
||||
accept();
|
||||
stitchyylval.number = atof(stitchyytext);
|
||||
stitchyylval.str = yytext;
|
||||
return NUMBER;
|
||||
}
|
||||
|
||||
{NUMERIC}['] {
|
||||
// An integer or floating-point number followed by feet symbol.
|
||||
accept();
|
||||
stitchyylval.number = atof(stitchyytext);
|
||||
stitchyylval.str = yytext;
|
||||
return NUMBER_FEET;
|
||||
}
|
||||
|
||||
{NUMERIC}["] {
|
||||
// An integer or floating-point number followed by inches symbol.
|
||||
accept();
|
||||
stitchyylval.number = atof(stitchyytext);
|
||||
stitchyylval.str = yytext;
|
||||
return NUMBER_INCHES;
|
||||
}
|
||||
|
||||
["] {
|
||||
// Quoted string.
|
||||
accept();
|
||||
stitchyylval.str = scan_quoted_string();
|
||||
return STRING;
|
||||
}
|
||||
|
||||
[a-zA-Z][a-zA-Z0-9_-]* {
|
||||
// Identifier or keyword.
|
||||
accept();
|
||||
string str = yytext;
|
||||
stitchyylval.str = str;
|
||||
|
||||
if (cmp_nocase_uh(str, "define") == 0) {
|
||||
return KW_DEFINE;
|
||||
} else if (cmp_nocase_uh(str, "lens") == 0) {
|
||||
return KW_LENS;
|
||||
} else if (cmp_nocase_uh(str, "input_image") == 0) {
|
||||
return KW_INPUT_IMAGE;
|
||||
} else if (cmp_nocase_uh(str, "output_image") == 0) {
|
||||
return KW_OUTPUT_IMAGE;
|
||||
} else if (cmp_nocase_uh(str, "eyepoint") == 0) {
|
||||
return KW_EYEPOINT;
|
||||
} else if (cmp_nocase_uh(str, "perspective") == 0) {
|
||||
return KW_PERSPECTIVE;
|
||||
} else if (cmp_nocase_uh(str, "fisheye") == 0) {
|
||||
return KW_FISHEYE;
|
||||
} else if (cmp_nocase_uh(str, "cylindrical") == 0) {
|
||||
return KW_CYLINDRICAL;
|
||||
} else if (cmp_nocase_uh(str, "psphere") == 0) {
|
||||
return KW_PSPHERE;
|
||||
} else if (cmp_nocase_uh(str, "focal_length") == 0) {
|
||||
return KW_FOCAL_LENGTH;
|
||||
} else if (cmp_nocase_uh(str, "fov") == 0) {
|
||||
return KW_FOV;
|
||||
} else if (cmp_nocase_uh(str, "singularity_tolerance") == 0) {
|
||||
return KW_SINGULARITY_TOLERANCE;
|
||||
} else if (cmp_nocase_uh(str, "resolution") == 0) {
|
||||
return KW_RESOLUTION;
|
||||
} else if (cmp_nocase_uh(str, "filename") == 0) {
|
||||
return KW_FILENAME;
|
||||
} else if (cmp_nocase_uh(str, "fade") == 0) {
|
||||
return KW_FADE;
|
||||
} else if (cmp_nocase_uh(str, "point") == 0) {
|
||||
return KW_POINT;
|
||||
} else if (cmp_nocase_uh(str, "show_points") == 0) {
|
||||
return KW_SHOW_POINTS;
|
||||
} else if (cmp_nocase_uh(str, "image_size") == 0) {
|
||||
return KW_IMAGE_SIZE;
|
||||
} else if (cmp_nocase_uh(str, "film_size") == 0) {
|
||||
return KW_FILM_SIZE;
|
||||
} else if (cmp_nocase_uh(str, "film_offset") == 0) {
|
||||
return KW_FILM_OFFSET;
|
||||
} else if (cmp_nocase_uh(str, "grid") == 0) {
|
||||
return KW_GRID;
|
||||
} else if (cmp_nocase_uh(str, "untextured_color") == 0) {
|
||||
return KW_UNTEXTURED_COLOR;
|
||||
} else if (cmp_nocase_uh(str, "hpr") == 0) {
|
||||
return KW_HPR;
|
||||
} else if (cmp_nocase_uh(str, "pos") == 0) {
|
||||
return KW_POS;
|
||||
} else if (cmp_nocase_uh(str, "radius") == 0) {
|
||||
return KW_RADIUS;
|
||||
} else if (cmp_nocase_uh(str, "angle") == 0) {
|
||||
return KW_ANGLE;
|
||||
} else if (cmp_nocase_uh(str, "height") == 0) {
|
||||
return KW_HEIGHT;
|
||||
} else if (cmp_nocase_uh(str, "layers") == 0) {
|
||||
return KW_LAYERS;
|
||||
} else if (cmp_nocase_uh(str, "stitch") == 0) {
|
||||
return KW_STITCH;
|
||||
} else if (cmp_nocase_uh(str, "screen") == 0) {
|
||||
return KW_SCREEN;
|
||||
} else if (cmp_nocase_uh(str, "points") == 0) {
|
||||
return KW_POINTS;
|
||||
} else if (cmp_nocase_uh(str, "using") == 0) {
|
||||
return KW_USING;
|
||||
} else if (cmp_nocase_uh(str, "in") == 0) {
|
||||
return KW_IN;
|
||||
} else if (cmp_nocase_uh(str, "mm") == 0) {
|
||||
return KW_MM;
|
||||
} else if (cmp_nocase_uh(str, "cm") == 0) {
|
||||
return KW_CM;
|
||||
} else if (cmp_nocase_uh(str, "ft") == 0) {
|
||||
return KW_FT;
|
||||
} else if (cmp_nocase_uh(str, "p") == 0) {
|
||||
return KW_P;
|
||||
}
|
||||
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
. {
|
||||
// Send any other character as itself.
|
||||
accept();
|
||||
return stitchyytext[0];
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// Filename: stitchLexerDefs.h
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHLEXERDEFS_H
|
||||
#define STITCHLEXERDEFS_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
void stitch_init_lexer(istream &in, const string &filename);
|
||||
int stitch_error_count();
|
||||
int stitch_warning_count();
|
||||
|
||||
void stitchyyerror(const string &msg);
|
||||
void stitchyyerror(ostringstream &strm);
|
||||
|
||||
void stitchyywarning(const string &msg);
|
||||
void stitchyywarning(ostringstream &strm);
|
||||
|
||||
int stitchyylex();
|
||||
|
||||
#endif
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
// Filename: stitchMultiScreen.cxx
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchMultiScreen.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchMultiScreen::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchMultiScreen::
|
||||
StitchMultiScreen() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchMultiScreen::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchMultiScreen::
|
||||
~StitchMultiScreen() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchMultiScreen::add_screen
|
||||
// Access: Public
|
||||
// Description: Adds a new screen to the set of screens in the set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchMultiScreen::
|
||||
add_screen(StitchScreen *screen) {
|
||||
_screens.insert(screen);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchMultiScreen::clear_screens
|
||||
// Access: Public
|
||||
// Description: Empties the set of screens from the set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchMultiScreen::
|
||||
clear_screens() {
|
||||
_screens.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchMultiScreen::is_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if there are no screens in the set, or
|
||||
// false if there is at least one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchMultiScreen::
|
||||
is_empty() const {
|
||||
return _screens.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchMultiScreen::intersect
|
||||
// Access: Public, Virtual
|
||||
// Description: Determines the intersection point of a ray starting
|
||||
// at the indicated origin, and continuing infinitely in
|
||||
// the indicated direction, with the screen.
|
||||
//
|
||||
// If there is no intersection, leaves result undefined
|
||||
// and returns false. If there is an intersection, sets
|
||||
// result to the intersection point and returns true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchMultiScreen::
|
||||
intersect(LPoint3d &result,
|
||||
const LPoint3d &origin,
|
||||
const LVector3d &direction) const {
|
||||
if (_screens.empty()) {
|
||||
// If we have no screens, the direction is the same as the result.
|
||||
// This acts as if we have an infinitely large screen at infinity.
|
||||
result = direction;
|
||||
return true;
|
||||
}
|
||||
|
||||
return StitchScreen::intersect(result, origin, direction);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchMultiScreen::compute_intersect
|
||||
// Access: Protected, Virtual
|
||||
// Description: Computes the intersection point for the ray beginning
|
||||
// at the indicated origin point and continuing in the
|
||||
// indicated direction, to infinity. The return value
|
||||
// is a number >= 0.0 that indicates the parametric
|
||||
// intersection point along the ray with the screen
|
||||
// geometry, or a number < 0.0 if there is no
|
||||
// intersection with the screen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double StitchMultiScreen::
|
||||
compute_intersect(const LPoint3d &origin, const LVector3d &direction) const {
|
||||
LPoint3d p = origin * _inv_transform;
|
||||
LVector3d d = direction * _inv_transform;
|
||||
double best = -1.0;
|
||||
|
||||
// Walk through all of our screens and find the closest valid
|
||||
// intersection point.
|
||||
Screens::const_iterator si;
|
||||
for (si = _screens.begin(); si != _screens.end(); ++si) {
|
||||
double t = (*si)->compute_intersect(p, d);
|
||||
if (t >= 0.0) {
|
||||
if (best >= 0.0) {
|
||||
best = min(best, t);
|
||||
} else {
|
||||
best = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
// Filename: stitchMultiScreen.h
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHMULTISCREEN_H
|
||||
#define STITCHMULTISCREEN_H
|
||||
|
||||
#include "stitchScreen.h"
|
||||
#include "pset.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchMultiScreen
|
||||
// Description : A composite of one or more simple screens.
|
||||
//
|
||||
// If there is at least one screen in the set, the
|
||||
// StitchMultiScreen behaves like the intersection of
|
||||
// all of the screens. If there are no screens, it
|
||||
// behaves like an infinitely large screen at infinity.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchMultiScreen : public StitchScreen {
|
||||
public:
|
||||
StitchMultiScreen();
|
||||
virtual ~StitchMultiScreen();
|
||||
|
||||
void add_screen(StitchScreen *screen);
|
||||
void clear_screens();
|
||||
bool is_empty() const;
|
||||
|
||||
virtual bool intersect(LPoint3d &result,
|
||||
const LPoint3d &origin,
|
||||
const LVector3d &direction) const;
|
||||
|
||||
protected:
|
||||
virtual double compute_intersect(const LPoint3d &origin,
|
||||
const LVector3d &direction) const;
|
||||
|
||||
private:
|
||||
typedef pset< PT(StitchScreen) > Screens;
|
||||
Screens _screens;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,313 +0,0 @@
|
|||
// Filename: stitchPSphereLens.cxx
|
||||
// Created by: drose (16Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchPSphereLens.h"
|
||||
#include "stitchImage.h"
|
||||
#include "stitchCommand.h"
|
||||
#include "triangleRasterizer.h"
|
||||
#include "triangle.h"
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "deg_2_rad.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// This is the focal-length constant for fisheye lenses. See
|
||||
// stitchFisheyeLens.h.
|
||||
static const double psphere_k = 60.0;
|
||||
|
||||
StitchPSphereLens::
|
||||
StitchPSphereLens() {
|
||||
}
|
||||
|
||||
double StitchPSphereLens::
|
||||
get_focal_length(double width_mm) const {
|
||||
if (_flags & F_focal_length) {
|
||||
return _focal_length;
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
return width_mm * psphere_k / _fov;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double StitchPSphereLens::
|
||||
get_hfov(double width_mm) const {
|
||||
if (_flags & F_fov) {
|
||||
return _fov;
|
||||
}
|
||||
if (_flags & F_focal_length) {
|
||||
return width_mm * psphere_k / _focal_length;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
LVector3d StitchPSphereLens::
|
||||
extrude(const LPoint2d &point_mm, double width_mm) const {
|
||||
LVector2d v2 = point_mm;
|
||||
|
||||
double fl = get_focal_length(width_mm);
|
||||
return LVector3d::forward() *
|
||||
LMatrix3d::rotate_mat(v2[1] * psphere_k / fl, LVector3d::right()) *
|
||||
LMatrix3d::rotate_mat(-v2[0] * psphere_k / fl, LVector3d::up());
|
||||
}
|
||||
|
||||
|
||||
LPoint2d StitchPSphereLens::
|
||||
project(const LVector3d &vec, double width_mm) const {
|
||||
// A PSphere lens is a toroidal lens. It is independently curved in
|
||||
// the horizontal and vertical directions.
|
||||
|
||||
LVector3d v3 = vec * LMatrix4d::convert_mat(CS_default, CS_zup_right);
|
||||
|
||||
// To compute the x position on the frame, we only need to consider
|
||||
// the angle of the vector about the Z axis. Project the vector
|
||||
// into the XY plane to do this.
|
||||
|
||||
LVector2d xy(v3[0], v3[1]);
|
||||
|
||||
// The x position is the angle about the Z axis.
|
||||
double x =
|
||||
rad_2_deg(atan2(xy[0], xy[1])) * get_focal_length(width_mm) / psphere_k;
|
||||
|
||||
// Unroll the Z angle, and the y position is the angle about the X
|
||||
// axis.
|
||||
xy = normalize(xy);
|
||||
LVector2d yz(v3[0]*xy[0] + v3[1]*xy[1], v3[2]);
|
||||
double y =
|
||||
rad_2_deg(atan2(yz[1], yz[0])) * get_focal_length(width_mm) / psphere_k;
|
||||
|
||||
return LPoint2d(x, y);
|
||||
}
|
||||
|
||||
LPoint2d StitchPSphereLens::
|
||||
project_left(const LVector3d &vec, double width_mm) const {
|
||||
// This is just like project(), except that if the vertex extends
|
||||
// below -180 degrees, it remains on the left side of the film
|
||||
// (instead of wrapping around to the right side).
|
||||
|
||||
LVector3d v3 = vec * LMatrix4d::convert_mat(CS_default, CS_zup_right);
|
||||
LVector2d xy(v3[0], v3[1]);
|
||||
double x =
|
||||
(rad_2_deg(atan2(-xy[0], -xy[1])) - 180.0) *
|
||||
get_focal_length(width_mm) / psphere_k;
|
||||
|
||||
xy = normalize(xy);
|
||||
LVector2d yz(v3[0]*xy[0] + v3[1]*xy[1], v3[2]);
|
||||
double y =
|
||||
rad_2_deg(atan2(yz[1], yz[0])) * get_focal_length(width_mm) / psphere_k;
|
||||
|
||||
return LPoint2d(x, y);
|
||||
}
|
||||
|
||||
LPoint2d StitchPSphereLens::
|
||||
project_right(const LVector3d &vec, double width_mm) const {
|
||||
// This is just like project(), except that if the vertex extends
|
||||
// above 180 degrees, it remains on the right side of the film
|
||||
// (instead of wrapping around to the left side).
|
||||
|
||||
LVector3d v3 = vec * LMatrix4d::convert_mat(CS_default, CS_zup_right);
|
||||
LVector2d xy(v3[0], v3[1]);
|
||||
double x =
|
||||
(rad_2_deg(atan2(-xy[0], -xy[1])) + 180.0) *
|
||||
get_focal_length(width_mm) / psphere_k;
|
||||
|
||||
xy = normalize(xy);
|
||||
LVector2d yz(v3[0]*xy[0] + v3[1]*xy[1], v3[2]);
|
||||
double y =
|
||||
rad_2_deg(atan2(yz[1], yz[0])) * get_focal_length(width_mm) / psphere_k;
|
||||
|
||||
return LPoint2d(x, y);
|
||||
}
|
||||
|
||||
void StitchPSphereLens::
|
||||
draw_triangle(TriangleRasterizer &rast, const LMatrix3d &mm_to_pixels,
|
||||
double width_mm, const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1, const RasterizerVertex *v2) {
|
||||
// A PSphere lens has two singularities, at the north and south
|
||||
// poles, as well as a seam at 180 and -180 degrees.
|
||||
|
||||
// First, we reject any triangles within _singularity_tolerance of
|
||||
// either pole, similar to the fisheye lens.
|
||||
|
||||
LVector2d xy0(dot(v0->_space, LVector3d::right()),
|
||||
dot(v0->_space, LVector3d::forward()));
|
||||
LVector2d xy1(dot(v1->_space, LVector3d::right()),
|
||||
dot(v1->_space, LVector3d::forward()));
|
||||
LVector2d xy2(dot(v2->_space, LVector3d::right()),
|
||||
dot(v2->_space, LVector3d::forward()));
|
||||
|
||||
double z0 = dot(v0->_space, LVector3d::up());
|
||||
double z1 = dot(v0->_space, LVector3d::up());
|
||||
double z2 = dot(v0->_space, LVector3d::up());
|
||||
|
||||
if (z0 < 0.0 && z1 < 0.0 && z2 < 0.0) {
|
||||
// A triangle on the southern hemisphere. This projection will
|
||||
// reverse the vertex order.
|
||||
if (triangle_contains_circle(LPoint2d(0.0, 0.0),
|
||||
_singularity_radius,
|
||||
xy0, xy2, xy1)) {
|
||||
// The triangle does cross the singularity! Reject it.
|
||||
_singularity_detected |= 1;
|
||||
return;
|
||||
}
|
||||
} else if (z0 > 0.0 && z1 > 0.0 && z2 > 0.0) {
|
||||
// A triangle on the northern hemisphere. This projection will
|
||||
// preserve the vertex order.
|
||||
if (triangle_contains_circle(LPoint2d(0.0, 0.0),
|
||||
_singularity_radius,
|
||||
xy0, xy1, xy2)) {
|
||||
// The triangle does cross the singularity! Reject it.
|
||||
_singularity_detected |= 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// So the triangle is not at the north or south poles. But it might
|
||||
// cross the seam at the back. If it does, we'll simply draw it
|
||||
// twice: once at each side.
|
||||
|
||||
// Determine which quadrant each of the vertices is in. The
|
||||
// triangle crosses the seam if no vertices are in quadrants I and
|
||||
// II, and some vertices are in quadrant III and others are in
|
||||
// quadrant IV.
|
||||
|
||||
if (xy0[1] >= 0.0 || xy1[1] >= 0.0 || xy2[1] >= 0.0) {
|
||||
// Some vertices are in quadrants I or II.
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
|
||||
} else if (xy0[0] > 0.0 && xy1[0] > 0.0 && xy2[0] > 0.0) {
|
||||
// All vertices are in quadrant IV.
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
|
||||
} else if (xy0[0] < 0.0 && xy1[0] < 0.0 && xy2[0] < 0.0) {
|
||||
// All vertices are in quadrant III.
|
||||
rast.draw_triangle(v0, v1, v2);
|
||||
|
||||
} else {
|
||||
// The triangle crosses the seam. Draw it twice.
|
||||
RasterizerVertex v0a = *v0;
|
||||
RasterizerVertex v1a = *v1;
|
||||
RasterizerVertex v2a = *v2;
|
||||
|
||||
v0a._p = project_left(v0a._space, width_mm) * mm_to_pixels;
|
||||
v1a._p = project_left(v1a._space, width_mm) * mm_to_pixels;
|
||||
v2a._p = project_left(v2a._space, width_mm) * mm_to_pixels;
|
||||
rast.draw_triangle(&v0a, &v1a, &v2a);
|
||||
|
||||
v0a._p = project_right(v0a._space, width_mm) * mm_to_pixels;
|
||||
v1a._p = project_right(v1a._space, width_mm) * mm_to_pixels;
|
||||
v2a._p = project_right(v2a._space, width_mm) * mm_to_pixels;
|
||||
rast.draw_triangle(&v0a, &v1a, &v2a);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchPSphereLens::
|
||||
pick_up_singularity(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
const LMatrix3d &pixels_to_mm,
|
||||
const LMatrix3d &rotate,
|
||||
double width_mm, StitchImage *input) {
|
||||
if (_singularity_detected & 2) {
|
||||
nout << "Picking up north pole singularity\n";
|
||||
// Determine what the bottom y pixel is of the circle around the
|
||||
// north pole.
|
||||
double d = deg_2_rad(_singularity_tolerance * 2.0);
|
||||
LPoint2d pmm = project(LVector3d(0.0, sin(d), cos(d)), width_mm);
|
||||
LPoint2d p = pmm * mm_to_pixels;
|
||||
|
||||
int xsize = rast._output->get_x_size();
|
||||
int ysize = rast._output->get_y_size();
|
||||
|
||||
int bot_y = min((int)ceil(p[1]), ysize - 1);
|
||||
RasterizerVertex v0;
|
||||
v0._p.set(0.0, 0.0);
|
||||
v0._uv.set(0.0, 0.0);
|
||||
v0._space.set(0.0, 0.0, 0.0);
|
||||
v0._alpha = 1.0;
|
||||
v0._visibility = 0;
|
||||
|
||||
int xi, yi;
|
||||
for (yi = 0; yi <= bot_y; yi++) {
|
||||
// Project xi point 1 to determine the radius.
|
||||
v0._p.set(0, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
|
||||
for (xi = 0; xi < xsize; xi++) {
|
||||
double last_u = v0._uv[0];
|
||||
|
||||
v0._p.set(xi, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
rast.draw_pixel(&v0, fabs(v0._uv[0] - last_u));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_singularity_detected & 1) {
|
||||
nout << "Picking up south pole singularity\n";
|
||||
// Determine what the top y pixel is of the circle around the
|
||||
// south pole.
|
||||
double d = deg_2_rad(_singularity_tolerance * 2.0);
|
||||
LPoint2d pmm = project(LVector3d(0.0, sin(d), -cos(d)), width_mm);
|
||||
LPoint2d p = pmm * mm_to_pixels;
|
||||
|
||||
int xsize = rast._output->get_x_size();
|
||||
int ysize = rast._output->get_y_size();
|
||||
|
||||
int top_y = max((int)floor(p[1]), 0);
|
||||
RasterizerVertex v0;
|
||||
v0._p.set(0.0, 0.0);
|
||||
v0._uv.set(0.0, 0.0);
|
||||
v0._space.set(0.0, 0.0, 0.0);
|
||||
v0._alpha = 1.0;
|
||||
v0._visibility = 0;
|
||||
|
||||
int xi, yi;
|
||||
for (yi = top_y; yi < ysize; yi++) {
|
||||
// Project xi point 1 to determine the radius.
|
||||
v0._p.set(0, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
|
||||
for (xi = 0; xi < xsize; xi++) {
|
||||
double last_u = v0._uv[0];
|
||||
|
||||
v0._p.set(xi, yi);
|
||||
v0._space = extrude(v0._p * pixels_to_mm, width_mm) * rotate;
|
||||
v0._uv = input->project(v0._space);
|
||||
rast.draw_pixel(&v0, fabs(v0._uv[0] - last_u));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StitchPSphereLens::
|
||||
make_lens_command(StitchCommand *parent) {
|
||||
StitchCommand *lens_cmd = new StitchCommand(parent, StitchCommand::C_lens);
|
||||
StitchCommand *cmd;
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_psphere);
|
||||
if (_flags & F_focal_length) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_focal_length);
|
||||
cmd->set_length(_focal_length);
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_fov);
|
||||
cmd->set_number(_fov);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
// Filename: stitchPSphereLens.h
|
||||
// Created by: drose (16Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHPSPHERELENS_H
|
||||
#define STITCHPSPHERELENS_H
|
||||
|
||||
#include "stitchLens.h"
|
||||
|
||||
class StitchPSphereLens : public StitchLens {
|
||||
public:
|
||||
StitchPSphereLens();
|
||||
|
||||
virtual double get_focal_length(double width_mm) const;
|
||||
virtual double get_hfov(double width_mm) const;
|
||||
|
||||
virtual LVector3d extrude(const LPoint2d &point_mm, double width_mm) const;
|
||||
virtual LPoint2d project(const LVector3d &vec, double width_mm) const;
|
||||
|
||||
LPoint2d project_left(const LVector3d &vec, double width_mm) const;
|
||||
LPoint2d project_right(const LVector3d &vec, double width_mm) const;
|
||||
|
||||
virtual void draw_triangle(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
double width_mm,
|
||||
const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1,
|
||||
const RasterizerVertex *v2);
|
||||
|
||||
virtual void pick_up_singularity(TriangleRasterizer &rast,
|
||||
const LMatrix3d &mm_to_pixels,
|
||||
const LMatrix3d &pixels_to_mm,
|
||||
const LMatrix3d &rotate,
|
||||
double width_mm,
|
||||
StitchImage *input);
|
||||
|
||||
virtual void make_lens_command(StitchCommand *parent);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,50 +0,0 @@
|
|||
#ifndef BISON_Y_TAB_H
|
||||
# define BISON_Y_TAB_H
|
||||
|
||||
# define NUMBER 257
|
||||
# define NUMBER_FEET 258
|
||||
# define NUMBER_INCHES 259
|
||||
# define IDENTIFIER 260
|
||||
# define STRING 261
|
||||
# define KW_DEFINE 262
|
||||
# define KW_LENS 263
|
||||
# define KW_INPUT_IMAGE 264
|
||||
# define KW_OUTPUT_IMAGE 265
|
||||
# define KW_EYEPOINT 266
|
||||
# define KW_PERSPECTIVE 267
|
||||
# define KW_FISHEYE 268
|
||||
# define KW_CYLINDRICAL 269
|
||||
# define KW_PSPHERE 270
|
||||
# define KW_FOCAL_LENGTH 271
|
||||
# define KW_FOV 272
|
||||
# define KW_SINGULARITY_TOLERANCE 273
|
||||
# define KW_RESOLUTION 274
|
||||
# define KW_FILENAME 275
|
||||
# define KW_FADE 276
|
||||
# define KW_POINT 277
|
||||
# define KW_SHOW_POINTS 278
|
||||
# define KW_IMAGE_SIZE 279
|
||||
# define KW_FILM_SIZE 280
|
||||
# define KW_FILM_OFFSET 281
|
||||
# define KW_GRID 282
|
||||
# define KW_UNTEXTURED_COLOR 283
|
||||
# define KW_HPR 284
|
||||
# define KW_POS 285
|
||||
# define KW_RADIUS 286
|
||||
# define KW_ANGLE 287
|
||||
# define KW_HEIGHT 288
|
||||
# define KW_LAYERS 289
|
||||
# define KW_STITCH 290
|
||||
# define KW_SCREEN 291
|
||||
# define KW_POINTS 292
|
||||
# define KW_USING 293
|
||||
# define KW_IN 294
|
||||
# define KW_MM 295
|
||||
# define KW_FT 296
|
||||
# define KW_CM 297
|
||||
# define KW_P 298
|
||||
|
||||
|
||||
extern YYSTYPE stitchyylval;
|
||||
|
||||
#endif /* not BISON_Y_TAB_H */
|
||||
|
|
@ -1,496 +0,0 @@
|
|||
// Filename: stitchParser.y
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
%{
|
||||
|
||||
#include "stitchParserDefs.h"
|
||||
#include "stitchLexerDefs.h"
|
||||
#include "stitchCommand.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Defining the interface to the parser.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define YYERROR_VERBOSE
|
||||
|
||||
typedef vector<StitchCommand *> CommandStack;
|
||||
static CommandStack cstack;
|
||||
static StitchCommand *parent;
|
||||
|
||||
void
|
||||
stitch_init_parser(istream &in, const string &filename,
|
||||
StitchCommand *tos) {
|
||||
stitch_init_lexer(in, filename);
|
||||
parent = tos;
|
||||
cstack.push_back(parent);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%token <number> NUMBER NUMBER_FEET NUMBER_INCHES
|
||||
%token <str> IDENTIFIER
|
||||
%token <str> STRING
|
||||
|
||||
%token KW_DEFINE
|
||||
%token KW_LENS
|
||||
%token KW_INPUT_IMAGE
|
||||
%token KW_OUTPUT_IMAGE
|
||||
%token KW_EYEPOINT
|
||||
%token KW_PERSPECTIVE
|
||||
%token KW_FISHEYE
|
||||
%token KW_CYLINDRICAL
|
||||
%token KW_PSPHERE
|
||||
%token KW_FOCAL_LENGTH
|
||||
%token KW_FOV
|
||||
%token KW_SINGULARITY_TOLERANCE
|
||||
%token KW_RESOLUTION
|
||||
%token KW_FILENAME
|
||||
%token KW_FADE
|
||||
%token KW_POINT
|
||||
%token KW_SHOW_POINTS
|
||||
%token KW_IMAGE_SIZE
|
||||
%token KW_FILM_SIZE
|
||||
%token KW_FILM_OFFSET
|
||||
%token KW_GRID
|
||||
%token KW_UNTEXTURED_COLOR
|
||||
%token KW_HPR
|
||||
%token KW_POS
|
||||
%token KW_RADIUS
|
||||
%token KW_ANGLE
|
||||
%token KW_HEIGHT
|
||||
%token KW_LAYERS
|
||||
%token KW_STITCH
|
||||
%token KW_SCREEN
|
||||
%token KW_POINTS
|
||||
%token KW_USING
|
||||
%token KW_IN
|
||||
%token KW_MM
|
||||
%token KW_FT
|
||||
%token KW_CM
|
||||
%token KW_P
|
||||
|
||||
%type <command> command
|
||||
%type <command> group_command
|
||||
%type <command> simple_command
|
||||
%type <number> length
|
||||
%type <number> length_units
|
||||
%type <number> resolution
|
||||
%type <number> resolution_units
|
||||
%type <vec> point
|
||||
%type <vec> vec2
|
||||
%type <vec> vec3
|
||||
%type <vec> length_pair
|
||||
%type <vec> length_triple
|
||||
%type <vec> color
|
||||
%type <str> name
|
||||
%type <str> optional_name
|
||||
|
||||
%%
|
||||
|
||||
stitch_file:
|
||||
commands
|
||||
;
|
||||
|
||||
commands:
|
||||
empty
|
||||
| commands command
|
||||
{
|
||||
// parent->add_nested($2);
|
||||
}
|
||||
| commands KW_POINTS '{' points_list '}'
|
||||
;
|
||||
|
||||
command:
|
||||
group_command
|
||||
{
|
||||
parent = $1;
|
||||
cstack.push_back(parent);
|
||||
}
|
||||
nested_commands
|
||||
{
|
||||
cstack.pop_back();
|
||||
parent = cstack.back();
|
||||
}
|
||||
| simple_command ';'
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
nested_commands:
|
||||
'{' commands '}'
|
||||
| ';'
|
||||
;
|
||||
|
||||
group_command:
|
||||
KW_DEFINE name
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_define);
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_LENS optional_name
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_lens);
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_INPUT_IMAGE optional_name
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_input_image);
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_OUTPUT_IMAGE optional_name
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_output_image);
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_EYEPOINT optional_name
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_eyepoint);
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_STITCH optional_name
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_stitch);
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_SCREEN optional_name
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_screen);
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_USING
|
||||
{
|
||||
cstack.push_back(new StitchCommand(parent, StitchCommand::C_using));
|
||||
}
|
||||
using_list
|
||||
{
|
||||
$$ = cstack.back();
|
||||
cstack.pop_back();
|
||||
}
|
||||
;
|
||||
|
||||
simple_command:
|
||||
KW_PERSPECTIVE
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_perspective);
|
||||
}
|
||||
| KW_FISHEYE
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_fisheye);
|
||||
}
|
||||
| KW_CYLINDRICAL
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_cylindrical);
|
||||
}
|
||||
| KW_PSPHERE
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_psphere);
|
||||
}
|
||||
| KW_FOCAL_LENGTH length
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_focal_length);
|
||||
$$->set_length($2);
|
||||
}
|
||||
| KW_FOV NUMBER
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_fov);
|
||||
$$->set_number($2);
|
||||
}
|
||||
| KW_SINGULARITY_TOLERANCE NUMBER
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_singularity_tolerance);
|
||||
$$->set_number($2);
|
||||
}
|
||||
| KW_RESOLUTION resolution
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_resolution);
|
||||
$$->set_resolution($2);
|
||||
}
|
||||
| KW_FILENAME STRING
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_filename);
|
||||
$$->set_str($2);
|
||||
}
|
||||
| KW_FADE STRING
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_fade);
|
||||
$$->set_str($2);
|
||||
}
|
||||
| KW_POINT name point
|
||||
{
|
||||
if ($<num_components>3 == 2) {
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_point2d);
|
||||
$$->set_point2d((const LPoint2d &)$3);
|
||||
} else {
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_point3d);
|
||||
$$->set_point3d((const LPoint3d &)$3);
|
||||
}
|
||||
$$->set_name($2);
|
||||
}
|
||||
| KW_SHOW_POINTS NUMBER color
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_show_points);
|
||||
$$->set_number($2);
|
||||
$$->set_color($3);
|
||||
}
|
||||
| KW_IMAGE_SIZE vec2
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_image_size);
|
||||
$$->set_point2d((const LPoint2d &)$2);
|
||||
}
|
||||
| KW_FILM_SIZE length_pair
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_film_size);
|
||||
$$->set_length_pair((const LPoint2d &)$2);
|
||||
}
|
||||
| KW_FILM_OFFSET length_pair
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_film_offset);
|
||||
$$->set_length_pair((const LPoint2d &)$2);
|
||||
}
|
||||
| KW_GRID vec2
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_grid);
|
||||
$$->set_point2d((const LPoint2d &)$2);
|
||||
}
|
||||
| KW_UNTEXTURED_COLOR color
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_untextured_color);
|
||||
$$->set_color((const Colord &)$2);
|
||||
}
|
||||
| KW_HPR vec3
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_hpr);
|
||||
$$->set_point3d((const LPoint3d &)$2);
|
||||
}
|
||||
| KW_POS length_triple
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_pos);
|
||||
$$->set_point3d((const LPoint3d &)$2);
|
||||
}
|
||||
| KW_RADIUS length
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_radius);
|
||||
$$->set_number($2);
|
||||
}
|
||||
| KW_ANGLE vec2
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_angle);
|
||||
$$->set_point2d((const LPoint2d &)$2);
|
||||
}
|
||||
| KW_HEIGHT length_pair
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_height);
|
||||
$$->set_point2d((const LPoint2d &)$2);
|
||||
}
|
||||
| KW_LAYERS
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_layers);
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new StitchCommand(parent, StitchCommand::C_user_command);
|
||||
if (!$$->add_using($1)) {
|
||||
yyerror("Undefined identifier " + $1);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
using_list:
|
||||
IDENTIFIER
|
||||
{
|
||||
if (!cstack.back()->add_using($1)) {
|
||||
yyerror("Undefined identifier " + $1);
|
||||
}
|
||||
}
|
||||
| using_list ',' IDENTIFIER
|
||||
{
|
||||
if (!cstack.back()->add_using($3)) {
|
||||
yyerror("Undefined identifier " + $3);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
points_list:
|
||||
empty
|
||||
| points_list name point ';'
|
||||
{
|
||||
StitchCommand *cmd;
|
||||
if ($<num_components>3 == 2) {
|
||||
cmd = new StitchCommand(parent, StitchCommand::C_point2d);
|
||||
cmd->set_point2d((const LPoint2d &)$3);
|
||||
} else {
|
||||
cmd = new StitchCommand(parent, StitchCommand::C_point3d);
|
||||
cmd->set_point3d((const LPoint3d &)$3);
|
||||
}
|
||||
cmd->set_name($2);
|
||||
// parent->add_nested(cmd);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
length:
|
||||
NUMBER length_units
|
||||
{
|
||||
$$ = $1 * $2;
|
||||
}
|
||||
| NUMBER_FEET
|
||||
{
|
||||
$$ = $1 * 304.8; // ft to mm
|
||||
}
|
||||
| NUMBER_INCHES
|
||||
{
|
||||
$$ = $1 * 25.4; // in to mm
|
||||
}
|
||||
| NUMBER_FEET NUMBER_INCHES
|
||||
{
|
||||
if ($1 < 0.0) {
|
||||
$$ = $1 * 304.8 - $2 * 25.4;
|
||||
} else {
|
||||
$$ = $1 * 304.8 + $2 * 25.4;
|
||||
}
|
||||
}
|
||||
| NUMBER
|
||||
{
|
||||
$$ = $1; // implicitly mm
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
length_units:
|
||||
KW_IN
|
||||
{
|
||||
$$ = 25.4; // in to mm
|
||||
}
|
||||
| KW_CM
|
||||
{
|
||||
$$ = 10.0; // cm to mm
|
||||
}
|
||||
| KW_MM
|
||||
{
|
||||
$$ = 1.0;
|
||||
}
|
||||
| KW_FT
|
||||
{
|
||||
$$ = 304.8; // ft to mm
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
resolution:
|
||||
NUMBER resolution_units
|
||||
{
|
||||
$$ = $1 * $2; // convert to pixels per mm
|
||||
}
|
||||
;
|
||||
|
||||
resolution_units:
|
||||
KW_P '/' length_units
|
||||
{
|
||||
$$ = 1.0 / $3;
|
||||
}
|
||||
;
|
||||
|
||||
point:
|
||||
'(' NUMBER NUMBER ')'
|
||||
{
|
||||
$$.set($2, $3, 0.0, 0.0);
|
||||
$<num_components>$ = 2;
|
||||
}
|
||||
| '(' NUMBER ',' NUMBER ')'
|
||||
{
|
||||
$$.set($2, $4, 0.0, 0.0);
|
||||
$<num_components>$ = 2;
|
||||
}
|
||||
| '(' NUMBER NUMBER NUMBER ')'
|
||||
{
|
||||
$$.set($2, $3, $4, 0.0);
|
||||
$<num_components>$ = 3;
|
||||
}
|
||||
| '(' NUMBER ',' NUMBER ',' NUMBER ')'
|
||||
{
|
||||
$$.set($2, $4, $6, 0.0);
|
||||
$<num_components>$ = 3;
|
||||
}
|
||||
;
|
||||
|
||||
vec2:
|
||||
'(' NUMBER NUMBER ')'
|
||||
{
|
||||
$$.set($2, $3, 0.0, 0.0);
|
||||
$<num_components>$ = 2;
|
||||
}
|
||||
| '(' NUMBER ',' NUMBER ')'
|
||||
{
|
||||
$$.set($2, $4, 0.0, 0.0);
|
||||
$<num_components>$ = 2;
|
||||
}
|
||||
;
|
||||
|
||||
vec3: '(' NUMBER NUMBER NUMBER ')'
|
||||
{
|
||||
$$.set($2, $3, $4, 0.0);
|
||||
$<num_components>$ = 3;
|
||||
}
|
||||
| '(' NUMBER ',' NUMBER ',' NUMBER ')'
|
||||
{
|
||||
$$.set($2, $4, $6, 0.0);
|
||||
$<num_components>$ = 3;
|
||||
}
|
||||
;
|
||||
|
||||
length_pair:
|
||||
'(' length ',' length ')'
|
||||
{
|
||||
$$.set($2, $4, 0.0, 0.0);
|
||||
$<num_components>$ = 2;
|
||||
}
|
||||
;
|
||||
|
||||
length_triple:
|
||||
'(' length ',' length ',' length ')'
|
||||
{
|
||||
$$.set($2, $4, $6, 0.0);
|
||||
$<num_components>$ = 3;
|
||||
}
|
||||
;
|
||||
|
||||
color:
|
||||
'(' NUMBER NUMBER NUMBER ')'
|
||||
{
|
||||
$$.set($2, $3, $4, 1.0);
|
||||
$<num_components>$ = 3;
|
||||
}
|
||||
| '(' NUMBER ',' NUMBER ',' NUMBER ')'
|
||||
{
|
||||
$$.set($2, $4, $6, 1.0);
|
||||
$<num_components>$ = 3;
|
||||
}
|
||||
| '(' NUMBER NUMBER NUMBER NUMBER ')'
|
||||
{
|
||||
$$.set($2, $3, $4, $5);
|
||||
$<num_components>$ = 4;
|
||||
}
|
||||
| '(' NUMBER ',' NUMBER ',' NUMBER ',' NUMBER ')'
|
||||
{
|
||||
$$.set($2, $4, $6, $8);
|
||||
$<num_components>$ = 4;
|
||||
}
|
||||
;
|
||||
|
||||
name:
|
||||
IDENTIFIER
|
||||
;
|
||||
|
||||
optional_name:
|
||||
IDENTIFIER
|
||||
| empty
|
||||
{
|
||||
$$ = "";
|
||||
}
|
||||
;
|
||||
|
||||
empty:
|
||||
;
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
// Filename: stitchParserDefs.h
|
||||
// Created by: drose (08Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHPARSERDEFS_H
|
||||
#define STITCHPARSERDEFS_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
class StitchCommand;
|
||||
|
||||
int stitchyyparse();
|
||||
|
||||
void stitch_init_parser(istream &in, const string &filename,
|
||||
StitchCommand *tos);
|
||||
|
||||
// This structure holds the return value for each token.
|
||||
// Traditionally, this is a union, and is declared with the %union
|
||||
// declaration in the parser.y file, but unions are pretty worthless
|
||||
// in C++ (you can't include an object that has member functions in a
|
||||
// union), so we'll use a class instead. That means we need to
|
||||
// declare it externally, here.
|
||||
|
||||
class yystype {
|
||||
public:
|
||||
double number;
|
||||
string str;
|
||||
StitchCommand *command;
|
||||
LVecBase4d vec;
|
||||
int num_components;
|
||||
};
|
||||
#define YYSTYPE yystype
|
||||
|
||||
#endif
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
// Filename: stitchPerspectiveLens.cxx
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchPerspectiveLens.h"
|
||||
#include "stitchCommand.h"
|
||||
|
||||
#include "pandatoolbase.h"
|
||||
#include "deg_2_rad.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
StitchPerspectiveLens::
|
||||
StitchPerspectiveLens() {
|
||||
}
|
||||
|
||||
void StitchPerspectiveLens::
|
||||
set_hfov(double fov_deg) {
|
||||
StitchLens::set_hfov(fov_deg);
|
||||
_tan_fov = tan(deg_2_rad(_fov / 2.0)) * 2.0;
|
||||
}
|
||||
|
||||
double StitchPerspectiveLens::
|
||||
get_focal_length(double width_mm) const {
|
||||
if (_flags & F_focal_length) {
|
||||
return _focal_length;
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
return width_mm / _tan_fov;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double StitchPerspectiveLens::
|
||||
get_hfov(double width_mm) const {
|
||||
if (_flags & F_fov) {
|
||||
return _fov;
|
||||
}
|
||||
if (_flags & F_focal_length) {
|
||||
return 2.0 * rad_2_deg(atan(width_mm / (2.0 * _focal_length)));
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
LVector3d StitchPerspectiveLens::
|
||||
extrude(const LPoint2d &point_mm, double width_mm) const {
|
||||
return LVector3d::rfu(point_mm[0], get_focal_length(width_mm), point_mm[1]);
|
||||
}
|
||||
|
||||
LPoint2d StitchPerspectiveLens::
|
||||
project(const LVector3d &vec, double width_mm) const {
|
||||
double r = dot(vec, LVector3d::right());
|
||||
double f = dot(vec, LVector3d::forward());
|
||||
double u = dot(vec, LVector3d::up());
|
||||
if (f <= 0.0) {
|
||||
// If the point is in or behind our view plane, project it out to
|
||||
// as near to infinity as we can comfortably manage.
|
||||
return LPoint2d(r / 0.000001, u / 0.000001);
|
||||
} else {
|
||||
return LPoint2d(r / f * get_focal_length(width_mm),
|
||||
u / f * get_focal_length(width_mm));
|
||||
}
|
||||
}
|
||||
|
||||
void StitchPerspectiveLens::
|
||||
make_lens_command(StitchCommand *parent) {
|
||||
StitchCommand *lens_cmd = new StitchCommand(parent, StitchCommand::C_lens);
|
||||
StitchCommand *cmd;
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_perspective);
|
||||
if (_flags & F_focal_length) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_focal_length);
|
||||
cmd->set_length(_focal_length);
|
||||
}
|
||||
if (_flags & F_fov) {
|
||||
cmd = new StitchCommand(lens_cmd, StitchCommand::C_fov);
|
||||
cmd->set_number(_fov);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Filename: stitchPerspectiveLens.h
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHPERSPECTIVELENS_H
|
||||
#define STITCHPERSPECTIVELENS_H
|
||||
|
||||
#include "stitchLens.h"
|
||||
|
||||
class StitchPerspectiveLens : public StitchLens {
|
||||
public:
|
||||
StitchPerspectiveLens();
|
||||
|
||||
virtual void set_hfov(double fov_deg);
|
||||
|
||||
virtual double get_focal_length(double width_mm) const;
|
||||
virtual double get_hfov(double width_mm) const;
|
||||
|
||||
virtual LVector3d extrude(const LPoint2d &point_mm, double width_mm) const;
|
||||
virtual LPoint2d project(const LVector3d &vec, double width_mm) const;
|
||||
|
||||
virtual void make_lens_command(StitchCommand *parent);
|
||||
|
||||
private:
|
||||
double _tan_fov;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// Filename: stitchPoint.cxx
|
||||
// Created by: drose (04Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchPoint.h"
|
||||
|
||||
StitchPoint::
|
||||
StitchPoint(const string &name) :
|
||||
_name(name)
|
||||
{
|
||||
_space_known = false;
|
||||
}
|
||||
|
||||
void StitchPoint::
|
||||
set_space(const LVector3d &space) {
|
||||
_space_known = true;
|
||||
_space = space;
|
||||
}
|
||||
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// Filename: stitchPoint.h
|
||||
// Created by: drose (04Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHPOINT_H
|
||||
#define STITCHPOINT_H
|
||||
|
||||
#include "pandaappbase.h"
|
||||
|
||||
#include "luse.h"
|
||||
#include "pset.h"
|
||||
|
||||
|
||||
class StitchImage;
|
||||
|
||||
class StitchPoint {
|
||||
public:
|
||||
StitchPoint(const string &name);
|
||||
|
||||
void set_space(const LVector3d &space);
|
||||
|
||||
string _name;
|
||||
bool _space_known;
|
||||
LVector3d _space;
|
||||
|
||||
typedef pset<StitchImage *> Images;
|
||||
Images _images;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
// Filename: stitchScreen.cxx
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchScreen.h"
|
||||
|
||||
#include "compose_matrix.h"
|
||||
|
||||
TypeHandle StitchScreen::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchScreen::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchScreen::
|
||||
StitchScreen() :
|
||||
_transform(LMatrix4d::ident_mat()),
|
||||
_inv_transform(LMatrix4d::ident_mat())
|
||||
{
|
||||
_hpr_set = false;
|
||||
_pos_set = false;
|
||||
_hpr.set(0.0, 0.0, 0.0);
|
||||
_pos.set(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchScreen::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
StitchScreen::
|
||||
~StitchScreen() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchScreen::clear_transform
|
||||
// Access: Public
|
||||
// Description: Resets the transform on this screen to identity.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchScreen::
|
||||
clear_transform() {
|
||||
_transform = LMatrix3d::ident_mat();
|
||||
_inv_transform = LMatrix3d::ident_mat();
|
||||
_hpr_set = false;
|
||||
_pos_set = false;
|
||||
_hpr.set(0.0, 0.0, 0.0);
|
||||
_pos.set(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchScreen::set_transform
|
||||
// Access: Public
|
||||
// Description: Sets an arbitrary transform matrix on this screen.
|
||||
// This adjusts the screen's position and/or size in
|
||||
// space accordingly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchScreen::
|
||||
set_transform(const LMatrix4d &trans) {
|
||||
_transform = trans;
|
||||
_inv_transform = invert(trans);
|
||||
LVecBase3d scale;
|
||||
decompose_matrix(_transform, scale, _hpr, _pos);
|
||||
_hpr_set = false;
|
||||
_pos_set = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchScreen::set_hpr
|
||||
// Access: Public
|
||||
// Description: Sets the orientation of the screen, independent of
|
||||
// its position.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchScreen::
|
||||
set_hpr(const LVecBase3d &hpr) {
|
||||
compose_matrix(_transform, LVecBase3d(1.0, 1.0, 1.0), hpr, _pos);
|
||||
_inv_transform.invert_from(_transform);
|
||||
_hpr_set = true;
|
||||
_hpr = hpr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchScreen::set_pos
|
||||
// Access: Public
|
||||
// Description: Sets the position of the screen, independent of
|
||||
// its orientation.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchScreen::
|
||||
set_pos(const LPoint3d &pos) {
|
||||
compose_matrix(_transform, LVecBase3d(1.0, 1.0, 1.0), _hpr, pos);
|
||||
_inv_transform.invert_from(_transform);
|
||||
_pos_set = true;
|
||||
_pos = pos;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchScreen::intersect
|
||||
// Access: Public, Virtual
|
||||
// Description: Determines the intersection point of a ray starting
|
||||
// at the indicated origin, and continuing infinitely in
|
||||
// the indicated direction, with the screen.
|
||||
//
|
||||
// If there is no intersection, leaves result undefined
|
||||
// and returns false. If there is an intersection, sets
|
||||
// result to the intersection point and returns true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool StitchScreen::
|
||||
intersect(LPoint3d &result,
|
||||
const LPoint3d &origin,
|
||||
const LVector3d &direction) const {
|
||||
double t = compute_intersect(origin, direction);
|
||||
if (t < 0.0) {
|
||||
// No intersection.
|
||||
return false;
|
||||
}
|
||||
|
||||
result = origin + direction * t;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
// Filename: stitchScreen.h
|
||||
// Created by: drose (16Jul01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHSCREEN_H
|
||||
#define STITCHSCREEN_H
|
||||
|
||||
#include "luse.h"
|
||||
#include "referenceCount.h"
|
||||
#include "namable.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : StitchScreen
|
||||
// Description : This is an abstract base class defining the interface
|
||||
// to a number of different kinds of screens that images
|
||||
// may be projected onto.
|
||||
//
|
||||
// The shape and position of the screen geometry
|
||||
// determines the net warping of an image transform, but
|
||||
// only when the input projector and the output image
|
||||
// camera are not positioned at the same nodal point.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class StitchScreen : public ReferenceCount, public Namable {
|
||||
public:
|
||||
StitchScreen();
|
||||
virtual ~StitchScreen();
|
||||
|
||||
void clear_transform();
|
||||
void set_transform(const LMatrix4d &transform);
|
||||
void set_hpr(const LVecBase3d &hpr);
|
||||
void set_pos(const LPoint3d &pos);
|
||||
|
||||
virtual bool intersect(LPoint3d &result,
|
||||
const LPoint3d &origin,
|
||||
const LVector3d &direction) const;
|
||||
|
||||
protected:
|
||||
virtual double compute_intersect(const LPoint3d &origin,
|
||||
const LVector3d &direction) const=0;
|
||||
|
||||
protected:
|
||||
bool _hpr_set;
|
||||
LVecBase3d _hpr;
|
||||
bool _pos_set;
|
||||
LPoint3d _pos;
|
||||
LMatrix4d _transform;
|
||||
LMatrix4d _inv_transform;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ReferenceCount::init_type();
|
||||
Namable::init_type();
|
||||
register_type(_type_handle, "StitchScreen",
|
||||
ReferenceCount::get_class_type(),
|
||||
Namable::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class StitchMultiScreen;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#include "config_stitch.cxx"
|
||||
#include "fadeImagePool.cxx"
|
||||
#include "layeredImage.cxx"
|
||||
#include "morphGrid.cxx"
|
||||
#include "triangle.cxx"
|
||||
#include "triangleRasterizer.cxx"
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#include "stitchCommand.cxx"
|
||||
#include "stitchCommandReader.cxx"
|
||||
#include "stitchCylindricalLens.cxx"
|
||||
#include "stitchFile.cxx"
|
||||
#include "stitchFisheyeLens.cxx"
|
||||
#include "stitchImage.cxx"
|
||||
#include "stitchImageOutputter.cxx"
|
||||
#include "stitchImageCommandOutput.cxx"
|
||||
#include "stitchImageRasterizer.cxx"
|
||||
#include "stitchLens.cxx"
|
||||
#include "stitchPSphereLens.cxx"
|
||||
#include "stitchPerspectiveLens.cxx"
|
||||
#include "stitchPoint.cxx"
|
||||
#include "stitcher.cxx"
|
||||
#include "stitchCylindricalScreen.cxx"
|
||||
#include "stitchFlatScreen.cxx"
|
||||
#include "stitchMultiScreen.cxx"
|
||||
#include "stitchScreen.cxx"
|
||||
|
||||
|
|
@ -1,478 +0,0 @@
|
|||
// Filename: stitcher.cxx
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitcher.h"
|
||||
#include "stitchImage.h"
|
||||
#include "stitchPoint.h"
|
||||
|
||||
#include "rotate_to.h"
|
||||
#include "compose_matrix.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
Stitcher::MatchingPoint::
|
||||
MatchingPoint(StitchPoint *p, const LPoint2d &got_uv) :
|
||||
_p(p),
|
||||
_got_uv(got_uv)
|
||||
{
|
||||
_need_uv.set(0.0, 0.0);
|
||||
_diff = 0.0;
|
||||
}
|
||||
|
||||
Stitcher::
|
||||
Stitcher() {
|
||||
_show_points = false;
|
||||
}
|
||||
|
||||
Stitcher::
|
||||
~Stitcher() {
|
||||
}
|
||||
|
||||
void Stitcher::
|
||||
add_image(StitchImage *image) {
|
||||
image->_index = _images.size();
|
||||
_images.push_back(image);
|
||||
|
||||
// Record all of the points in the image as well.
|
||||
StitchImage::Points::const_iterator pi;
|
||||
for (pi = image->_points.begin(); pi != image->_points.end(); ++pi) {
|
||||
string name = (*pi).first;
|
||||
|
||||
Points::iterator ppi;
|
||||
ppi = _points.find(name);
|
||||
StitchPoint *sp;
|
||||
if (ppi != _points.end()) {
|
||||
// Previously used point.
|
||||
sp = (*ppi).second;
|
||||
} else {
|
||||
// New point.
|
||||
sp = new StitchPoint(name);
|
||||
_points.insert(Points::value_type(name, sp));
|
||||
}
|
||||
sp->_images.insert(image);
|
||||
}
|
||||
}
|
||||
|
||||
void Stitcher::
|
||||
add_point(const string &name, const LVector3d &vec) {
|
||||
Points::iterator ppi;
|
||||
ppi = _points.find(name);
|
||||
StitchPoint *sp;
|
||||
if (ppi != _points.end()) {
|
||||
// Previously used point.
|
||||
sp = (*ppi).second;
|
||||
} else {
|
||||
// New point.
|
||||
sp = new StitchPoint(name);
|
||||
_points.insert(Points::value_type(name, sp));
|
||||
}
|
||||
|
||||
sp->set_space(normalize(vec));
|
||||
_loose_points.push_back(sp);
|
||||
}
|
||||
|
||||
|
||||
void Stitcher::
|
||||
show_points(double radius, const Colord &color) {
|
||||
_show_points = true;
|
||||
_point_radius = radius;
|
||||
_point_color = color;
|
||||
}
|
||||
|
||||
|
||||
void Stitcher::
|
||||
stitch() {
|
||||
if (_images.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First place the reference image. All of its points are fixed
|
||||
// where they are.
|
||||
if (_loose_points.empty()) {
|
||||
StitchImage *image = _images.front();
|
||||
assert(image != NULL);
|
||||
|
||||
StitchImage::Points::const_iterator pi;
|
||||
for (pi = image->_points.begin(); pi != image->_points.end(); ++pi) {
|
||||
string name = (*pi).first;
|
||||
LPoint2d uv = (*pi).second;
|
||||
|
||||
Points::iterator ppi;
|
||||
ppi = _points.find(name);
|
||||
assert(ppi != _points.end());
|
||||
StitchPoint *sp = (*ppi).second;
|
||||
|
||||
LVector3d space = normalize(image->extrude(uv));
|
||||
sp->set_space(space);
|
||||
}
|
||||
|
||||
_placed.push_back(image);
|
||||
|
||||
// Report the reference image.
|
||||
nout << "\n" << *image << "\n";
|
||||
_images.erase(_images.begin());
|
||||
}
|
||||
|
||||
// Now place each of the other images relative to the already-known
|
||||
// points.
|
||||
double net_stitch_score = 0.0;
|
||||
bool done = false;
|
||||
|
||||
while (!_images.empty() && !done) {
|
||||
// Find the image with the greatest number of known points.
|
||||
int max_score = 0;
|
||||
Images::iterator best_image = _images.end();
|
||||
|
||||
Images::iterator ii;
|
||||
for (ii = _images.begin(); ii != _images.end(); ++ii) {
|
||||
int score = score_image(*ii);
|
||||
if (score > max_score) {
|
||||
max_score = score;
|
||||
best_image = ii;
|
||||
}
|
||||
}
|
||||
if (best_image == _images.end()) {
|
||||
// Bad news. None of the images had a score greater than zero,
|
||||
// so we can't stitch them in--not enough shared points.
|
||||
done = true;
|
||||
|
||||
} else {
|
||||
// Now stitch this image in and remove it from the set.
|
||||
net_stitch_score += stitch_image(*best_image);
|
||||
_placed.push_back(*best_image);
|
||||
_images.erase(best_image);
|
||||
}
|
||||
}
|
||||
|
||||
// Any of the unplaced images with explicit hpr's get placed where
|
||||
// they are.
|
||||
Images::iterator ii = _images.begin();
|
||||
while (ii != _images.end()) {
|
||||
StitchImage *image = (*ii);
|
||||
if (image->_hpr_set) {
|
||||
net_stitch_score += stitch_image(image);
|
||||
_placed.push_back(image);
|
||||
_images.erase(ii);
|
||||
} else {
|
||||
++ii;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_images.empty()) {
|
||||
nout << "Not enough shared points; " << _images.size()
|
||||
<< " images remain unstitched.\n";
|
||||
}
|
||||
|
||||
nout << "Net score is " << net_stitch_score << "\n";
|
||||
|
||||
// Reorder all of the images by index number order.
|
||||
sort(_placed.begin(), _placed.end(), StitchImageByIndex());
|
||||
|
||||
// And feather the edges between them nicely. We don't need to
|
||||
// feather the first image.
|
||||
if (_placed.size() > 1) {
|
||||
nout << "Feathering edges\n";
|
||||
Images::iterator ii;
|
||||
ii = _placed.begin();
|
||||
for (++ii; ii != _placed.end(); ++ii) {
|
||||
feather_image(*ii);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Stitcher::
|
||||
score_image(StitchImage *image) {
|
||||
// Give the image one point for each StitchPoint it has that has a
|
||||
// known location in space.
|
||||
int score = 0;
|
||||
|
||||
StitchImage::Points::const_iterator pi;
|
||||
for (pi = image->_points.begin(); pi != image->_points.end(); ++pi) {
|
||||
string name = (*pi).first;
|
||||
|
||||
Points::iterator ppi;
|
||||
ppi = _points.find(name);
|
||||
assert(ppi != _points.end());
|
||||
StitchPoint *sp = (*ppi).second;
|
||||
|
||||
if (sp->_space_known) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
|
||||
// We must have at least two points in common to stitch an image.
|
||||
if (score < 2) {
|
||||
score = 0;
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
double Stitcher::
|
||||
stitch_image(StitchImage *image) {
|
||||
// First, collect all the points we have that exist somewhere in
|
||||
// known space.
|
||||
MatchingPoints mp;
|
||||
|
||||
StitchImage::Points::const_iterator pi;
|
||||
for (pi = image->_points.begin(); pi != image->_points.end(); ++pi) {
|
||||
string name = (*pi).first;
|
||||
LPoint2d uv = (*pi).second;
|
||||
|
||||
Points::iterator ppi;
|
||||
ppi = _points.find(name);
|
||||
assert(ppi != _points.end());
|
||||
StitchPoint *sp = (*ppi).second;
|
||||
|
||||
if (sp->_space_known) {
|
||||
mp.push_back(MatchingPoint(sp, uv));
|
||||
}
|
||||
}
|
||||
|
||||
// We need at least two points in common, or one point and an
|
||||
// explicit hpr to stitch.
|
||||
if (mp.size() < 2 && !image->_hpr_set) {
|
||||
nout << "cannot stitch " << image->get_name() << "\n\n";
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double best_score = 0.0;
|
||||
|
||||
if (mp.empty()) {
|
||||
// If we have no points, we can at least place it where the hpr says to.
|
||||
nout << *image << "placed explicitly.\n\n";
|
||||
|
||||
} else {
|
||||
// If we have at least one point, we can stitch something.
|
||||
|
||||
// Reset the image's total transform, since we'll be changing it.
|
||||
image->clear_transform();
|
||||
|
||||
// Find the best match.
|
||||
int best_i = -1;
|
||||
int best_j = -1;
|
||||
|
||||
if (mp.size() < 2) {
|
||||
// If we don't have two points, there's nothing to choose.
|
||||
best_i = 0;
|
||||
best_j = 0;
|
||||
} else {
|
||||
for (int i = 0; i < (int)mp.size(); i++) {
|
||||
for (int j = 0; j < (int)mp.size(); j++) {
|
||||
if (j != i) {
|
||||
LMatrix3d rot;
|
||||
double score = try_match(image, rot, mp, i, j);
|
||||
if (score < best_score || best_i == -1) {
|
||||
best_i = i;
|
||||
best_j = j;
|
||||
best_score = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now go back and actually use the best match.
|
||||
LMatrix3d rot;
|
||||
try_match(image, rot, mp, best_i, best_j);
|
||||
|
||||
image->set_transform(rot);
|
||||
|
||||
if (mp.size() < 2) {
|
||||
nout << *image << "placed semi-explicitly.\n\n";
|
||||
} else {
|
||||
nout << *image << "score is " << best_score << "\n\n";
|
||||
}
|
||||
|
||||
// Now compute the degree of success.
|
||||
MatchingPoints::iterator mi;
|
||||
for (mi = mp.begin(); mi != mp.end(); ++mi) {
|
||||
(*mi)._need_uv = image->project((*mi)._p->_space);
|
||||
(*mi)._diff = (*mi)._need_uv - (*mi)._got_uv;
|
||||
}
|
||||
|
||||
// Now morph the image out the last few pixels so that all the
|
||||
// points will match up exactly.
|
||||
|
||||
int x_verts = image->get_x_verts();
|
||||
int y_verts = image->get_y_verts();
|
||||
image->_morph.init(x_verts, y_verts);
|
||||
int x, y;
|
||||
for (y = 0; y < y_verts; y++) {
|
||||
for (x = 0; x < x_verts; x++) {
|
||||
LPoint2d p = image->get_grid_uv(x, y);
|
||||
LVector2d offset(0.0, 0.0);
|
||||
double net = 0.0;
|
||||
|
||||
MatchingPoints::const_iterator cmi;
|
||||
bool done = false;
|
||||
for (cmi = mp.begin(); cmi != mp.end() && !done; ++cmi) {
|
||||
LVector2d v = p - (*cmi)._got_uv;
|
||||
double d = pow(dot(v, v), 0.1);
|
||||
if (d < 0.0001) {
|
||||
// This one is dead on; stop here and never mind.
|
||||
offset = (*cmi)._diff;
|
||||
net = 1.0;
|
||||
done = true;
|
||||
} else {
|
||||
double scale = 1.0 / d;
|
||||
offset += (*cmi)._diff * scale;
|
||||
net += scale;
|
||||
}
|
||||
}
|
||||
|
||||
offset /= net;
|
||||
image->_morph._table[y][x]._p[MorphGrid::TT_out] += offset;
|
||||
}
|
||||
}
|
||||
image->_morph.recompute();
|
||||
|
||||
|
||||
/*
|
||||
|
||||
for (mi = mp.begin(); mi != mp.end(); ++mi) {
|
||||
LVector3d va = normalize(LVector3d(image->extrude((*mi)._got_uv)));
|
||||
LVector3d vb = (*mi)._p->_space;
|
||||
nout << 1000.0 * (1.0 - dot(va, vb)) << " for " << (*mi)._p->_name
|
||||
<< "\n at " << va << " vs. " << vb << "\n";
|
||||
}
|
||||
nout << "\n";
|
||||
|
||||
// Report the final results, including the morphs, to the user.
|
||||
for (mi = mp.begin(); mi != mp.end(); ++mi) {
|
||||
(*mi)._need_uv = image->project((*mi)._p->_space);
|
||||
(*mi)._diff = (*mi)._need_uv - (*mi)._got_uv;
|
||||
|
||||
nout << (*mi)._p->_name
|
||||
<< " "<< (*mi)._need_uv << " vs. " << (*mi)._got_uv
|
||||
<< " diff is " << length((*mi)._diff * image->_uv_to_pixels)
|
||||
<< " pixels\n";
|
||||
}
|
||||
*/
|
||||
|
||||
// Finally, mark all of the other points in this image as now known
|
||||
// points in space.
|
||||
for (pi = image->_points.begin(); pi != image->_points.end(); ++pi) {
|
||||
string name = (*pi).first;
|
||||
LPoint2d uv = (*pi).second;
|
||||
|
||||
Points::iterator ppi;
|
||||
ppi = _points.find(name);
|
||||
assert(ppi != _points.end());
|
||||
StitchPoint *sp = (*ppi).second;
|
||||
|
||||
if (!sp->_space_known) {
|
||||
LVector3d space = normalize(image->extrude(uv));
|
||||
sp->set_space(space);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best_score;
|
||||
}
|
||||
|
||||
void Stitcher::
|
||||
feather_image(StitchImage *image) {
|
||||
// Feather the edges of the image wherever it overlaps with an image
|
||||
// we have laid down previously. We do this by first determining
|
||||
// which morph points overlap with some other image.
|
||||
int x_verts = image->get_x_verts();
|
||||
int y_verts = image->get_y_verts();
|
||||
|
||||
if (image->_morph.is_empty()) {
|
||||
image->_morph.init(x_verts, y_verts);
|
||||
image->_morph.recompute();
|
||||
}
|
||||
|
||||
int x, y;
|
||||
for (y = 0; y < y_verts; y++) {
|
||||
for (x = 0; x < x_verts; x++) {
|
||||
LVector3d space = image->get_grid_vector(x, y);
|
||||
Images::const_iterator ii;
|
||||
for (ii = _placed.begin();
|
||||
ii != _placed.end() &&
|
||||
!image->_morph._table[y][x]._over_another;
|
||||
++ii) {
|
||||
StitchImage *other = (*ii);
|
||||
if (other->_index < image->_index) {
|
||||
LPoint2d uv = other->project(space);
|
||||
if (uv[0] >= 0.0 && uv[0] <= 1.0 &&
|
||||
uv[1] >= 0.0 && uv[1] <= 1.0) {
|
||||
// This point is over the other image.
|
||||
image->_morph._table[y][x]._over_another = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
image->_morph.fill_alpha();
|
||||
}
|
||||
|
||||
|
||||
double Stitcher::
|
||||
try_match(StitchImage *image, LMatrix3d &rot,
|
||||
const Stitcher::MatchingPoints &mp, int zero, int one) {
|
||||
|
||||
// Now rotate this image relative to the other so the first pair of
|
||||
// points exactly coincide.
|
||||
LVector3d v0a = normalize(image->extrude(mp[zero]._got_uv));
|
||||
LVector3d v0b = mp[zero]._p->_space;
|
||||
|
||||
rotate_to(rot, v0a, v0b);
|
||||
|
||||
if (zero == one) {
|
||||
// Here's a special case: only one matching point. In this case,
|
||||
// we roll by the explicit angle given by the user.
|
||||
if (image->_hpr_set) {
|
||||
rot = rot * LMatrix3d::rotate_mat(image->_hpr[2], v0b);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Now (v0a * rot) == v0b. Roll about this vector till the
|
||||
// second pair of points comes as close as possible to coinciding.
|
||||
LVector3d v1a = normalize(image->extrude(mp[one]._got_uv));
|
||||
LVector3d v1b = mp[one]._p->_space;
|
||||
|
||||
v1a = v1a * rot;
|
||||
|
||||
// We need to determine the appropriate angle to roll. This is the
|
||||
// angle between the plane that contains v0 and v1a, and the plane
|
||||
// that contains v0 and v1b.
|
||||
|
||||
LVector3d normal_a = normalize(cross(v0b, v1a));
|
||||
LVector3d normal_b = normalize(cross(v0b, v1b));
|
||||
|
||||
double cos_theta = dot(normal_a, normal_b);
|
||||
double theta = rad_2_deg(acos(cos_theta));
|
||||
|
||||
rot = rot * LMatrix3d::rotate_mat(-theta, v0b);
|
||||
}
|
||||
|
||||
// Now compute the score.
|
||||
double score = 0.0;
|
||||
|
||||
MatchingPoints::const_iterator mi;
|
||||
for (mi = mp.begin(); mi != mp.end(); ++mi) {
|
||||
LVector3d va = normalize(LVector3d(image->extrude((*mi)._got_uv) * rot));
|
||||
LVector3d vb = (*mi)._p->_space;
|
||||
score += 1.0 - dot(va, vb);
|
||||
}
|
||||
|
||||
return 1000.0 * score;
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
// Filename: stitcher.h
|
||||
// Created by: drose (09Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHER_H
|
||||
#define STITCHER_H
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class StitchPoint;
|
||||
class StitchImage;
|
||||
|
||||
class Stitcher {
|
||||
public:
|
||||
Stitcher();
|
||||
~Stitcher();
|
||||
|
||||
void add_image(StitchImage *image);
|
||||
void add_point(const string &name, const LVector3d &vec);
|
||||
void show_points(double radius, const Colord &color);
|
||||
void stitch();
|
||||
|
||||
typedef vector<StitchImage *> Images;
|
||||
Images _placed;
|
||||
|
||||
typedef vector<StitchPoint *> LoosePoints;
|
||||
LoosePoints _loose_points;
|
||||
bool _show_points;
|
||||
double _point_radius;
|
||||
Colord _point_color;
|
||||
|
||||
private:
|
||||
class MatchingPoint {
|
||||
public:
|
||||
MatchingPoint(StitchPoint *p, const LPoint2d &got_uv);
|
||||
|
||||
StitchPoint *_p;
|
||||
LPoint2d _need_uv;
|
||||
LPoint2d _got_uv;
|
||||
LVector2d _diff;
|
||||
};
|
||||
typedef vector<MatchingPoint> MatchingPoints;
|
||||
|
||||
int score_image(StitchImage *image);
|
||||
double stitch_image(StitchImage *image);
|
||||
void feather_image(StitchImage *image);
|
||||
|
||||
double try_match(StitchImage *image, LMatrix3d &rot,
|
||||
const MatchingPoints &mp, int zero, int one);
|
||||
|
||||
Images _images;
|
||||
|
||||
typedef map<string, StitchPoint *> Points;
|
||||
Points _points;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
// Filename: triangle.cxx
|
||||
// Created by: drose (16Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "triangle.h"
|
||||
|
||||
inline int
|
||||
is_right(const LVector2d &v1, const LVector2d &v2) {
|
||||
return (-v1[0] * v2[1] + v1[1] * v2[0]) < 0.0;
|
||||
}
|
||||
|
||||
bool
|
||||
triangle_contains_point(const LPoint2d &p, const LPoint2d &v0,
|
||||
const LPoint2d &v1, const LPoint2d &v2) {
|
||||
// In the case of a triangle defined with points in counterclockwise
|
||||
// order, a point is interior to the triangle iff the point is not
|
||||
// right of each of the edges.
|
||||
|
||||
if (is_right(p - v0, v1 - v0)) {
|
||||
return false;
|
||||
}
|
||||
if (is_right(p - v1, v2 - v1)) {
|
||||
return false;
|
||||
}
|
||||
if (is_right(p - v2, v0 - v2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
triangle_contains_circle(const LPoint2d &p, double radius,
|
||||
const LPoint2d &v0,
|
||||
const LPoint2d &v1, const LPoint2d &v2) {
|
||||
// This is a cheesy hack. Instead of performing an actual
|
||||
// triangle-circle intersection test, we simply move the point
|
||||
// radius units closer to the centroid of the triangle, and test
|
||||
// that point for intersection.
|
||||
|
||||
LPoint2d centroid = (v0 + v1 + v2) / 3.0;
|
||||
|
||||
LVector2d vec = centroid - p;
|
||||
double d = length(vec);
|
||||
if (d <= radius) {
|
||||
// We were already closer than radius distance from the centroid;
|
||||
// this is an automatic intersection.
|
||||
return true;
|
||||
}
|
||||
|
||||
LPoint2d new_p = p + radius * (vec / d);
|
||||
return triangle_contains_point(new_p, v0, v1, v2);
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Filename: triangle.h
|
||||
// Created by: drose (16Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIANGLE_H
|
||||
#define TRIANGLE_H
|
||||
|
||||
#include "luse.h"
|
||||
|
||||
// A handy triangle utility. Maybe more later.
|
||||
|
||||
// The triangle must be defined with vertices in counter-clockwise
|
||||
// order.
|
||||
bool
|
||||
triangle_contains_point(const LPoint2d &p, const LPoint2d &v0,
|
||||
const LPoint2d &v1, const LPoint2d &v2);
|
||||
|
||||
bool
|
||||
triangle_contains_circle(const LPoint2d &p, double radius,
|
||||
const LPoint2d &v0,
|
||||
const LPoint2d &v1, const LPoint2d &v2);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,589 +0,0 @@
|
|||
// Filename: triangleRasterizer.cxx
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "triangleRasterizer.h"
|
||||
#include "stitchImage.h"
|
||||
|
||||
// Inline function declared up here for the forward reference.
|
||||
inline void TriangleRasterizer::
|
||||
filter_pixel(RGBColord &rgb, double &alpha,
|
||||
double s, double t,
|
||||
double dsdx, double dtdx, double dsdy, double dtdy) {
|
||||
filter_pixel(rgb, alpha, s, t,
|
||||
max(max(dsdx, dtdx), max(dsdy, dtdy)) / 2.0);
|
||||
}
|
||||
|
||||
|
||||
TriangleRasterizer::Edge::
|
||||
Edge(const RasterizerVertex *v0, const RasterizerVertex *v1) :
|
||||
_v0(v0), _v1(v1)
|
||||
{
|
||||
_dx = v1->_p[0] - v0->_p[0];
|
||||
_dy = v1->_p[1] - v0->_p[1];
|
||||
}
|
||||
|
||||
TriangleRasterizer::
|
||||
TriangleRasterizer() {
|
||||
_output = NULL;
|
||||
_input = NULL;
|
||||
_read_input = false;
|
||||
_texture = NULL;
|
||||
_filter_output = false;
|
||||
_untextured_color.set(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
void TriangleRasterizer::
|
||||
draw_triangle(const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1,
|
||||
const RasterizerVertex *v2) {
|
||||
if ((v0->_visibility & v1->_visibility & v2->_visibility) != 0) {
|
||||
// All three vertices are out of bounds in the same direction, so
|
||||
// the triangle is completely out of bounds. Don't bother trying
|
||||
// to draw it.
|
||||
return;
|
||||
}
|
||||
if (v0->_visibility < 0 || v1->_visibility < 0 || v2->_visibility < 0) {
|
||||
// At least one vertex is totally bogus, so throw up our hands on
|
||||
// the triangle.
|
||||
return;
|
||||
}
|
||||
|
||||
assert(_output != NULL);
|
||||
if (!_read_input) {
|
||||
read_input();
|
||||
}
|
||||
|
||||
double oneOverArea;
|
||||
const RasterizerVertex *vMin, *vMid, *vMax;
|
||||
/* Y(vMin)<=Y(vMid)<=Y(vMax) */
|
||||
|
||||
/* find the order of the 3 vertices along the Y axis */
|
||||
{
|
||||
double y0 = v0->_p[1];
|
||||
double y1 = v1->_p[1];
|
||||
double y2 = v2->_p[1];
|
||||
|
||||
if (y0<=y1) {
|
||||
if (y1<=y2) {
|
||||
vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */
|
||||
} else if (y2<=y0) {
|
||||
vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */
|
||||
} else {
|
||||
vMin = v0; vMid = v2; vMax = v1; /* y0<=y2<=y1 */
|
||||
}
|
||||
} else {
|
||||
if (y0<=y2) {
|
||||
vMin = v1; vMid = v0; vMax = v2; /* y1<=y0<=y2 */
|
||||
} else if (y2<=y1) {
|
||||
vMin = v2; vMid = v1; vMax = v0; /* y2<=y1<=y0 */
|
||||
} else {
|
||||
vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vertex/edge relationship */
|
||||
Edge eMaj(vMin, vMax);
|
||||
Edge eTop(vMid, vMax);
|
||||
Edge eBot(vMin, vMid);
|
||||
|
||||
/* compute oneOverArea */
|
||||
{
|
||||
double area = eMaj._dx * eBot._dy - eBot._dx * eMaj._dy;
|
||||
|
||||
// We can't cull very small triangles; we might generate small
|
||||
// triangles through normal operations.
|
||||
|
||||
/*
|
||||
if (area>-0.05 && area<0.05) {
|
||||
return; // very small; CULLED
|
||||
}
|
||||
*/
|
||||
oneOverArea = 1.0 / area;
|
||||
}
|
||||
|
||||
/* Edge setup. For a triangle strip these could be reused... */
|
||||
{
|
||||
/* fixed point Y coordinates */
|
||||
FixedPoint vMin_fx = FloatToFixed(vMin->_p[0] + 0.5);
|
||||
FixedPoint vMin_fy = FloatToFixed(vMin->_p[1] - 0.5);
|
||||
FixedPoint vMid_fx = FloatToFixed(vMid->_p[0] + 0.5);
|
||||
FixedPoint vMid_fy = FloatToFixed(vMid->_p[1] - 0.5);
|
||||
FixedPoint vMax_fy = FloatToFixed(vMax->_p[1] - 0.5);
|
||||
|
||||
eMaj._fsy = FixedCeil(vMin_fy);
|
||||
eMaj._lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eMaj._fsy);
|
||||
if (eMaj._lines > 0) {
|
||||
double dxdy = eMaj._dx / eMaj._dy;
|
||||
eMaj._fdxdy = SignedFloatToFixed(dxdy);
|
||||
eMaj._adjy = (double) (eMaj._fsy - vMin_fy); /* SCALED! */
|
||||
eMaj._fx0 = vMin_fx;
|
||||
eMaj._fsx = eMaj._fx0 + (FixedPoint) (eMaj._adjy * dxdy);
|
||||
}
|
||||
else {
|
||||
return; /*CULLED*/
|
||||
}
|
||||
|
||||
eTop._fsy = FixedCeil(vMid_fy);
|
||||
eTop._lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eTop._fsy);
|
||||
if (eTop._lines > 0) {
|
||||
double dxdy = eTop._dx / eTop._dy;
|
||||
eTop._fdxdy = SignedFloatToFixed(dxdy);
|
||||
eTop._adjy = (double) (eTop._fsy - vMid_fy); /* SCALED! */
|
||||
eTop._fx0 = vMid_fx;
|
||||
eTop._fsx = eTop._fx0 + (FixedPoint) (eTop._adjy * dxdy);
|
||||
}
|
||||
|
||||
eBot._fsy = FixedCeil(vMin_fy);
|
||||
eBot._lines = FixedToInt(vMid_fy + FIXED_ONE - FIXED_EPSILON - eBot._fsy);
|
||||
if (eBot._lines > 0) {
|
||||
double dxdy = eBot._dx / eBot._dy;
|
||||
eBot._fdxdy = SignedFloatToFixed(dxdy);
|
||||
eBot._adjy = (double) (eBot._fsy - vMin_fy); /* SCALED! */
|
||||
eBot._fx0 = vMin_fx;
|
||||
eBot._fsx = eBot._fx0 + (FixedPoint) (eBot._adjy * dxdy);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Conceptually, we view a triangle as two subtriangles
|
||||
* separated by a perfectly horizontal line. The edge that is
|
||||
* intersected by this line is one with maximal absolute dy; we
|
||||
* call it a ``major'' edge. The other two edges are the
|
||||
* ``top'' edge (for the upper subtriangle) and the ``bottom''
|
||||
* edge (for the lower subtriangle). If either of these two
|
||||
* edges is horizontal or very close to horizontal, the
|
||||
* corresponding subtriangle might cover zero sample points;
|
||||
* we take care to handle such cases, for performance as well
|
||||
* as correctness.
|
||||
*
|
||||
* By stepping rasterization parameters along the major edge,
|
||||
* we can avoid recomputing them at the discontinuity where
|
||||
* the top and bottom edges meet. However, this forces us to
|
||||
* be able to scan both left-to-right and right-to-left.
|
||||
* Also, we must determine whether the major edge is at the
|
||||
* left or right side of the triangle. We do this by
|
||||
* computing the magnitude of the cross-product of the major
|
||||
* and top edges. Since this magnitude depends on the sine of
|
||||
* the angle between the two edges, its sign tells us whether
|
||||
* we turn to the left or to the right when travelling along
|
||||
* the major edge to the top edge, and from this we infer
|
||||
* whether the major edge is on the left or the right.
|
||||
*
|
||||
* Serendipitously, this cross-product magnitude is also a
|
||||
* value we need to compute the iteration parameter
|
||||
* derivatives for the triangle, and it can be used to perform
|
||||
* backface culling because its sign tells us whether the
|
||||
* triangle is clockwise or counterclockwise. In this code we
|
||||
* refer to it as ``area'' because it's also proportional to
|
||||
* the pixel area of the triangle.
|
||||
*/
|
||||
|
||||
{
|
||||
int ltor; /* true if scanning left-to-right */
|
||||
|
||||
// For interpolating the alpha value.
|
||||
double dadx, dady;
|
||||
FixedPoint fdadx;
|
||||
|
||||
// For interpolating texture coordinates.
|
||||
double dsdx, dsdy;
|
||||
FixedPoint fdsdx;
|
||||
double dtdx, dtdy;
|
||||
FixedPoint fdtdx;
|
||||
|
||||
// Set up values for texture coordinates.
|
||||
|
||||
double twidth, theight;
|
||||
if (_texture != NULL) {
|
||||
twidth = (double) _texture->get_x_size();
|
||||
theight = (double) _texture->get_y_size();
|
||||
} else {
|
||||
twidth = 1.0;
|
||||
theight = 1.0;
|
||||
}
|
||||
|
||||
ltor = (oneOverArea < 0.0);
|
||||
|
||||
// More alpha setup.
|
||||
{
|
||||
double eMaj_da, eBot_da;
|
||||
eMaj_da = vMax->_alpha - vMin->_alpha;
|
||||
eBot_da = vMid->_alpha - vMin->_alpha;
|
||||
dadx = oneOverArea * (eMaj_da * eBot._dy - eMaj._dy * eBot_da);
|
||||
fdadx = SignedFloatToFixed(dadx);
|
||||
dady = oneOverArea * (eMaj._dx * eBot_da - eMaj_da * eBot._dx);
|
||||
}
|
||||
|
||||
// Texture coordinates.
|
||||
{
|
||||
double eMaj_ds, eBot_ds;
|
||||
eMaj_ds = (vMax->_uv[0] - vMin->_uv[0]) * twidth;
|
||||
eBot_ds = (vMid->_uv[0] - vMin->_uv[0]) * twidth;
|
||||
|
||||
dsdx = oneOverArea * (eMaj_ds * eBot._dy - eMaj._dy * eBot_ds);
|
||||
fdsdx = SignedFloatToFixed(dsdx);
|
||||
dsdy = oneOverArea * (eMaj._dx * eBot_ds - eMaj_ds * eBot._dx);
|
||||
}
|
||||
{
|
||||
double eMaj_dt, eBot_dt;
|
||||
eMaj_dt = (vMax->_uv[1] - vMin->_uv[1]) * theight;
|
||||
eBot_dt = (vMid->_uv[1] - vMin->_uv[1]) * theight;
|
||||
|
||||
dtdx = oneOverArea * (eMaj_dt * eBot._dy - eMaj._dy * eBot_dt);
|
||||
fdtdx = SignedFloatToFixed(dtdx);
|
||||
dtdy = oneOverArea * (eMaj._dx * eBot_dt - eMaj_dt * eBot._dx);
|
||||
}
|
||||
|
||||
/*
|
||||
* We always sample at pixel centers. However, we avoid
|
||||
* explicit half-pixel offsets in this code by incorporating
|
||||
* the proper offset in each of x and y during the
|
||||
* transformation to window coordinates.
|
||||
*
|
||||
* We also apply the usual rasterization rules to prevent
|
||||
* cracks and overlaps. A pixel is considered inside a
|
||||
* subtriangle if it meets all of four conditions: it is on or
|
||||
* to the right of the left edge, strictly to the left of the
|
||||
* right edge, on or below the top edge, and strictly above
|
||||
* the bottom edge. (Some edges may be degenerate.)
|
||||
*
|
||||
* The following discussion assumes left-to-right scanning
|
||||
* (that is, the major edge is on the left); the right-to-left
|
||||
* case is a straightforward variation.
|
||||
*
|
||||
* We start by finding the half-integral y coordinate that is
|
||||
* at or below the top of the triangle. This gives us the
|
||||
* first scan line that could possibly contain pixels that are
|
||||
* inside the triangle.
|
||||
*
|
||||
* Next we creep down the major edge until we reach that y,
|
||||
* and compute the corresponding x coordinate on the edge.
|
||||
* Then we find the half-integral x that lies on or just
|
||||
* inside the edge. This is the first pixel that might lie in
|
||||
* the interior of the triangle. (We won't know for sure
|
||||
* until we check the other edges.)
|
||||
*
|
||||
* As we rasterize the triangle, we'll step down the major
|
||||
* edge. For each step in y, we'll move an integer number
|
||||
* of steps in x. There are two possible x step sizes, which
|
||||
* we'll call the ``inner'' step (guaranteed to land on the
|
||||
* edge or inside it) and the ``outer'' step (guaranteed to
|
||||
* land on the edge or outside it). The inner and outer steps
|
||||
* differ by one. During rasterization we maintain an error
|
||||
* term that indicates our distance from the true edge, and
|
||||
* select either the inner step or the outer step, whichever
|
||||
* gets us to the first pixel that falls inside the triangle.
|
||||
*
|
||||
* All parameters (z, red, etc.) as well as the buffer
|
||||
* addresses for color and z have inner and outer step values,
|
||||
* so that we can increment them appropriately. This method
|
||||
* eliminates the need to adjust parameters by creeping a
|
||||
* sub-pixel amount into the triangle at each scanline.
|
||||
*/
|
||||
|
||||
{
|
||||
int subTriangle;
|
||||
FixedPoint fx, fxLeftEdge, fxRightEdge, fdxLeftEdge, fdxRightEdge;
|
||||
FixedPoint fdxOuter;
|
||||
int idxOuter;
|
||||
double dxOuter;
|
||||
FixedPoint fError, fdError;
|
||||
double adjx, adjy;
|
||||
FixedPoint fy;
|
||||
int iy;
|
||||
|
||||
// Alpha.
|
||||
FixedPoint fa, fdaOuter, fdaInner;
|
||||
|
||||
// Texture coordinates.
|
||||
FixedPoint fs, fdsOuter, fdsInner;
|
||||
FixedPoint ft, fdtOuter, fdtInner;
|
||||
|
||||
for (subTriangle=0; subTriangle<=1; subTriangle++) {
|
||||
Edge *eLeft, *eRight;
|
||||
int setupLeft, setupRight;
|
||||
int lines;
|
||||
|
||||
if (subTriangle==0) {
|
||||
/* bottom half */
|
||||
if (ltor) {
|
||||
eLeft = &eMaj;
|
||||
eRight = &eBot;
|
||||
lines = eRight->_lines;
|
||||
setupLeft = 1;
|
||||
setupRight = 1;
|
||||
}
|
||||
else {
|
||||
eLeft = &eBot;
|
||||
eRight = &eMaj;
|
||||
lines = eLeft->_lines;
|
||||
setupLeft = 1;
|
||||
setupRight = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* top half */
|
||||
if (ltor) {
|
||||
eLeft = &eMaj;
|
||||
eRight = &eTop;
|
||||
lines = eRight->_lines;
|
||||
setupLeft = 0;
|
||||
setupRight = 1;
|
||||
}
|
||||
else {
|
||||
eLeft = &eTop;
|
||||
eRight = &eMaj;
|
||||
lines = eLeft->_lines;
|
||||
setupLeft = 1;
|
||||
setupRight = 0;
|
||||
}
|
||||
if (lines==0) return;
|
||||
}
|
||||
|
||||
if (setupLeft && eLeft->_lines>0) {
|
||||
const RasterizerVertex *vLower;
|
||||
FixedPoint fsx = eLeft->_fsx;
|
||||
fx = FixedCeil(fsx);
|
||||
fError = fx - fsx - FIXED_ONE;
|
||||
fxLeftEdge = fsx - FIXED_EPSILON;
|
||||
fdxLeftEdge = eLeft->_fdxdy;
|
||||
fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
|
||||
fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
|
||||
idxOuter = FixedToInt(fdxOuter);
|
||||
dxOuter = (double) idxOuter;
|
||||
|
||||
fy = eLeft->_fsy;
|
||||
iy = FixedToInt(fy);
|
||||
|
||||
adjx = (double)(fx - eLeft->_fx0); /* SCALED! */
|
||||
adjy = eLeft->_adjy; /* SCALED! */
|
||||
|
||||
vLower = eLeft->_v0;
|
||||
|
||||
/*
|
||||
* Now we need the set of parameter (z, color, etc.) values at
|
||||
* the point (fx, fy). This gives us properly-sampled parameter
|
||||
* values that we can step from pixel to pixel. Furthermore,
|
||||
* although we might have intermediate results that overflow
|
||||
* the normal parameter range when we step temporarily outside
|
||||
* the triangle, we shouldn't overflow or underflow for any
|
||||
* pixel that's actually inside the triangle.
|
||||
*/
|
||||
|
||||
// Interpolate alpha
|
||||
fa = (FixedPoint)(vLower->_alpha * FIXED_SCALE + dadx * adjx + dady * adjy)
|
||||
+ FIXED_HALF;
|
||||
fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
|
||||
// Interpolate texture coordinates
|
||||
{
|
||||
double s0, t0;
|
||||
s0 = vLower->_uv[0] * twidth;
|
||||
fs = (FixedPoint)(s0 * FIXED_SCALE + dsdx * adjx + dsdy * adjy) + FIXED_HALF;
|
||||
fdsOuter = SignedFloatToFixed(dsdy + dxOuter * dsdx);
|
||||
t0 = vLower->_uv[1] * theight;
|
||||
ft = (FixedPoint)(t0 * FIXED_SCALE + dtdx * adjx + dtdy * adjy) + FIXED_HALF;
|
||||
fdtOuter = SignedFloatToFixed(dtdy + dxOuter * dtdx);
|
||||
}
|
||||
|
||||
} /*if setupLeft*/
|
||||
|
||||
|
||||
if (setupRight && eRight->_lines>0) {
|
||||
fxRightEdge = eRight->_fsx - FIXED_EPSILON;
|
||||
fdxRightEdge = eRight->_fdxdy;
|
||||
}
|
||||
|
||||
if (lines==0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Rasterize setup */
|
||||
fdaInner = fdaOuter + fdadx;
|
||||
fdsInner = fdsOuter + fdsdx;
|
||||
fdtInner = fdtOuter + fdtdx;
|
||||
|
||||
while (lines>0) {
|
||||
if (iy >= 0 && iy < _output->get_y_size()) {
|
||||
/* initialize the span interpolants to the leftmost value */
|
||||
/* ff = fixed-pt fragment */
|
||||
FixedPoint ffa = fa;
|
||||
FixedPoint ffs = fs, fft = ft;
|
||||
|
||||
int left = FixedToInt(fxLeftEdge);
|
||||
int right = FixedToInt(fxRightEdge);
|
||||
|
||||
// Alpha
|
||||
{
|
||||
// FixedPoint ffaend = ffa+(right-left-1)*fdadx;
|
||||
// if (ffaend<0) ffa -= ffaend;
|
||||
// if (ffa<0) ffa = 0;
|
||||
}
|
||||
|
||||
// Rasterize left to right at row iy.
|
||||
if (right > left) {
|
||||
ffs -= FIXED_HALF; /* off-by-one error? */
|
||||
fft -= FIXED_HALF;
|
||||
ffa -= FIXED_HALF;
|
||||
for (int ix = left; ix < right; ix++) {
|
||||
if (ix >= 0 && ix < _output->get_x_size()) {
|
||||
RGBColord rgb;
|
||||
double alpha;
|
||||
filter_pixel(rgb, alpha,
|
||||
FixedToFloat(ffs), FixedToFloat(fft),
|
||||
dsdx, dtdx, dsdy, dtdy);
|
||||
alpha *= FixedToFloat(ffa);
|
||||
_output->blend(ix, iy, rgb, alpha);
|
||||
}
|
||||
|
||||
ffs += fdsdx;
|
||||
fft += fdtdx;
|
||||
ffa += fdadx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance to the next scan line. Compute the
|
||||
* new edge coordinates, and adjust the
|
||||
* pixel-center x coordinate so that it stays
|
||||
* on or inside the major edge.
|
||||
*/
|
||||
iy++;
|
||||
lines--;
|
||||
|
||||
fxLeftEdge += fdxLeftEdge;
|
||||
fxRightEdge += fdxRightEdge;
|
||||
|
||||
fError += fdError;
|
||||
if (fError >= 0) {
|
||||
fError -= FIXED_ONE;
|
||||
|
||||
fa += fdaOuter;
|
||||
fs += fdsOuter;
|
||||
ft += fdtOuter;
|
||||
} else {
|
||||
fa += fdaInner;
|
||||
fs += fdsInner;
|
||||
ft += fdtInner;
|
||||
}
|
||||
} /*while lines>0*/
|
||||
|
||||
} /* for subTriangle */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TriangleRasterizer::
|
||||
draw_pixel(const RasterizerVertex *v0, double radius) {
|
||||
if (v0->_visibility != 0) {
|
||||
// The pixel is off the screen.
|
||||
return;
|
||||
}
|
||||
int ix = (int)v0->_p[0];
|
||||
int iy = (int)v0->_p[1];
|
||||
|
||||
if (iy >= 0 && iy < _output->get_y_size() &&
|
||||
ix >= 0 && ix < _output->get_x_size()) {
|
||||
if (!_read_input) {
|
||||
read_input();
|
||||
}
|
||||
|
||||
RGBColord rgb;
|
||||
double alpha;
|
||||
if (_texture == NULL) {
|
||||
filter_pixel(rgb, alpha, v0->_uv[0], v0->_uv[1], radius);
|
||||
} else {
|
||||
filter_pixel(rgb, alpha,
|
||||
v0->_uv[0] * (_texture->get_x_size() - 1),
|
||||
v0->_uv[1] * (_texture->get_y_size() - 1),
|
||||
radius * (_texture->get_x_size() - 1));
|
||||
}
|
||||
alpha *= v0->_alpha;
|
||||
_output->blend(ix, iy, rgb, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void TriangleRasterizer::
|
||||
filter_pixel(RGBColord &rgb, double &alpha,
|
||||
double s, double t, double radius) {
|
||||
if (_texture == NULL) {
|
||||
rgb.set(_untextured_color[0],
|
||||
_untextured_color[1],
|
||||
_untextured_color[2]);
|
||||
alpha = _untextured_color[3];
|
||||
return;
|
||||
}
|
||||
|
||||
int ri = (int)radius;
|
||||
int si = (int)(s + 0.5);
|
||||
int ti = _texture->get_y_size() - 1 - (int)(t + 0.5);
|
||||
|
||||
rgb.set(0.0, 0.0, 0.0);
|
||||
alpha = 0.0;
|
||||
|
||||
if (!_filter_output) {
|
||||
if (si >= 0 && si < _texture->get_x_size() &&
|
||||
ti >= 0 && ti < _texture->get_y_size()) {
|
||||
rgb = _texture->get_xel(si, ti);
|
||||
alpha = 1.0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int num_total = 0;
|
||||
int num_visible = 0;
|
||||
for (int yr = -ri; yr <= ri; yr++) {
|
||||
int tii = ti + yr;
|
||||
for (int xr = -ri; xr <= ri; xr++) {
|
||||
int sii = si + xr;
|
||||
if (sii >= 0 && sii < _texture->get_x_size() &&
|
||||
tii >= 0 && tii < _texture->get_y_size()) {
|
||||
rgb += _texture->get_xel(sii, tii);
|
||||
num_visible++;
|
||||
}
|
||||
num_total++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_visible != 0) {
|
||||
rgb /= (double)num_visible;
|
||||
alpha = 1.0;
|
||||
}
|
||||
|
||||
// We would do this to antialias the edge of the image. However, it
|
||||
// seems to cause problems at seams, so we won't do it.
|
||||
/*
|
||||
if (num_total != 0) {
|
||||
alpha = (double)num_visible / (double)num_total;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void TriangleRasterizer::
|
||||
read_input() {
|
||||
if (_input != NULL) {
|
||||
if (!_input->read_file()) {
|
||||
nout << "Unable to read image.\n";
|
||||
} else {
|
||||
_texture = _input->_data;
|
||||
}
|
||||
}
|
||||
_read_input = true;
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
// Filename: triangleRasterizer.h
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIANGLERASTERIZER_H
|
||||
#define TRIANGLERASTERIZER_H
|
||||
|
||||
#include "fixedPoint.h"
|
||||
|
||||
#include "luse.h"
|
||||
#include <pnmImage.h>
|
||||
|
||||
class StitchImage;
|
||||
|
||||
class RasterizerVertex {
|
||||
public:
|
||||
LPoint2d _p;
|
||||
LPoint2d _uv;
|
||||
LVector3d _space;
|
||||
double _alpha;
|
||||
int _visibility;
|
||||
};
|
||||
|
||||
class TriangleRasterizer {
|
||||
public:
|
||||
TriangleRasterizer();
|
||||
|
||||
void draw_triangle(const RasterizerVertex *v0,
|
||||
const RasterizerVertex *v1,
|
||||
const RasterizerVertex *v2);
|
||||
void draw_pixel(const RasterizerVertex *v0, double radius);
|
||||
|
||||
PNMImage *_output;
|
||||
StitchImage *_input;
|
||||
bool _read_input;
|
||||
const PNMImage *_texture;
|
||||
bool _filter_output;
|
||||
Colord _untextured_color;
|
||||
|
||||
private:
|
||||
class Edge {
|
||||
public:
|
||||
Edge(const RasterizerVertex *v0, const RasterizerVertex *v1);
|
||||
|
||||
const RasterizerVertex *_v0; // Y(v0) < Y(v1)
|
||||
const RasterizerVertex *_v1;
|
||||
double _dx; // X(v1) - X(v0)
|
||||
double _dy; // Y(v1) - Y(v0)
|
||||
FixedPoint _fdxdy; // dx/dy in fixed-point
|
||||
FixedPoint _fsx; // first sample point x coord
|
||||
FixedPoint _fsy;
|
||||
double _adjy; // adjust from v[0]->fy to fsy, scaled
|
||||
int _lines; // number of lines to be sampled on this edge
|
||||
FixedPoint _fx0; // fixed pt X of lower endpoint
|
||||
};
|
||||
|
||||
inline void filter_pixel(RGBColord &rgb, double &alpha,
|
||||
double s, double t,
|
||||
double dsdx, double dtdx, double dsdy, double dtdy);
|
||||
void filter_pixel(RGBColord &rgb, double &alpha,
|
||||
double s, double t, double radius);
|
||||
|
||||
void read_input();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// This directory is temporarily commented out until it can be brought
|
||||
// into the new scene graph.
|
||||
#define BUILD_DIRECTORY
|
||||
|
||||
#begin ss_lib_target
|
||||
#define TARGET stitchviewer
|
||||
#define LOCAL_LIBS stitchbase
|
||||
#define OTHER_LIBS \
|
||||
progbase converter \
|
||||
device:c tform:c graph:c dgraph:c sgraph:c gobj:c pnmimage:c \
|
||||
sgattrib:c event:c chancfg:c display:c sgraphutil:c light:c putil:c \
|
||||
express:c panda:m
|
||||
|
||||
#define SOURCES \
|
||||
stitchImageConverter.cxx stitchImageConverter.h \
|
||||
stitchImageVisualizer.cxx stitchImageVisualizer.h triangleMesh.cxx \
|
||||
triangleMesh.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
stitchImageConverter.h stitchImageVisualizer.h triangleMesh.h
|
||||
|
||||
#end ss_lib_target
|
||||
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
// Filename: stitchImageConverter.cxx
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchImageConverter.h"
|
||||
#include "stitchImage.h"
|
||||
#include "triangleMesh.h"
|
||||
|
||||
#include "geomTristrip.h"
|
||||
#include "geomNode.h"
|
||||
#include "texture.h"
|
||||
#include "textureTransition.h"
|
||||
#include "chancfg.h"
|
||||
#include "camera.h"
|
||||
#include "perspectiveLens.h"
|
||||
#include "frustum.h"
|
||||
|
||||
StitchImageConverter::
|
||||
StitchImageConverter() {
|
||||
_output_image = NULL;
|
||||
}
|
||||
|
||||
void StitchImageConverter::
|
||||
add_output_image(StitchImage *image) {
|
||||
_output_image = image;
|
||||
}
|
||||
|
||||
void StitchImageConverter::
|
||||
override_chan_cfg(ChanCfgOverrides &override) {
|
||||
override.setField(ChanCfgOverrides::Mask,
|
||||
((unsigned int)(W_DOUBLE|W_DEPTH|W_MULTISAMPLE)));
|
||||
override.setField(ChanCfgOverrides::Title, "Stitch");
|
||||
|
||||
LVecBase2d size = _output_image->get_size_pixels();
|
||||
|
||||
override.setField(ChanCfgOverrides::SizeX, (int)size[0]);
|
||||
override.setField(ChanCfgOverrides::SizeY, (int)size[1]);
|
||||
}
|
||||
|
||||
void StitchImageConverter::
|
||||
setup_camera(const RenderRelation &camera_arc) {
|
||||
PT(Camera) cam = DCAST(Camera, camera_arc.get_child());
|
||||
|
||||
PT(Lens) lens = new PerspectiveLens;
|
||||
cam->set_lens(lens);
|
||||
}
|
||||
|
||||
bool StitchImageConverter::
|
||||
is_interactive() const {
|
||||
//return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void StitchImageConverter::
|
||||
create_image_geometry(Image &im) {
|
||||
assert(_output_image != NULL);
|
||||
|
||||
// double dist = 1.0 + (double)im._index / (double)_images.size();
|
||||
#if 0
|
||||
int x_verts = _output_image->get_x_verts();
|
||||
int y_verts = _output_image->get_y_verts();
|
||||
TriangleMesh mesh(x_verts, y_verts);
|
||||
|
||||
for (int xi = 0; xi < x_verts; xi++) {
|
||||
for (int yi = 0; yi < y_verts; yi++) {
|
||||
LVector2d uvd =
|
||||
im._image->project(_output_image->get_grid_vector(xi, yi));
|
||||
LVector2f uvf(uvd);
|
||||
|
||||
LVector3f p = LVector3f::rfu(2 * (double)xi / (double)(x_verts - 1) - 1,
|
||||
1.0,
|
||||
1 - 2 * (double)yi / (double)(y_verts - 1));
|
||||
mesh._coords.push_back(p);
|
||||
mesh._texcoords.push_back(uvf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int x_verts = im._image->get_x_verts();
|
||||
int y_verts = im._image->get_y_verts();
|
||||
TriangleMesh mesh(x_verts, y_verts);
|
||||
|
||||
for (int xi = 0; xi < x_verts; xi++) {
|
||||
for (int yi = 0; yi < y_verts; yi++) {
|
||||
LVector2d uvd =
|
||||
_output_image->project(im._image->get_grid_vector(xi, yi));
|
||||
|
||||
LVector3f p = LVector3f::rfu(2 * uvd[0] - 1,
|
||||
1.0,
|
||||
2 * uvd[1] - 1);
|
||||
LPoint2f uvf((double)xi / (double)(x_verts - 1),
|
||||
1.0 - (double)yi / (double)(y_verts - 1));
|
||||
mesh._coords.push_back(p);
|
||||
mesh._texcoords.push_back(uvf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PT(GeomTristrip) geom = mesh.build_mesh();
|
||||
|
||||
PT(GeomNode) node = new GeomNode;
|
||||
node->add_geom(geom.p());
|
||||
|
||||
im._arc = new RenderRelation(_render, node);
|
||||
|
||||
if (im._image->_data != NULL) {
|
||||
im._tex = new Texture;
|
||||
im._tex->set_name(im._image->get_filename());
|
||||
im._tex->load(*im._image->_data);
|
||||
im._arc->set_transition(new TextureTransition(im._tex));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
// Filename: stitchImageConverter.h
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHIMAGECONVERTER_H
|
||||
#define STITCHIMAGECONVERTER_H
|
||||
|
||||
#include "stitchImageVisualizer.h"
|
||||
|
||||
class StitchImage;
|
||||
|
||||
class StitchImageConverter : public StitchImageVisualizer {
|
||||
public:
|
||||
StitchImageConverter();
|
||||
|
||||
virtual void add_output_image(StitchImage *image);
|
||||
|
||||
protected:
|
||||
virtual void override_chan_cfg(ChanCfgOverrides &override);
|
||||
virtual void setup_camera(const RenderRelation &camera_arc);
|
||||
virtual bool is_interactive() const;
|
||||
virtual void create_image_geometry(Image &im);
|
||||
|
||||
StitchImage *_output_image;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,396 +0,0 @@
|
|||
// Filename: stitchImageVisualizer.cxx
|
||||
// Created by: drose (05Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stitchImageVisualizer.h"
|
||||
#include "config_stitch.h"
|
||||
#include "triangleMesh.h"
|
||||
#include "stitchLens.h"
|
||||
|
||||
#include "luse.h"
|
||||
#include "chancfg.h"
|
||||
#include "transform2sg.h"
|
||||
#include "geomTristrip.h"
|
||||
#include "geomNode.h"
|
||||
#include "interactiveGraphicsPipe.h"
|
||||
#include "noninteractiveGraphicsPipe.h"
|
||||
#include "buttonThrower.h"
|
||||
#include "dataGraphTraversal.h"
|
||||
#include "eventQueue.h"
|
||||
#include "texture.h"
|
||||
#include "textureTransition.h"
|
||||
#include "renderModeTransition.h"
|
||||
#include "cullFaceTransition.h"
|
||||
#include "clockObject.h"
|
||||
#include "config_gobj.h"
|
||||
#include "renderRelation.h"
|
||||
#include "dataRelation.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
StitchImageVisualizer *StitchImageVisualizer::_static_siv;
|
||||
|
||||
// Returns the largest power of 2 less than or equal to value.
|
||||
static int
|
||||
to_power_2(int value) {
|
||||
int x = 1;
|
||||
while ((x << 1) <= value) {
|
||||
x = (x << 1);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
StitchImageVisualizer::Image::
|
||||
Image(StitchImage *image, int index, bool scale) :
|
||||
_image(image),
|
||||
_index(index)
|
||||
{
|
||||
_arc = NULL;
|
||||
_viz = true;
|
||||
|
||||
if (!image->read_file()) {
|
||||
nout << "Unable to read image.\n";
|
||||
}
|
||||
|
||||
if (scale && image->_data != NULL) {
|
||||
// We have to make it a power of 2.
|
||||
int old_xsize = image->_data->get_x_size();
|
||||
int old_ysize = image->_data->get_y_size();
|
||||
int new_xsize = old_xsize;
|
||||
int new_ysize = old_ysize;
|
||||
if (max_texture_dimension > 0) {
|
||||
new_xsize = min(new_xsize, max_texture_dimension);
|
||||
new_ysize = min(new_ysize, max_texture_dimension);
|
||||
}
|
||||
new_xsize = to_power_2(new_xsize);
|
||||
new_ysize = to_power_2(new_ysize);
|
||||
|
||||
if (new_xsize != old_xsize || new_ysize != old_ysize) {
|
||||
nout << "Scaling " << image->get_name() << " from "
|
||||
<< old_xsize << " " << old_ysize << " to "
|
||||
<< new_xsize << " " << new_ysize << "\n";
|
||||
|
||||
PNMImage *n = new PNMImage(new_xsize, new_ysize);
|
||||
n->quick_filter_from(*image->_data);
|
||||
delete image->_data;
|
||||
image->_data = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StitchImageVisualizer::Image::
|
||||
Image(const Image ©) :
|
||||
_image(copy._image),
|
||||
_arc(copy._arc),
|
||||
_tex(copy._tex),
|
||||
_viz(copy._viz),
|
||||
_index(copy._index)
|
||||
{
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::Image::
|
||||
operator = (const Image ©) {
|
||||
_image = copy._image;
|
||||
_arc = copy._arc;
|
||||
_tex = copy._tex;
|
||||
_viz = copy._viz;
|
||||
_index = copy._index;
|
||||
}
|
||||
|
||||
StitchImageVisualizer::
|
||||
StitchImageVisualizer() :
|
||||
_eyepoint_inv(LMatrix4f::ident_mat()),
|
||||
_event_handler(EventQueue::get_global_event_queue())
|
||||
{
|
||||
_event_handler.add_hook("q", static_handle_event);
|
||||
_event_handler.add_hook("z", static_handle_event);
|
||||
}
|
||||
|
||||
|
||||
void StitchImageVisualizer::
|
||||
add_input_image(StitchImage *image) {
|
||||
int index = _images.size();
|
||||
char letter = index + 'a';
|
||||
_images.push_back(Image(image, index, true));
|
||||
|
||||
string event_name(1, letter);
|
||||
_event_handler.add_hook(event_name, static_handle_event);
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
add_output_image(StitchImage *) {
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
add_stitcher(Stitcher *) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: StitchImageVisualizer::set_eyepoint
|
||||
// Access: Public, Virtual
|
||||
// Description: Sets the eye point to the indicated coordinate frame,
|
||||
// if it makes sense to this kind of outputter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void StitchImageVisualizer::
|
||||
set_eyepoint(const LMatrix4d &mat) {
|
||||
_eyepoint_inv.invert_from(LCAST(float, mat));
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
execute() {
|
||||
setup();
|
||||
|
||||
if (is_interactive()) {
|
||||
_main_win->set_draw_callback(this);
|
||||
_main_win->set_idle_callback(this);
|
||||
_running = true;
|
||||
while (_running) {
|
||||
_main_win->update();
|
||||
}
|
||||
} else {
|
||||
nout << "Drawing frame\n";
|
||||
draw(true);
|
||||
nout << "Done drawing frame\n";
|
||||
}
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
setup() {
|
||||
ChanCfgOverrides override;
|
||||
|
||||
override_chan_cfg(override);
|
||||
|
||||
// load display modules
|
||||
GraphicsPipe::resolve_modules();
|
||||
|
||||
// Create a window
|
||||
TypeHandle want_pipe_type = InteractiveGraphicsPipe::get_class_type();
|
||||
if (!is_interactive()) {
|
||||
want_pipe_type = NoninteractiveGraphicsPipe::get_class_type();
|
||||
}
|
||||
|
||||
_main_pipe = GraphicsPipe::get_factory().make_instance(want_pipe_type);
|
||||
|
||||
if (_main_pipe == (GraphicsPipe*)0L) {
|
||||
nout << "No suitable pipe is available! Check your Configrc!\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
nout << "Opened a '" << _main_pipe->get_type().get_name()
|
||||
<< "' graphics pipe." << endl;
|
||||
|
||||
// Create the render node
|
||||
_render_top = new NamedNode("render_top");
|
||||
_render = new NamedNode("render");
|
||||
_render_arc = new RenderRelation(_render_top, _render);
|
||||
|
||||
ChanConfig chanConfig(_main_pipe, chan_cfg, _render, override);
|
||||
_main_win = chanConfig.get_win();
|
||||
assert(_main_win != (GraphicsWindow*)0L);
|
||||
PT_NamedNode cameras = chanConfig.get_group_node(0);
|
||||
cameras->set_name("cameras");
|
||||
for(int group_node_index = 1;
|
||||
group_node_index < chanConfig.get_num_groups();
|
||||
group_node_index++) {
|
||||
DisplayRegion *dr = chanConfig.get_dr(group_node_index);
|
||||
dr->get_camera()->get_lens()->set_near_far(1.0, 10000.0);
|
||||
new RenderRelation(_render, chanConfig.get_group_node(group_node_index));
|
||||
|
||||
}
|
||||
NodeRelation *cam_trans = new RenderRelation(_render, cameras);
|
||||
|
||||
// Turn on backface culling.
|
||||
CullFaceTransition *cfa = new CullFaceTransition(CullFaceProperty::M_cull_clockwise);
|
||||
_render_arc->set_transition(cfa);
|
||||
|
||||
// Create the data graph root.
|
||||
_data_root = new NamedNode( "data" );
|
||||
|
||||
// Create a mouse and put it in the data graph.
|
||||
_mak = new MouseAndKeyboard(_main_win, 0);
|
||||
new DataRelation(_data_root, _mak);
|
||||
|
||||
// Create a trackball to handle the mouse input.
|
||||
_trackball = new Trackball("trackball");
|
||||
_trackball->set_mat(_eyepoint_inv);
|
||||
|
||||
new DataRelation(_mak, _trackball);
|
||||
|
||||
// Connect the trackball output to the camera's transform.
|
||||
PT(Transform2SG) tball2cam = new Transform2SG("tball2cam");
|
||||
tball2cam->set_arc(cam_trans);
|
||||
new DataRelation(_trackball, tball2cam);
|
||||
|
||||
// Create an ButtonThrower to throw events from the keyboard.
|
||||
PT(ButtonThrower) et = new ButtonThrower("kb-events");
|
||||
new DataRelation(_mak, et);
|
||||
|
||||
// Create all the images.
|
||||
Images::iterator ii;
|
||||
for (ii = _images.begin(); ii != _images.end(); ++ii) {
|
||||
create_image_geometry(*ii);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StitchImageVisualizer::
|
||||
override_chan_cfg(ChanCfgOverrides &override) {
|
||||
override.setField(ChanCfgOverrides::Mask,
|
||||
((unsigned int)(W_DOUBLE|W_DEPTH|W_MULTISAMPLE)));
|
||||
override.setField(ChanCfgOverrides::Title, "Stitch");
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
setup_camera(const RenderRelation &) {
|
||||
}
|
||||
|
||||
bool StitchImageVisualizer::
|
||||
is_interactive() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
toggle_viz(StitchImageVisualizer::Image &im) {
|
||||
im._viz = !im._viz;
|
||||
if (im._viz) {
|
||||
im._arc->set_transition(new RenderModeTransition(RenderModeProperty::M_filled));
|
||||
im._arc->set_transition(new CullFaceTransition(CullFaceProperty::M_cull_clockwise));
|
||||
if (im._tex != (Texture *)NULL) {
|
||||
im._arc->set_transition(new TextureTransition(im._tex));
|
||||
}
|
||||
} else {
|
||||
im._arc->set_transition(new RenderModeTransition(RenderModeProperty::M_wireframe));
|
||||
im._arc->set_transition(new CullFaceTransition(CullFaceProperty::M_cull_none));
|
||||
im._arc->set_transition(new TextureTransition);
|
||||
}
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
create_image_geometry(StitchImageVisualizer::Image &im) {
|
||||
int x_verts = im._image->get_x_verts();
|
||||
int y_verts = im._image->get_y_verts();
|
||||
/*
|
||||
int x_verts = 2;
|
||||
int y_verts = 2;
|
||||
*/
|
||||
TriangleMesh mesh(x_verts, y_verts);
|
||||
|
||||
StitchLens *lens = im._image->_lens;
|
||||
|
||||
if (_screen->is_empty()) {
|
||||
// If we have no screens, draw the image geometry by extruding an
|
||||
// arbitrary distance from each camera's origin.
|
||||
LVector3d center =
|
||||
lens->extrude(LPoint2d(0.0, 0.0), im._image->_size_mm[0]);
|
||||
double scale = 10.0 / length(center);
|
||||
|
||||
for (int xi = 0; xi < x_verts; xi++) {
|
||||
for (int yi = 0; yi < y_verts; yi++) {
|
||||
LPoint2d uv = LPoint2d((double)xi / (double)(x_verts - 1),
|
||||
1.0 - (double)yi / (double)(y_verts - 1));
|
||||
LVector3d p = im._image->extrude(uv);
|
||||
|
||||
mesh._coords.push_back(LCAST(float, p) * scale);
|
||||
mesh._texcoords.push_back(LCAST(float, uv));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Otherwise, if we do have screens, draw the image geometry by
|
||||
// projecting its vertices on to the screen(s).
|
||||
|
||||
for (int xi = 0; xi < x_verts; xi++) {
|
||||
for (int yi = 0; yi < y_verts; yi++) {
|
||||
LPoint2d uv = LPoint2d((double)xi / (double)(x_verts - 1),
|
||||
1.0 - (double)yi / (double)(y_verts - 1));
|
||||
LVector3d space = im._image->extrude(uv);
|
||||
LPoint3d p;
|
||||
if (_screen->intersect(p, im._image->get_pos(), space)) {
|
||||
mesh._coords.push_back(LCAST(float, p));
|
||||
} else {
|
||||
// No intersection.
|
||||
mesh._coords.push_back(Vertexf(0.0, 0.0, 0.0));
|
||||
}
|
||||
mesh._texcoords.push_back(LCAST(float, uv));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PT(GeomTristrip) geom = mesh.build_mesh();
|
||||
|
||||
PT(GeomNode) node = new GeomNode;
|
||||
node->add_geom(geom.p());
|
||||
|
||||
im._arc = new RenderRelation(_render, node);
|
||||
|
||||
if (im._image->_data != NULL) {
|
||||
im._tex = new Texture;
|
||||
im._tex->set_name(im._image->get_filename());
|
||||
im._tex->load(*im._image->_data);
|
||||
im._arc->set_transition(new TextureTransition(im._tex));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void StitchImageVisualizer::
|
||||
draw(bool) {
|
||||
int num_windows = _main_pipe->get_num_windows();
|
||||
for (int w = 0; w < num_windows; w++) {
|
||||
GraphicsWindow *win = _main_pipe->get_window(w);
|
||||
win->get_gsg()->render_frame();
|
||||
}
|
||||
ClockObject::get_global_clock()->tick();
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
idle() {
|
||||
// Initiate the data traversal, to send device data down its
|
||||
// respective pipelines.
|
||||
traverse_data_graph(_data_root);
|
||||
|
||||
// Throw any events generated recently.
|
||||
_static_siv = this;
|
||||
_event_handler.process_events();
|
||||
}
|
||||
|
||||
void StitchImageVisualizer::
|
||||
static_handle_event(CPT(Event) event) {
|
||||
_static_siv->handle_event(event);
|
||||
}
|
||||
|
||||
|
||||
void StitchImageVisualizer::
|
||||
handle_event(CPT(Event) event) {
|
||||
string name = event->get_name();
|
||||
|
||||
if (name.size() == 1 && isalpha(name[0])) {
|
||||
int index = tolower(name[0]) - 'a';
|
||||
if (index >= 0 && index < (int)_images.size()) {
|
||||
toggle_viz(_images[index]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (name == "q") {
|
||||
_running = false;
|
||||
|
||||
} else if (name == "z") {
|
||||
_trackball->reset();
|
||||
_trackball->set_mat(_eyepoint_inv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
// Filename: stitchImageVisualizer.h
|
||||
// Created by: drose (05Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef STITCHIMAGEVISUALIZER_H
|
||||
#define STITCHIMAGEVISUALIZER_H
|
||||
|
||||
#include "stitchImage.h"
|
||||
#include "stitchImageOutputter.h"
|
||||
|
||||
#include "pointerTo.h"
|
||||
#include <graphicsPipe.h>
|
||||
#include <graphicsWindow.h>
|
||||
#include <namedNode.h>
|
||||
#include <renderRelation.h>
|
||||
#include <mouse.h>
|
||||
#include <trackball.h>
|
||||
#include <nodeTransition.h>
|
||||
#include <eventHandler.h>
|
||||
#include <texture.h>
|
||||
|
||||
class PNMImage;
|
||||
class ChanCfgOverrides;
|
||||
|
||||
class StitchImageVisualizer : public StitchImageOutputter,
|
||||
public GraphicsWindow::Callback {
|
||||
public:
|
||||
StitchImageVisualizer();
|
||||
virtual void add_input_image(StitchImage *image);
|
||||
virtual void add_output_image(StitchImage *image);
|
||||
virtual void add_stitcher(Stitcher *stitcher);
|
||||
|
||||
virtual void set_eyepoint(const LMatrix4d &mat);
|
||||
|
||||
virtual void execute();
|
||||
|
||||
protected:
|
||||
void setup();
|
||||
|
||||
class Image {
|
||||
public:
|
||||
Image(StitchImage *image, int index, bool scale);
|
||||
Image(const Image ©);
|
||||
void operator = (const Image ©);
|
||||
|
||||
StitchImage *_image;
|
||||
RenderRelation *_arc;
|
||||
PT(Texture) _tex;
|
||||
bool _viz;
|
||||
int _index;
|
||||
};
|
||||
|
||||
virtual void override_chan_cfg(ChanCfgOverrides &override);
|
||||
virtual void setup_camera(const RenderRelation &camera_arc);
|
||||
virtual bool is_interactive() const;
|
||||
|
||||
void toggle_viz(Image &im);
|
||||
virtual void create_image_geometry(Image &im);
|
||||
|
||||
static void static_handle_event(CPT(Event) event);
|
||||
void handle_event(CPT(Event) event);
|
||||
|
||||
virtual void draw(bool);
|
||||
virtual void idle();
|
||||
|
||||
typedef vector<Image> Images;
|
||||
Images _images;
|
||||
|
||||
LMatrix4f _eyepoint_inv;
|
||||
|
||||
PT(GraphicsPipe) _main_pipe;
|
||||
PT(GraphicsWindow) _main_win;
|
||||
PT(NamedNode) _render_top;
|
||||
PT(NamedNode) _render;
|
||||
NodeRelation *_render_arc;
|
||||
PT(NamedNode) _data_root;
|
||||
PT(MouseAndKeyboard) _mak;
|
||||
PT(Trackball) _trackball;
|
||||
EventHandler _event_handler;
|
||||
|
||||
static StitchImageVisualizer *_static_siv;
|
||||
bool _running;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
// Filename: triangleMesh.cxx
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d-general@lists.sourceforge.net .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "triangleMesh.h"
|
||||
|
||||
#include "geomTristrip.h"
|
||||
|
||||
TriangleMesh::
|
||||
TriangleMesh(int x_verts, int y_verts) :
|
||||
_coords(PTA_Vertexf::empty_array(0)),
|
||||
_norms(PTA_Normalf::empty_array(0)),
|
||||
_colors(PTA_Colorf::empty_array(0)),
|
||||
_texcoords(PTA_TexCoordf::empty_array(0)),
|
||||
_x_verts(x_verts),
|
||||
_y_verts(y_verts)
|
||||
{
|
||||
}
|
||||
|
||||
int TriangleMesh::
|
||||
get_x_verts() const {
|
||||
return _x_verts;
|
||||
}
|
||||
|
||||
int TriangleMesh::
|
||||
get_y_verts() const {
|
||||
return _y_verts;
|
||||
}
|
||||
|
||||
int TriangleMesh::
|
||||
get_num_verts() const {
|
||||
return _x_verts * _y_verts;
|
||||
}
|
||||
|
||||
GeomTristrip *TriangleMesh::
|
||||
build_mesh() const {
|
||||
// int num_verts = _x_verts * _y_verts;
|
||||
int num_tstrips = (_y_verts-1);
|
||||
int tstrip_length = 2*(_x_verts-1)+2;
|
||||
|
||||
PTA_int lengths = PTA_int::empty_array(num_tstrips);
|
||||
PTA_ushort vindex = PTA_ushort::empty_array(num_tstrips * tstrip_length);
|
||||
|
||||
// Set the lengths array. We are creating num_tstrips T-strips,
|
||||
// each of which has t_strip length vertices.
|
||||
int n;
|
||||
for (n = 0; n < num_tstrips; n++) {
|
||||
lengths[n] = tstrip_length;
|
||||
}
|
||||
|
||||
// Now fill up the index array into the vertices. This lays out the
|
||||
// order of the vertices in each T-strip.
|
||||
n = 0;
|
||||
int ti, si;
|
||||
for (ti = 1; ti < _y_verts; ti++) {
|
||||
vindex[n++] = ti * _x_verts;
|
||||
for (si = 1; si < _x_verts; si++) {
|
||||
vindex[n++] = (ti - 1) * _x_verts + (si-1);
|
||||
vindex[n++] = ti * _x_verts + si;
|
||||
}
|
||||
vindex[n++] = (ti - 1) * _x_verts + (_x_verts-1);
|
||||
}
|
||||
assert(n==num_tstrips * tstrip_length);
|
||||
|
||||
GeomTristrip *geom = new GeomTristrip;
|
||||
geom->set_num_prims(num_tstrips);
|
||||
geom->set_lengths(lengths);
|
||||
|
||||
assert(!_coords.empty());
|
||||
geom->set_coords(_coords, G_PER_VERTEX, vindex);
|
||||
|
||||
if (!_norms.empty()) {
|
||||
geom->set_normals(_norms, G_PER_VERTEX, vindex);
|
||||
}
|
||||
|
||||
if (!_colors.empty()) {
|
||||
geom->set_colors(_colors, G_PER_VERTEX, vindex);
|
||||
}
|
||||
|
||||
if (!_texcoords.empty()) {
|
||||
geom->set_texcoords(_texcoords, G_PER_VERTEX, vindex);
|
||||
}
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Filename: triangleMesh.h
|
||||
// Created by: drose (06Nov99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIANGLEMESH_H
|
||||
#define TRIANGLEMESH_H
|
||||
|
||||
#include "luse.h"
|
||||
#include <pta_Vertexf.h>
|
||||
#include <pta_Normalf.h>
|
||||
#include <pta_Colorf.h>
|
||||
#include <pta_TexCoordf.h>
|
||||
|
||||
class GeomTristrip;
|
||||
|
||||
class TriangleMesh {
|
||||
public:
|
||||
TriangleMesh(int x_verts, int y_verts);
|
||||
|
||||
int get_x_verts() const;
|
||||
int get_y_verts() const;
|
||||
int get_num_verts() const;
|
||||
|
||||
GeomTristrip *build_mesh() const;
|
||||
|
||||
PTA_Vertexf _coords;
|
||||
PTA_Normalf _norms;
|
||||
PTA_Colorf _colors;
|
||||
PTA_TexCoordf _texcoords;
|
||||
|
||||
private:
|
||||
int _x_verts, _y_verts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Loading…
Reference in New Issue