remove ancient program

This commit is contained in:
David Rose 2006-10-27 23:29:35 +00:00
parent 70db0829ff
commit e9c0e4b267
74 changed files with 0 additions and 13975 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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]);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}
}
}
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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.
}
}

View File

@ -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

View File

@ -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 &) {
}

View File

@ -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

View File

@ -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);
}
}
}
}
}
}

View File

@ -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

View File

@ -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 *) {
}

View File

@ -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

View File

@ -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 = &in;
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];
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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 */

View File

@ -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:
;

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -1,6 +0,0 @@
#include "config_stitch.cxx"
#include "fadeImagePool.cxx"
#include "layeredImage.cxx"
#include "morphGrid.cxx"
#include "triangle.cxx"
#include "triangleRasterizer.cxx"

View File

@ -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"

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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));
}
}

View File

@ -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

View File

@ -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 &copy) :
_image(copy._image),
_arc(copy._arc),
_tex(copy._tex),
_viz(copy._viz),
_index(copy._index)
{
}
void StitchImageVisualizer::Image::
operator = (const Image &copy) {
_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);
}
}

View File

@ -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 &copy);
void operator = (const Image &copy);
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

View File

@ -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;
}

View File

@ -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