Text archives Help
- From: abe@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r395 - in branches/itanium2: . Model/Cameras Model/Groups fox scenes
- Date: Sat, 18 Jun 2005 22:29:47 -0600 (MDT)
Author: abe
Date: Sat Jun 18 22:29:40 2005
New Revision: 395
Modified:
branches/itanium2/Model/Cameras/PinholeCamera.cc
branches/itanium2/Model/Groups/kdtree.cc
branches/itanium2/fox/FMantaImageFrame.cc
branches/itanium2/fox/FMantaUniformNav.cc
branches/itanium2/fox/FMantaUniformNav.h
branches/itanium2/fox/FMantaWindow.cc
branches/itanium2/fox/fox_manta.cc
branches/itanium2/manta-commands.txt
branches/itanium2/scenes/0.cc
Log:
Updates to fox_manta example. Still needs a lot of work
Modified: branches/itanium2/Model/Cameras/PinholeCamera.cc
==============================================================================
--- branches/itanium2/Model/Cameras/PinholeCamera.cc (original)
+++ branches/itanium2/Model/Cameras/PinholeCamera.cc Sat Jun 18 22:29:40
2005
@@ -149,7 +149,7 @@
{
Vector d = (lookat - eye) * scale;
eye += d;
- lookat += d;
+ lookat += d; // Maybe we need two types of dolly.
setup();
}
Modified: branches/itanium2/Model/Groups/kdtree.cc
==============================================================================
--- branches/itanium2/Model/Groups/kdtree.cc (original)
+++ branches/itanium2/Model/Groups/kdtree.cc Sat Jun 18 22:29:40 2005
@@ -41,7 +41,7 @@
///////////////////////////////////////////////////////////////////////////////
class V3C1Worker : public Runnable {
public:
- BBox bounds; // Thread specific bounding box.
+ BBox &bounds; // Thread specific bounding box.
// Target data.
float *rawData;
@@ -55,8 +55,9 @@
/////////////////////////////////////////////////////////////////////////////
// Constructor.
V3C1Worker( float *rawData_, VArray<Triangle> **tris_, Vectorf
**perVertNormals_,
- long begin_offset_, long end_offset_ ) :
- Runnable( false ), // Do not delete on exit (so we can pick
up the bounds).
+ long begin_offset_, long end_offset_, BBox &bounds_ ) :
+ Runnable( true ),
+ bounds( bounds_ ),
rawData( rawData_ ), tris( tris_ ), perVertNormals(
perVertNormals_ ),
begin_offset( begin_offset_ ), end_offset( end_offset_ ) { }
@@ -246,6 +247,11 @@
return 1;
}
+struct CacheAlignedBBox {
+ BBox box;
+ char padding[MAXCACHELINESIZE-sizeof(BBox)];
+};
+
int LoadBin_V3C1(const char *filename, VArray<Triangle> **tris, /*Vectorf
**perVertNormals,*/ Vectorf **perVertNormals, BBox &bounds, int np ) {
@@ -309,6 +315,10 @@
// Create worker threads to preprocess and bound the data.
Thread **workers = new Thread *[ np ];
+
+
+ CacheAlignedBBox *worker_box = new CacheAlignedBBox[ np ];
+
int work_per_thread = nTris / np;
long begin = 0;
@@ -323,7 +333,7 @@
sprintf( worker_name, "V3C1 Worker %d", i );
- workers[i] = new Thread( new V3C1Worker( rawData, tris,
perVertNormals, begin, end ), worker_name );
+ workers[i] = new Thread( new V3C1Worker( rawData, tris,
perVertNormals, begin, end, worker_box[i].box ), worker_name );
begin = end;
end += work_per_thread;
}
@@ -331,7 +341,7 @@
sprintf( worker_name, "V3C1 Worker %d", np-1 );
// Assign the rest of the work to the last worker.
- workers[np-1] = new Thread( new V3C1Worker( rawData, tris,
perVertNormals, begin, nTris ), "V3C1 Worker" );
+ workers[np-1] = new Thread( new V3C1Worker( rawData, tris,
perVertNormals, begin, nTris, worker_box[np-1].box ), "V3C1 Worker" );
// Wait for all of the threads to finish.
for (int i=0;i<np;++i) {
@@ -340,14 +350,12 @@
std::cout << "Worker " << i << " finished." << std::endl;
// Enlarge the bounding box.
- bounds.extendByBox( ((V3C1Worker
*)workers[i]->getRunnable())->bounds );
-
- // Delete the thread.
- // delete workers[i];
+ bounds.extendByBox( worker_box[i].box );
}
// Delete the array of pointers to workers.
delete [] workers;
+ delete [] worker_box;
#if 0
float *_rawData;
Modified: branches/itanium2/fox/FMantaImageFrame.cc
==============================================================================
--- branches/itanium2/fox/FMantaImageFrame.cc (original)
+++ branches/itanium2/fox/FMantaImageFrame.cc Sat Jun 18 22:29:40 2005
@@ -16,6 +16,11 @@
FXMAPFUNC(SEL_CONFIGURE, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onConfigure ),
FXMAPFUNC(SEL_LEFTBUTTONRELEASE, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onMouseChange ),
FXMAPFUNC(SEL_LEFTBUTTONPRESS, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onMouseChange ),
+ FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onMouseChange ),
+ FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onMouseChange ),
+ FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onMouseChange ),
+ FXMAPFUNC(SEL_RIGHTBUTTONPRESS, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onMouseChange ),
+
FXMAPFUNC(SEL_MOTION, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onMouseChange ),
FXMAPFUNC(SEL_KEYPRESS, FMantaImageFrame::ID_IMAGE,
FMantaImageFrame::onKeyPress )
};
Modified: branches/itanium2/fox/FMantaUniformNav.cc
==============================================================================
--- branches/itanium2/fox/FMantaUniformNav.cc (original)
+++ branches/itanium2/fox/FMantaUniformNav.cc Sat Jun 18 22:29:40 2005
@@ -12,6 +12,22 @@
Callback::create(this,
&FMantaUniformNav::mantaThreadCallback, action ));
}
+void FMantaUniformNav::projectToSphere( Vector &result, Real x, Real y, Real
radius ) {
+
+ x /= radius;
+ y /= radius;
+ Real rad2 = x*x+y*y;
+ if(rad2 > 1){
+ Real rad = sqrt(rad2);
+ x /= rad;
+ y /= rad;
+ result = Vector( x, y, 0 );
+ } else {
+ Real z = sqrt(1-rad2);
+ result = Vector( x, y, z );
+ }
+}
+
// Mouse events.
long FMantaUniformNav::onKeyPress ( FXObject *sender, FXSelector sel, void
*data ) {
@@ -83,21 +99,93 @@
FXEvent *event = (FXEvent *)data;
FXushort sel_type = FXSELTYPE( sel );
+ Real width = ((FXComposite *)sender)->getWidth() * 0.5;
+ Real height = ((FXComposite *)sender)->getHeight() * 0.5;
+
// Record mouse up and mouse down.
- if (sel_type == SEL_LEFTBUTTONPRESS) {
- mouse_down = true;
- }
- else if (sel_type == SEL_LEFTBUTTONRELEASE) {
- mouse_down = false;
- }
+ switch (sel_type) {
+ case SEL_LEFTBUTTONPRESS:
+ mouse_down[0] = true;
+
+ // Update rotate from.
+ projectToSphere( rotate_from,
+ ((Real)event->win_x-width)/width,
+
-((Real)event->win_y-height)/height,
+
trackball_radius );
+
+ std::cout << "Rotate from: " << rotate_from << std::endl;
+
+ break;
+ case SEL_LEFTBUTTONRELEASE:
+ mouse_down[0] = false;
+ break;
+ case SEL_MIDDLEBUTTONPRESS:
+ mouse_down[1] = true;
+ break;
+ case SEL_MIDDLEBUTTONRELEASE:
+ mouse_down[1] = false;
+ break;
+ case SEL_RIGHTBUTTONPRESS:
+ mouse_down[2] = true;
+ break;
+ case SEL_RIGHTBUTTONRELEASE:
+ mouse_down[2] = false;
+ break;
+ };
// Look for mouse movements.
- else if (sel_type == SEL_MOTION && mouse_down) {
+ if (sel_type == SEL_MOTION && mouse_down[0]) {
- Real delta_x = event->win_x - event->last_x;
- Real delta_y = event->win_y - event->last_y;
+ // Update rotate to.
+ projectToSphere( rotate_to,
+ ((Real)event->win_x-width)/width,
+
-((Real)event->win_y-height)/height,
+
trackball_radius );
- std::cerr << "delta " << delta_x << " " << delta_y <<
std::endl;
+ // Check to make sure the vectors are far enough apart.
+ std::cout << "Distance: " << (rotate_from -
rotate_to).length() << std::endl;
+
+ Real distance = (rotate_from - rotate_to).length();
+ if (distance > 0.001) {
+
+ // Create a rotation event.
+ Action action;
+
+ std::cout << "Rotate: from: "
+ <<
rotate_from << " to: "
+ << rotate_to
<< std::endl;
+
+ action.type = Action::ROTATE;
+ action.rotation.initWithRotation( rotate_to,
rotate_from );
+
+ // Send the rotation to manta.
+ mantaAddTransaction( action );
+
+ // Move the from point of the rotation.
+ rotate_from = rotate_to;
+ }
+ }
+ else if (sel_type == SEL_MOTION && mouse_down[1]) {
+
+ // Create a pan (translation) event.
+ Action action;
+
+ action.type = Action::DOLLY;
+ action.dolly = ((Real) (event->win_x -
event->last_x))/(width+amount);
+
+ mantaAddTransaction( action );
+ }
+
+ else if (sel_type == SEL_MOTION && mouse_down[2]) {
+
+ // Create a pan (translation) event.
+ Action action;
+
+ action.type = Action::TRANSLATE;
+ action.translation[0] = ((Real)-(event->win_x -
event->last_x))/width;
+ action.translation[1] = ((Real) (event->win_y -
event->last_y))/height;
+
+ mantaAddTransaction( action );
}
return 1;
@@ -118,7 +206,7 @@
// Check for a rotation.
if (action.type == Action::ROTATE) {
- manta_camera->transform( action.rotation, Camera::Eye );
+ manta_camera->transform( action.rotation,
(Camera::TransformCenter)rotate_type );
}
// Check for a dolly.
Modified: branches/itanium2/fox/FMantaUniformNav.h
==============================================================================
--- branches/itanium2/fox/FMantaUniformNav.h (original)
+++ branches/itanium2/fox/FMantaUniformNav.h Sat Jun 18 22:29:40 2005
@@ -4,6 +4,8 @@
#include <MantaTypes.h>
#include <Core/Geometry/PointVector.h>
#include <Core/Geometry/AffineTransform.h>
+#include <Core/Math/MiscMath.h>
+#include <Core/Math/Trig.h>
#include <fox/FMantaNavigator.h>
@@ -15,6 +17,7 @@
// The center of rotation by default is the camera itself, however
// the user may "freeze" the center of rotation at a point and then
// rotate the camera about that point.
+
class FMantaUniformNav : public FMantaNavigator {
private:
// This structure defines an amount to change the camera.
@@ -36,14 +39,31 @@
};
// Attributes.
- Real amount; // Uniform amount to move.
- bool mouse_down;
+ Real amount; // Uniform amount to move.
+ Real trackball_radius; // Radius of trackball, 1.0 is half
width of window.
+
+ Vector rotate_from; // Trackball vectors.
+ Vector rotate_to;
+
+ enum { ROTATE_EYE = Camera::Eye, ROTATE_LOOKAT =
Camera::LookAt };
+ int rotate_type;
+
+ // Mouse buttons up and down.
+ bool mouse_down[3];
// This method sends the transaction to manta.
void mantaAddTransaction( Action &action );
+ // This method is used to implement the trackball.
+ // Note that x and y are [-radius,radius]
+ void projectToSphere( Vector &result, Real x, Real y, Real
radius );
+
public:
- FMantaUniformNav() : mouse_down( false ), amount( 1.0 ) { };
+ FMantaUniformNav() : amount( 1.0 ),
+ trackball_radius( 1.0 ),
+
rotate_type( ROTATE_EYE ) {
+
+ mouse_down[0] = mouse_down[1] = mouse_down[2] =
false; };
// Mouse events.
long onKeyPress ( FXObject *sender, FXSelector sel, void
*data );
@@ -51,6 +71,10 @@
// This function is called by the manta thread.
void mantaThreadCallback( Action action ) const;
+
+ // Accessors.
+ void setAmount( Real amount_ ) { amount =
amount_; };
+ void setTrackballRadius( Real trackball_radius_ ) {
trackball_radius = trackball_radius_; };
};
};
Modified: branches/itanium2/fox/FMantaWindow.cc
==============================================================================
--- branches/itanium2/fox/FMantaWindow.cc (original)
+++ branches/itanium2/fox/FMantaWindow.cc Sat Jun 18 22:29:40 2005
@@ -35,8 +35,15 @@
manta_menu = new FXMenuPane( this );
new FXMenuTitle( menu_bar, "Manta", 0, manta_menu );
+ // Create the content of the window.
+ FXComposite *frame = new FXHorizontalFrame( this, LAYOUT_FILL );
+
+ FXComposite *left_controls = new FXVerticalFrame ( frame,
LAYOUT_FILL_Y|LAYOUT_LEFT );
+ FXComposite *viewers = new FXHorizontalFrame( frame,
LAYOUT_FILL );
+ FXComposite *right_controls = new FXVerticalFrame ( frame,
LAYOUT_FILL_Y|LAYOUT_RIGHT );
+
// Manta Image Frame.
- manta_frame = new FMantaImageFrame( this, app, width, height, 0 );
+ manta_frame = new FMantaImageFrame( viewers, app, width, height, 0 );
}
// Quit the program.
Modified: branches/itanium2/fox/fox_manta.cc
==============================================================================
--- branches/itanium2/fox/fox_manta.cc (original)
+++ branches/itanium2/fox/fox_manta.cc Sat Jun 18 22:29:40 2005
@@ -8,6 +8,7 @@
#include <X11/Xlib.h>
#include <Engine/Display/GLXImageDisplay.h>
+#include <Model/Cameras/PinholeCamera.h>
#include <fox/FMantaWindow.h>
#include <fox/FMantaUniformNav.h>
@@ -15,7 +16,6 @@
#include <string>
#include <stdlib.h>
-
using namespace FX;
using namespace fox_manta;
using namespace Manta;
@@ -29,6 +29,7 @@
// Parse args.
int np = 1;
+ char *scene_text = 0;
// Look for specific args.
for (int i=0;i<argc;++i) {
@@ -36,6 +37,9 @@
if (arg == "-np") {
np = atoi( argv[++i] );
}
+ else if (arg == "-scene") {
+ scene_text = argv[++i];
+ }
}
std::cerr << "Using " << np << " workers plus one gui thread." <<
std::endl;
@@ -49,7 +53,7 @@
int height = 256;
// Add an FMantaWindow.
- FMantaWindow manta_window( &app, "Fox/Manta Demo App", width, height
);
+ FMantaWindow manta_window( &app, "Open-Source MANTA. Silicon Graphics
Inc. and SCI Institute, University of Utah", width, height );
// Create the application's windows.
app.create();
@@ -67,6 +71,10 @@
manta_interface->selectShadowAlgorithm( "hard" );
Camera *camera = manta_interface->createCamera( "pinhole(-eye 1 1 1
-lookat 0 -1.0 0 -up 0 0 1 -fov 60)" );
+ //Camera *camera = new PinholeCamera( Point ( 0.0, 2.0, 1.0 ),
+ // Point ( 0.0, 0.0, 0.0 ),
+ //
Vector( 0.0, 0.0, 1.0 ),
+ //
60
);
// Create the manta image frame.
FMantaImageFrame *manta_frame = manta_window.getMantaFrame();
@@ -93,9 +101,13 @@
int manta_channel = 0; // !!! See XWindowUI.cc line: 586
manta_interface->createChannel( &glx_image_display, camera, false,
width, height );
- // Create a default scene.
- manta_interface->setScene( createDefaultScene() );
-
+ // Check for a command line scene.
+ if ((scene_text == 0) || (!manta_interface->readScene( scene_text )))
{
+ // Create a default scene.
+ manta_interface->setScene( createDefaultScene() );
+
+ }
+
// Set the manta interface for the application.
manta_window.setMantaInterface( manta_interface, manta_channel );
Modified: branches/itanium2/manta-commands.txt
==============================================================================
--- branches/itanium2/manta-commands.txt (original)
+++ branches/itanium2/manta-commands.txt Sat Jun 18 22:29:40 2005
@@ -1,3 +1,6 @@
+# Engine Cross Section
+dplace -c 1-61 bin/manta -np 60 -scene "lib/libscene_boeing777.so( -file
/dev/shm/Boeing777.v3c1 -np 32 -cutting 1018.45 -390.521 106.425 0 -1 0 )"
-camera "pinhole( -eye 1038.31 -517.053 108.78 -lookat 1057.9 169.557
123.655 -up 0.0107751 -0.392417 0.919724 -fov 60 )"
+
# Cockpit Cross section.
dplace -c 1-61 bin/manta -np 60 -scene "lib/libscene_boeing777.so( -file
/dev/shm/Boeing777.v3c1 -np 32 -cutting default )" -camera "pinhole( -eye
312.31 -315.671 199.735 -lookat 280.305 98.0706 184.652 -up 0.0256952
-0.337005 0.941152 -fov 60 )"
@@ -5,4 +8,7 @@
dplace -c 1-61 bin/manta -np 60 -scene "lib/libscene_boeing777.so( -file
/dev/shm/Boeing777.v3c1 )" -camera "pinhole( -eye 1821.5 -29.356 2323.27
-lookat 1446.55 13.6745 -591.948 -up -0.323033 -0.85584 0.403966 -fov 60 )"
# Nose from outside.
-dplace -c 1-61 bin/manta -np 60 -scene "lib/libscene_boeing777.so( -file
/dev/shm/Boeing777.v3c1 -np 32 )" -camera "pinhole( -eye 104.567 -27.7932
239.894 -lookat 964.189 -144.363 202.981 -up -0.329093 0.0449434 0.943228
-fov 51.217 )"
\ No newline at end of file
+dplace -c 1-61 bin/manta -np 60 -scene "lib/libscene_boeing777.so( -file
/dev/shm/Boeing777.v3c1 -np 32 )" -camera "pinhole( -eye 104.567 -27.7932
239.894 -lookat 964.189 -144.363 202.981 -up -0.329093 0.0449434 0.943228
-fov 51.217 )"
+
+# Massive cross section NOTE RESOLUTION
+dplace -c 1-511 bin/manta -res 46080x14400 -bench 1 0 -np 508 -scene
"lib/libscene_boeing777.so( -file /dev/shm/Boeing777.v3c1 -np 64 -cutting
default )" -camera "pinhole( -eye 1408.56 -2172.05 110.736 -lookat 1350.55
188.313 354.277 -up 0.0117111 -0.465077 0.885192 -fov 60 )" -shadows
noshadows -imagedisplay "file( /tmp/test_img46080x14400 )
Modified: branches/itanium2/scenes/0.cc
==============================================================================
--- branches/itanium2/scenes/0.cc (original)
+++ branches/itanium2/scenes/0.cc Sat Jun 18 22:29:40 2005
@@ -8,15 +8,12 @@
#include <Interface/Scene.h>
#include <Model/AmbientLights/ArcAmbient.h>
#include <Model/Backgrounds/LinearBackground.h>
-#include <Model/Backgrounds/ConstantBackground.h>
#include <Model/Groups/Group.h>
#include <Model/Lights/PointLight.h>
#include <Model/Materials/Lambertian.h>
#include <Model/Materials/MetalMaterial.h>
-#include <Model/Materials/NormalMaterial.h>
#include <Model/Primitives/Parallelogram.h>
#include <Model/Primitives/Sphere.h>
-#include <Model/Primitives/Cube.h>
#include <Model/Textures/CheckerTexture.h>
#include <Core/Geometry/AffineTransform.h>
#include <Core/Util/NotFinished.h>
@@ -92,15 +89,11 @@
static void make_box(Group* group, Material* matl,
const Point& corner, const Vector& x, const Vector& y,
const Vector& z)
{
- // group->add(new Parallelogram(matl, corner, x*2, z*2));
- // group->add(new Parallelogram(matl, corner+y*2, z*2, x*2));
- // group->add(new Parallelogram(matl, corner, y*2, z*2));
- // group->add(new Parallelogram(matl, corner+x*2, z*2, y*2));
- // group->add(new Parallelogram(matl, corner+z*2, x*2, y*2));
-
- Point corner1 = corner + x + y + z;
-
- group->add( new Cube( matl, corner, corner1 ) );
+ group->add(new Parallelogram(matl, corner, x*2, z*2));
+ group->add(new Parallelogram(matl, corner+y*2, z*2, x*2));
+ group->add(new Parallelogram(matl, corner, y*2, z*2));
+ group->add(new Parallelogram(matl, corner+x*2, z*2, y*2));
+ group->add(new Parallelogram(matl, corner+z*2, x*2, y*2));
}
static void make_obj(Group* world, int size)
@@ -108,20 +101,20 @@
Vector objset[9];
create_dirs(objset);
Material* matl0=new Lambertian(Color(RGBColor(.4,.4,.4)));
- //create_objs(world, Point(0,0,.5), BV_RADIUS/2.0, Vector(0,0,1),
- // size, objset, matl0);
+ create_objs(world, Point(0,0,.5), BV_RADIUS/2.0, Vector(0,0,1),
+ size, objset, matl0);
- // Just make a box....
+ Vector diag1(1,1,0);
+ diag1.normalize();
+ Vector diag2(-1,1,0);
+ diag2.normalize();
Material* matl1=new Lambertian(Color(RGBColor(.2,.4,.2)));
- NormalMaterial* normal_material = new NormalMaterial();
-
- // Add a box.
- world->add( new Cube( normal_material, Point(-1,-1,-1), Point(1,1,1)
) );
-
- // Make a sphere where we think the box should be
- world->add(new Sphere( normal_material, Point(0.0,0.0,0.00), 1.0 ) );
-
- /*
+ diag1*=1.5;
+ diag2*=1.5;
+ Vector z(0,0,.4);
+ Point corner(-1.8,-.3,0);
+ make_box(world, matl1, corner, diag1, diag2, z);
+
Material* matl3=new MetalMaterial( Color(RGBColor(.7,.7,.7)));
world->add(new Sphere(matl3,
corner+diag1*1.25+diag2*.6+z*2+Vector(0,0,.6), .6));
double planesize=15;
@@ -134,7 +127,6 @@
Vector edge2(-planesize*1.1, planesize, 0);
Object* obj1=new Parallelogram(matl2, Point(0,0,0)-edge1-edge2, edge1*2,
edge2*2);
world->add(obj1);
- */
}
extern "C"
@@ -167,10 +159,9 @@
if(!world)
world = new Group();
-
+
NOT_FINISHED("scene 0");
make_obj(world, scenesize);
-
#if 0
Camera cam(Point(1.8,-5.53,1.25), Point(0.0,-.13,1.22),
Vector(0,0,1), 28.2);
@@ -181,7 +172,7 @@
Color cup(RGB(0.1, 0.3, 0.8));
- rtrt::Plane groundplane ( Point(0, 0, 0), Vector(0, 0, 300) );
+ rtrt::Plane groundplane ( Point(0, 0, 0), Vector(0, 0, 3) );
Scene* scene=new Scene(obj, cam,
bgcolor, cdown, cup, groundplane,
ambient_scale, Arc_Ambient);
@@ -189,7 +180,9 @@
scene->select_shadow_mode( Single_Soft_Shadow );
#endif
Scene* scene = new Scene();
- scene->setBackground(new ConstantBackground(Color::white()));
+ scene->setBackground(new LinearBackground(Color(RGB(0.2, 0.4, 0.9)),
+ Color::black(),
+ Vector(0,0,1)));
scene->setObject(world);
NOT_FINISHED("soft shadows/area lights for scene 0");
- [MANTA] r395 - in branches/itanium2: . Model/Cameras Model/Groups fox scenes, abe, 06/18/2005
Archive powered by MHonArc 2.6.16.