added pos to images

This commit is contained in:
David Rose 2001-07-17 19:28:47 +00:00
parent 37843d61a9
commit 0fc8c767da
33 changed files with 1362 additions and 164 deletions

View File

@ -35,9 +35,18 @@ StitchImageProgram() {
"algorithm (no graphics hardware is used).");
add_option
("f", "", 0,
"Apply a very simple filter in an attempt to smooth the results.",
&StitchImageProgram::dispatch_none, &_filter_output);
("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);
_filter_factor = 1.0;
}
////////////////////////////////////////////////////////////////////
@ -48,7 +57,7 @@ StitchImageProgram() {
void StitchImageProgram::
run() {
StitchImageRasterizer outputter;
outputter._filter_output = _filter_output;
outputter._filter_factor = _filter_factor;
_command_file.process(outputter);
}

View File

@ -36,7 +36,7 @@ public:
void run();
private:
bool _filter_output;
double _filter_factor;
};
#endif

View File

@ -3,7 +3,7 @@
#begin ss_lib_target
#define TARGET stitchbase
#define LOCAL_LIBS
#define LOCAL_LIBS pandaappbase
#define OTHER_LIBS \
progbase \
putil:c express:c mathutil:c linmath:c pnmimage:c pnm:c panda:m
@ -24,7 +24,11 @@
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
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 fixedPoint.h layeredImage.h morphGrid.h stitchCommand.h \
@ -33,6 +37,11 @@
stitchImageOutputter.h stitchImageRasterizer.h stitchLens.h \
stitchLexerDefs.h stitchPSphereLens.h stitchParser.h \
stitchParserDefs.h stitchPerspectiveLens.h stitchPoint.h \
stitcher.h triangle.h triangleRasterizer.h
stitcher.h triangle.h triangleRasterizer.h \
stitchCylindricalScreen.h \
stitchFlatScreen.h \
stitchMultiScreen.h \
stitchScreen.h
#end ss_lib_target

View File

@ -17,12 +17,14 @@
////////////////////////////////////////////////////////////////////
#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

@ -19,7 +19,7 @@
#ifndef CONFIG_STITCH_H
#define CONFIG_STITCH_H
#include <pandatoolbase.h>
#include "pandaappbase.h"
extern string chan_cfg;

View File

@ -19,7 +19,7 @@
#ifndef LAYEREDIMAGE_H
#define LAYEREDIMAGE_H
#include <pandatoolbase.h>
#include "pandaappbase.h"
#include <luse.h>
#include <filename.h>

View File

@ -24,6 +24,8 @@
#include "stitchCylindricalLens.h"
#include "stitchPSphereLens.h"
#include "stitchImageOutputter.h"
#include "stitchCylindricalScreen.h"
#include "stitchFlatScreen.h"
#include "stitcher.h"
#include <indent.h>
@ -121,6 +123,22 @@ operator << (ostream &out, StitchCommand::Command c) {
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;
@ -129,6 +147,10 @@ operator << (ostream &out, StitchCommand::Command c) {
return out << "stitch";
break;
case StitchCommand::C_screen:
return out << "screen";
break;
case StitchCommand::C_using:
return out << "using";
break;
@ -289,6 +311,36 @@ 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) {
@ -322,6 +374,10 @@ process(StitchImageOutputter &outputter, Stitcher *stitcher,
}
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());
@ -636,6 +692,10 @@ create_image() {
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;
@ -652,3 +712,54 @@ create_image() {
return image;
}
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

@ -19,15 +19,16 @@
#ifndef STITCHCOMMAND_H
#define STITCHCOMMAND_H
#include <pandatoolbase.h>
#include "pandaappbase.h"
#include "stitchScreen.h"
#include <luse.h>
#include <vector>
#include <map>
#include "luse.h"
#include "pointerTo.h"
#include "pvector.h"
class StitchLens;
class StitchImage;
class StitchScreen;
class StitchImageOutputter;
class StitchFile;
class Stitcher;
@ -58,8 +59,13 @@ public:
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,
};
@ -90,6 +96,13 @@ public:
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,
@ -110,6 +123,7 @@ private:
LVecBase2d find_parameter(Command command, const LVecBase2d &dflt);
StitchImage *create_image();
PT(StitchScreen) create_screen();
StitchCommand *_parent;
@ -139,7 +153,7 @@ private:
// This will only get filled in by make_lens().
StitchLens *_lens;
typedef vector<StitchCommand *> Commands;
typedef pvector<StitchCommand *> Commands;
Commands _using;
Commands _nested;
};

View File

@ -19,7 +19,7 @@
#ifndef STITCHCOMMANDREADER_H
#define STITCHCOMMANDREADER_H
#include <pandatoolbase.h>
#include "pandaappbase.h"
#include "stitchFile.h"

View File

@ -0,0 +1,182 @@
// Filename: stitchCylindricalScreen.cxx
// 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 .
//
////////////////////////////////////////////////////////////////////
#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

@ -0,0 +1,63 @@
// 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

@ -0,0 +1,69 @@
// Filename: stitchFlatScreen.cxx
// 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 .
//
////////////////////////////////////////////////////////////////////
#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

@ -0,0 +1,46 @@
// 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

@ -20,8 +20,8 @@
#include "stitchLens.h"
#include "layeredImage.h"
#include <compose_matrix.h>
#include <rotate_to.h>
#include "compose_matrix.h"
#include "rotate_to.h"
StitchImage::
StitchImage(const string &name, const string &filename,
@ -32,13 +32,15 @@ StitchImage(const string &name, const string &filename,
_size_pixels(size_pixels),
_pixels_per_mm(pixels_per_mm),
_film_offset_mm(film_offset_mm),
_rotate(LMatrix3d::ident_mat()),
_inv_rotate(LMatrix3d::ident_mat()),
_transform(LMatrix4d::ident_mat()),
_inv_transform(LMatrix4d::ident_mat()),
_filename(filename),
_name(name)
{
_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.
@ -55,16 +57,6 @@ StitchImage(const string &name, const string &filename,
// film_offset_mm-size_mm at the lower-left, to
// film_offset_mm+size_mm at the upper-right.
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]));
/*
nout << "_pixels_to_uv * _uv_to_pixels is\n"
<< _pixels_to_uv * _uv_to_pixels << "\n"
@ -88,8 +80,7 @@ StitchImage(const string &name, const string &filename,
LMatrix3d::scale_mat(1.0 / mm_per_uv[0], 1.0 / mm_per_uv[1]) *
LMatrix3d::translate_mat(LVector2d(0.5, 0.5) + _film_offset_mm);
_pixels_to_mm = _pixels_to_uv * _uv_to_mm;
_mm_to_pixels = _mm_to_uv * _uv_to_pixels;
setup_pixel_scales();
_show_points = false;
setup_grid(2, 2);
@ -98,6 +89,9 @@ StitchImage(const string &name, const string &filename,
_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;
@ -194,6 +188,7 @@ close_layer(bool nonempty) {
_layer_index++;
sprintf(buff, _filename.c_str(), _layer_index);
nout << "Writing layer " << _layer_name << " as " << buff << "\n";
resize_data();
result = _data->write(buff);
}
}
@ -204,6 +199,7 @@ close_layer(bool nonempty) {
result = false;
} else {
if (nonempty) {
resize_data();
_layered_image->add_layer(_layer_name, LVector2d(0.0, 0.0),
_data);
_data = NULL;
@ -232,6 +228,7 @@ close_output_file() {
result = false;
} else {
nout << "Writing " << _filename << "\n";
resize_data();
result = _data->write(_filename);
}
}
@ -242,25 +239,51 @@ close_output_file() {
void StitchImage::
clear_transform() {
_rotate = LMatrix3d::ident_mat();
_inv_rotate = LMatrix3d::ident_mat();
_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 LMatrix3d &rot) {
_rotate = rot;
_inv_rotate = invert(rot);
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(_rotate, LVecBase3d(1.0, 1.0, 1.0), hpr);
_inv_rotate = invert(_rotate);
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;
@ -314,12 +337,12 @@ get_size_mm() const {
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]) * _rotate;
return _lens->extrude(p * _uv_to_mm, _size_mm[0]) * _transform;
}
LPoint2d StitchImage::
project(const LVector3d &vec) const {
LPoint2d m = _lens->project(vec * _inv_rotate, _size_mm[0]);
LPoint2d m = _lens->project(vec * _inv_transform, _size_mm[0]);
return _morph.morph_in(m * _mm_to_uv);
}
@ -342,7 +365,7 @@ draw_triangle(TriangleRasterizer &rast, const RasterizerVertex *v0,
void StitchImage::
pick_up_singularity(TriangleRasterizer &rast, StitchImage *input) {
_lens->pick_up_singularity(rast, _mm_to_pixels, _pixels_to_mm,
_rotate, _size_mm[0], input);
_transform.get_upper_3(), _size_mm[0], input);
}
void StitchImage::
@ -350,6 +373,26 @@ 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 {
@ -357,12 +400,65 @@ output(ostream &out) const {
<< get_size_pixels() << " pixels, or " << get_size_mm()
<< " mm\n";
LVecBase3d scale, hpr;
if (decompose_matrix(_rotate, scale, hpr)) {
out << "rotate " << hpr << "\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 rotation transform:\n";
_rotate.write(out);
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,
// int preparation to writing it out.
////////////////////////////////////////////////////////////////////
void StitchImage::
resize_data() {
assert(_data != (PNMImage *)NULL);
if (_orig_size_pixels == _size_pixels) {
return;
}
PNMImage *small =
new PNMImage(_orig_size_pixels[0], _orig_size_pixels[1],
_data->get_color_type());
cerr << "Filtering to " << small->get_x_size() << " by "
<< small->get_y_size() << "\n";
small->box_filter_from(1.0, *_data);
delete _data;
_data = small;
}

View File

@ -19,7 +19,7 @@
#ifndef STITCHIMAGE_H
#define STITCHIMAGE_H
#include <pandatoolbase.h>
#include "pandaappbase.h"
#include "stitchPoint.h"
#include "morphGrid.h"
@ -67,8 +67,11 @@ public:
bool close_output_file();
void clear_transform();
void set_transform(const LMatrix3d &rot);
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);
@ -106,6 +109,7 @@ public:
StitchImage *input);
void add_point(const string &name, const LPoint2d &pixel);
void set_output_scale_factor(double factor);
void output(ostream &out) const;
@ -119,6 +123,8 @@ public:
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.
@ -134,7 +140,7 @@ public:
typedef map<string, LPoint2d> Points;
Points _points;
LMatrix3d _rotate, _inv_rotate;
LMatrix4d _transform, _inv_transform;
MorphGrid _morph;
// This index number is filled in by the Stitcher. It allows us to
@ -142,6 +148,10 @@ public:
// file.
int _index;
private:
void setup_pixel_scales();
void resize_data();
private:
Filename _filename;
string _name;
@ -150,6 +160,8 @@ private:
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) {

View File

@ -96,9 +96,11 @@ fill_image_cmd(StitchCommand *image_cmd, StitchImage *image) {
image->_lens->make_lens_command(image_cmd);
LVecBase3d scale, hpr;
if (decompose_matrix(image->_rotate, scale, hpr)) {
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

@ -19,10 +19,34 @@
#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);
}

View File

@ -19,11 +19,30 @@
#ifndef STITCHIMAGEOUTPUTTER_H
#define STITCHIMAGEOUTPUTTER_H
#include "pandaappbase.h"
#include "stitchMultiScreen.h"
#include "luse.h"
#include "pointerTo.h"
class StitchImage;
class Stitcher;
#include <luse.h>
////////////////////////////////////////////////////////////////////
// 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();
@ -32,8 +51,12 @@ public:
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 execute()=0;
protected:
PT(StitchMultiScreen) _screen;
};
#endif

View File

@ -25,7 +25,7 @@
StitchImageRasterizer::
StitchImageRasterizer() {
_filter_output = true;
_filter_factor = 1.0;
}
@ -36,6 +36,7 @@ add_input_image(StitchImage *image) {
void StitchImageRasterizer::
add_output_image(StitchImage *image) {
image->set_output_scale_factor(_filter_factor);
_output_images.push_back(image);
}
@ -119,7 +120,7 @@ draw_image(StitchImage *output, StitchImage *input) {
TriangleRasterizer rast;
rast._output = output->_data;
rast._input = input;
rast._filter_output = _filter_output;
rast._filter_output = false;
rast._untextured_color = input->_untextured_color;
int x_verts = input->get_x_verts();
@ -128,37 +129,54 @@ draw_image(StitchImage *output, StitchImage *input) {
// Build up the table of verts.
typedef vector<RasterizerVertex> VRow;
typedef vector<VRow> VTable;
VTable _table(x_verts, VRow());
VTable table(x_verts, VRow());
int xi, yi;
for (xi = 0; xi < x_verts; xi++) {
_table[xi] = VRow(y_verts, RasterizerVertex());
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);
LPoint2d to = output->project(space);
LPoint2d from = input->get_grid_uv(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 = to * output->_uv_to_pixels;
_table[xi][yi]._uv = from;
_table[xi][yi]._space = space * output->_inv_rotate;
_table[xi][yi]._alpha = alpha;
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);
_table[xi][yi]._space = normalize(_table[xi][yi]._space);
// Tag any triangle including this vertex as totally invalid.
table[xi][yi]._visibility = -1;
// 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));
} 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));
}
}
}
@ -168,13 +186,13 @@ draw_image(StitchImage *output, StitchImage *input) {
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]);
&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]);
&table[xi][yi],
&table[xi + 1][yi + 1],
&table[xi + 1][yi]);
}
}
output->pick_up_singularity(rast, input);

View File

@ -36,7 +36,7 @@ public:
virtual void execute();
bool _filter_output;
double _filter_factor;
protected:
void draw_points(StitchImage *output, StitchImage *input,

View File

@ -284,6 +284,22 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
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();
@ -339,10 +355,20 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
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) {
@ -353,6 +379,8 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
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;
}

View File

@ -19,7 +19,7 @@
#ifndef STITCHLEXERDEFS_H
#define STITCHLEXERDEFS_H
#include <pandatoolbase.h>
#include "pandaappbase.h"
void stitch_init_lexer(istream &in, const string &filename);
int stitch_error_count();

View File

@ -0,0 +1,127 @@
// Filename: stitchMultiScreen.cxx
// 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 .
//
////////////////////////////////////////////////////////////////////
#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

@ -0,0 +1,59 @@
// 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,53 +1,43 @@
// Filename: stitchParser.h
// Created by:
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////
#define NUMBER 257
#define IDENTIFIER 258
#define STRING 259
#define KW_DEFINE 260
#define KW_LENS 261
#define KW_INPUT_IMAGE 262
#define KW_OUTPUT_IMAGE 263
#define KW_PERSPECTIVE 264
#define KW_FISHEYE 265
#define KW_CYLINDRICAL 266
#define KW_PSPHERE 267
#define KW_FOCAL_LENGTH 268
#define KW_FOV 269
#define KW_SINGULARITY_TOLERANCE 270
#define KW_RESOLUTION 271
#define KW_FILENAME 272
#define KW_POINT 273
#define KW_SHOW_POINTS 274
#define KW_IMAGE_SIZE 275
#define KW_FILM_SIZE 276
#define KW_FILM_OFFSET 277
#define KW_GRID 278
#define KW_UNTEXTURED_COLOR 279
#define KW_HPR 280
#define KW_LAYERS 281
#define KW_STITCH 282
#define KW_POINTS 283
#define KW_USING 284
#define KW_IN 285
#define KW_MM 286
#define KW_CM 287
#define KW_P 288
#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_PERSPECTIVE 266
#define KW_FISHEYE 267
#define KW_CYLINDRICAL 268
#define KW_PSPHERE 269
#define KW_FOCAL_LENGTH 270
#define KW_FOV 271
#define KW_SINGULARITY_TOLERANCE 272
#define KW_RESOLUTION 273
#define KW_FILENAME 274
#define KW_POINT 275
#define KW_SHOW_POINTS 276
#define KW_IMAGE_SIZE 277
#define KW_FILM_SIZE 278
#define KW_FILM_OFFSET 279
#define KW_GRID 280
#define KW_UNTEXTURED_COLOR 281
#define KW_HPR 282
#define KW_POS 283
#define KW_RADIUS 284
#define KW_ANGLE 285
#define KW_HEIGHT 286
#define KW_LAYERS 287
#define KW_STITCH 288
#define KW_SCREEN 289
#define KW_POINTS 290
#define KW_USING 291
#define KW_IN 292
#define KW_MM 293
#define KW_FT 294
#define KW_CM 295
#define KW_P 296
extern YYSTYPE stitchyylval;

View File

@ -29,7 +29,7 @@ stitch_init_parser(istream &in, const string &filename,
%}
%token <number> NUMBER
%token <number> NUMBER NUMBER_FEET NUMBER_INCHES
%token <str> IDENTIFIER
%token <str> STRING
@ -54,12 +54,18 @@ stitch_init_parser(istream &in, const string &filename,
%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
@ -74,6 +80,7 @@ stitch_init_parser(istream &in, const string &filename,
%type <vec> vec2
%type <vec> vec3
%type <vec> length_pair
%type <vec> length_triple
%type <vec> color
%type <str> name
%type <str> optional_name
@ -139,6 +146,11 @@ group_command:
{
$$ = new StitchCommand(parent, StitchCommand::C_stitch);
$$->set_name($2);
}
| KW_SCREEN optional_name
{
$$ = new StitchCommand(parent, StitchCommand::C_screen);
$$->set_name($2);
}
| KW_USING
{
@ -239,6 +251,26 @@ simple_command:
{
$$ = 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
{
@ -289,10 +321,31 @@ points_list:
length:
NUMBER length_units
{
$$ = $1 * $2; // convert to mm
$$ = $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
{
@ -305,6 +358,10 @@ length_units:
| KW_MM
{
$$ = 1.0;
}
| KW_FT
{
$$ = 304.8; // ft to mm
}
;
@ -372,18 +429,21 @@ vec3: '(' NUMBER NUMBER NUMBER ')'
;
length_pair:
'(' length length ')'
{
$$.set($2, $3, 0.0, 0.0);
$<num_components>$ = 2;
}
| '(' length ',' length ')'
'(' 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 ')'
{

View File

@ -19,7 +19,7 @@
#ifndef STITCHPARSERDEFS_H
#define STITCHPARSERDEFS_H
#include <pandatoolbase.h>
#include "pandaappbase.h"
#include <luse.h>

View File

@ -19,6 +19,8 @@
#ifndef STITCHPOINT_H
#define STITCHPOINT_H
#include "pandaappbase.h"
#include <luse.h>
#include <string>

View File

@ -0,0 +1,134 @@
// Filename: stitchScreen.cxx
// 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 .
//
////////////////////////////////////////////////////////////////////
#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

@ -0,0 +1,82 @@
// 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

@ -57,6 +57,11 @@ draw_triangle(const RasterizerVertex *v0,
// 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) {

View File

@ -186,12 +186,20 @@ setup() {
// Create the render node
_render = new NamedNode("render");
// make a node for the cameras to live under
_cameras = new NamedNode("cameras");
RenderRelation *cam_trans = new RenderRelation(_render, _cameras);
_main_win = ChanConfig(_main_pipe, chan_cfg, _cameras, _render, override);
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()->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.
CullFaceAttribute *cfa = new CullFaceAttribute;
@ -261,27 +269,51 @@ toggle_viz(StitchImageVisualizer::Image &im) {
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;
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));
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));
}
}
}

View File

@ -82,7 +82,6 @@ protected:
PT(GraphicsWindow) _main_win;
NodeAttributes _initial_state;
PT(NamedNode) _render;
PT(NamedNode) _cameras;
PT(NamedNode) _data_root;
PT(MouseAndKeyboard) _mak;
PT(Trackball) _trackball;