home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
PASM.LZH
/
PARTS.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-12
|
14KB
|
599 lines
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "matrix.h"
#include "suflib.h"
#include "seltype.h"
#include "parts.h"
#include "files.h"
#include "log.h"
#ifdef __WIN32__
#define INTMAX (double)(1<<30)
#else
#define INTMAX 32768.0
#endif
static const int EyeLength = 500;
LightType lighttype = LightLeftUpper;
Parts::Parts(Object *obj, Vector& pos, Vector& rot, Vector& scal)
{
position = pos;
rotation = rot;
scale = scal;
next = NULL;
sel = FALSE;
if (obj == NULL) {
object = NULL;
point_x = point_y = point_z = NULL;
view_x = view_y = view_z = NULL;
line_1 = line_2 = NULL;
lines = 0;
maxx = maxy = maxz = minx = miny = minz = 0;
polygons = 0;
} else {
object = obj;
point_x = new int[obj->points];
point_y = new int[obj->points];
point_z = new int[obj->points];
view_x = new int[obj->points];
view_y = new int[obj->points];
view_z = new int[obj->points];
line_1 = obj->line_1;
line_2 = obj->line_2;
lines = obj->lines;
maxx = obj->maxx;
maxy = obj->maxy;
maxz = obj->maxz;
minx = obj->minx;
miny = obj->miny;
minz = obj->minz;
polygons = obj->polygons;
}
}
Parts::Parts(Parts *p)
{
next = NULL;
sel = FALSE;
if (p == NULL || p->object == NULL) {
position = Vector(0,0,0);
rotation = Vector(0,0,0);
scale = Vector(1,1,1);
object = NULL;
point_x = point_y = point_z = NULL;
view_x = view_y = view_z = NULL;
line_1 = line_2 = NULL;
lines = 0;
maxx = maxy = maxz = minx = miny = minz = 0;
polygons = 0;
} else {
position = p->position;
rotation = p->rotation;
scale = p->scale;
object = p->object;
point_x = new int[object->points];
point_y = new int[object->points];
point_z = new int[object->points];
view_x = new int[object->points];
view_y = new int[object->points];
view_z = new int[object->points];
line_1 = object->line_1;
line_2 = object->line_2;
lines = object->lines;
maxx = object->maxx;
maxy = object->maxy;
maxz = object->maxz;
minx = object->minx;
miny = object->miny;
minz = object->minz;
polygons = object->polygons;
}
}
Parts::~Parts(void)
{
if (point_x != NULL) delete[] point_x;
if (point_y != NULL) delete[] point_y;
if (point_z != NULL) delete[] point_z;
if (view_x != NULL) delete[] view_x;
if (view_y != NULL) delete[] view_y;
if (view_z != NULL) delete[] view_z;
}
void Parts::CalcPoints(Matrix& m)
{
if (object != NULL) {
for (int i = 0; i < object->points; ++i) {
Vector v1 = m * Vector(object->point_x[i], object->point_y[i], object->point_z[i]);
point_x[i] = int(v1.x);
point_y[i] = int(v1.y);
point_z[i] = int(v1.z);
}
}
}
void Parts::CalcView(Matrix& m)
{
if (object != NULL) {
for (int i = 0; i < object->points; ++i) {
Vector v1 = m * Vector(object->point_x[i], object->point_y[i], object->point_z[i]);
if (v1.z <= 1.0) {
view_x[i] = 0;
view_y[i] = 0;
view_z[i] = -1;
} else {
double vx = v1.x / v1.z;
double vy = v1.y / v1.z;
if (vx < -4096 || vx > 4096 || vy < -4096 || vy > 4096) {
view_x[i] = 0;
view_y[i] = 0;
view_z[i] = -1;
} else {
view_x[i] = (int)vx;
view_y[i] = (int)vy;
view_z[i] = (int)(INTMAX / v1.z);
}
}
#if 0
view_x[i] = int(v1.x / v1.z);
view_y[i] = int(v1.y / v1.z);
if (v1.z > 1.0) {
view_z[i] = int(INTMAX / v1.z);
} else {
view_z[i] = -1;
}
#endif
}
}
}
void Parts::SetRotationParameter(Matrix& m)
{
rotation = m.GetRotation();
}
void Parts::GetMatrix(Matrix& move, Matrix& rot, Matrix& scal)
{
move = Matrix(1).move(position);
rot = Matrix(1).rotz(rotation.z).roty(rotation.y).rotx(rotation.x);
scal = Matrix(1).scale(scale);
}
void Parts::Trans(SelectType t)
{
switch (t) {
case SelX:
position.x = -position.x;
scale.x = -scale.x;
rotation.y = -rotation.y;
rotation.z = -rotation.z;
// if (rotation.z >= 0.0) {
// rotation.z = deg(180.0) - rotation.z;
// } else {
// rotation.z = deg(-180.0) - rotation.z;
// }
break;
case SelY:
position.y = -position.y;
scale.y = -scale.y;
rotation.x = -rotation.x;
rotation.z = -rotation.z;
break;
case SelZ:
position.z = -position.z;
scale.z = -scale.z;
rotation.x = -rotation.x;
rotation.y = -rotation.y;
break;
}
}
Matrix Parts::GetMatrix(void)
{
return Matrix(1)
.move(position)
.rotz(rotation.z)
.roty(rotation.y)
.rotx(rotation.x)
.scale(scale);
}
void Parts::PartsWrite(FILE *fp, char *initialdir, int len)
{
char *p = object->filename;
if (len > 0 && strncmpi(object->filename, initialdir, len) == 0) {
p = object->filename + len + 1;
} else if (strncmpi(object->filename, partsdir.c_str(), partsdir.length()) == 0) {
p = object->filename + partsdir.length();
} else if (strncmpi(object->filename, simplepartsdir.c_str(), simplepartsdir.length()) == 0) {
p = object->filename + simplepartsdir.length();
}
fprintf(fp,
#if 0
"\t{\tmov ( %5.0lf %5.0lf %5.0lf ) "
"rotz( %4.0lf ) roty( %4.0lf ) rotx( %4.0lf )\n"
"\t\tscal ( %5.3lf %5.3lf %5.3lf ) obj %s (: %s :)\n"
"\t}\n",
#else
"\t{\tmov ( %5.0lf %5.0lf %5.0lf ) "
"rotz( %4.0lf ) roty( %4.0lf ) rotx( %4.0lf )\n"
"\t\tscal ( %5.3lf %5.3lf %5.3lf ) obj %s /* %s */\n"
"\t}\n",
#endif
position.x, position.y, position.z,
rad(rotation.z), rad(rotation.y), rad(rotation.x),
scale.x, scale.y, scale.z, object->name, p);
}
int Parts::FileWrite(CameraParts *cam, char *filename, char *initialdir)
{
FILE *fp;
int objs = 0;
Parts *p;
int len = 0;
errormessage[0] = '\0';
if (initialdir != NULL) {
len = strlen(initialdir);
}
if ((fp = fopen(filename, "w")) == NULL) {
sprintf(errormessage, "メカデザインファイルの保存に失敗しました: %s", filename, _sys_errlist[errno]);
return FALSE;
}
for (p = this; p != NULL; p = p->next) {
if (p != cam) {
objs++;
}
}
fprintf(fp,
"/* Parts Assembler\n"
" Version 1.1\n"
"Parts: \n");
for (p = this; p != NULL; p = p->next) {
for (Parts *op = this; op != p && op != NULL; op = op->next) {
if (op->object == p->object) {
break;
}
}
if (op == p || op == NULL) {
char *f = p->object->filename;
if (len > 0 && strncmpi(p->object->filename, initialdir, len) == 0) {
f = p->object->filename + len + 1;
} else if (strncmpi(p->object->filename, partsdir.c_str(), partsdir.length()) == 0) {
f = p->object->filename + partsdir.length();
} else if (strncmpi(p->object->filename, simplepartsdir.c_str(), simplepartsdir.length()) == 0) {
f = p->object->filename + simplepartsdir.length();
}
fprintf(fp, "\t%s\n", f);
}
}
fprintf(fp,"*/\nfram\n{\n");
if (cam != NULL) {
Vector evec = cam->target - cam->position;
Vector lvec;
if (lighttype == LightLeftUpper || lighttype == LightLeftLower) {
lvec.x = evec.x + evec.y;
lvec.y = -evec.x + evec.y;
} else {
lvec.x = evec.x - evec.y;
lvec.y = evec.x + evec.y;
}
lvec.z = sqrt(lvec.x * lvec.x + lvec.y * lvec.y);
if (evec.x == 0.0 || evec.y == 0.0 || lvec.length() < minimumdouble) {
fprintf(fp, "\tlight pal( rgb ( 1.00 1.00 1.00 ) -3.00 -2.00 -4.00 )\n");
} else {
lvec *= (100.0 / lvec.length());
if (evec.z < 0) {
lvec.z = -lvec.z;
}
fprintf(fp, "\tlight pal( rgb ( 1.00 1.00 1.00 ) %3d %3d %3d )\n",
(int)(lvec.x),(int)(lvec.y),(int)(lvec.z));
}
cam->PartsWrite(fp, initialdir, len);
} else {
fprintf(fp, "\tlight pal( rgb ( 1.00 1.00 1.00 ) -3.00 -2.00 -4.00 )\n");
fprintf(fp,"\t{\tmov ( 0 0 0 ) eye deg( 60 ) }\n");
}
for (p = this; p != NULL; p = p->next) {
if (p != cam) {
p->PartsWrite(fp, initialdir, len);
}
}
#if 0
fprintf(fp, "}\n#endframe\n");
#else
fprintf(fp, "}\n");
#endif
int fe = ferror(fp);
if (ferror(fp)) {
sprintf(errormessage, "メカデザインファイルの保存に失敗しました: %s", _sys_errlist[errno]);
fclose(fp);
return FALSE;
}
fclose(fp);
return TRUE;
}
CameraParts::CameraParts(Vector& pos, Vector& tar): Parts()
{
position = pos;
scale = Vector(1.0, 1.0, 1.0);
target = tar;
SetAngle(deg(60));
SetTarget(tar);
line_1 = l1;
line_2 = l2;
for (int i = 0; i < CameraLines; ++i) {
line_1[i] = 0;
line_2[i] = i+1;
}
lines = CameraLines;;
point_x = new int[CameraPoints];
point_y = new int[CameraPoints];
point_z = new int[CameraPoints];
view_x = new int[CameraPoints];
view_y = new int[CameraPoints];
view_z = new int[CameraPoints];
}
//CameraParts::~CameraParts(): ~Parts()
//{
//}
void CameraParts::SetTarget(Vector& v)
{
target = v;
Matrix m = (v - position) ^ Vector(0.0, 0.0, 1.0);
double len = (v - position).length() / (double)EyeLength;
rotation = m.GetRotation();
scale.x = scale.y = scale.z = len;
}
void CameraParts::SetAngle(double a)
{
angle = a;
px[0] = py[0] = pz[0] = 0;
px[1] = EyeLength;
py[1] = pz[1] = 0;
for (int i = 2; i < CameraPoints; ++i) {
px[i] = EyeLength * 10;
}
py[2] = py[3] = int(double(EyeLength * 10) * tan(angle/2.0));
py[4] = py[5] = -py[2];
pz[2] = pz[4] = py[2] * 3 / 4;
pz[3] = pz[5] = -pz[2];
}
void CameraParts::CalcPoints(Matrix& m)
{
for (int i = 0; i < CameraPoints; ++i) {
Vector v1 = m * Vector(px[i], py[i], pz[i]);
point_x[i] = int(v1.x);
point_y[i] = int(v1.y);
point_z[i] = int(v1.z);
}
}
void CameraParts::CalcView(Matrix& /*m*/)
{
for (int i = 0; i < CameraPoints; ++i) {
view_x[i] = view_y[i] = 0;
view_z[i] = -1;
}
}
void CameraParts::PartsWrite(FILE *fp, char* /*initialdir*/, int /*len*/)
{
fprintf(fp,
"\t{\tmov ( %5.0lf %5.0lf %5.0lf ) eye deg( %d ) }\n"
"\t{\tmov ( %5.0lf %5.0lf %5.0lf ) target }\n",
position.x, position.y, position.z,
int(rad(angle)+0.5),
target.x, target.y, target.z);
}
CombinedParts::CombinedParts(void):
Parts()
{
nparts = 0;
}
CombinedParts::~CombinedParts(void)
{
Parts::~Parts();
}
void CombinedParts::CalcSizeAll(void)
{
int i;
minx = miny = minz = 32767;
maxx = maxy = maxz = -32767;
polygons = 0;
for (i = 0; i < nparts; i++) {
if (parts[i]->object != NULL) {
polygons += parts[i]->polygons;
Matrix m = parts[i]->GetMatrix();
int points = parts[i]->object->points;
int j;
for (j = 0; j < points; j++) {
Vector v = m *
Vector( parts[i]->object->point_x[j],
parts[i]->object->point_y[j],
parts[i]->object->point_z[j]);
if (minx > v.x) minx = v.x;
if (maxx < v.x) maxx = v.x;
if (miny > v.y) miny = v.y;
if (maxy < v.y) maxy = v.y;
if (minz > v.z) minz = v.z;
if (maxz < v.z) maxz = v.z;
}
}
}
rotation = Vector(0,0,0);
scale = Vector(1,1,1);
position = Vector( (minx+maxx)/2, (miny+maxy)/2, (minz+maxz)/2);
maxx = (maxx-minx)/2; minx = -maxx;
maxy = (maxy-miny)/2; miny = -maxy;
maxz = (maxz-minz)/2; minz = -maxz;
orig_position = old_position = position;
old_rotation = rotation;
old_scale = scale;
}
int CombinedParts::AddParts(Parts *p)
{
int i;
for (i = 0; i < nparts; i++) {
if (parts[i] == p) {
return FALSE;
}
}
parts[nparts++] = p;
return TRUE;
}
int CombinedParts::DeleteParts(Parts *p)
{
for (int i = 0; i < nparts; i++) {
if (parts[i] == p) {
for (; i < nparts-1; i++) {
parts[i] = parts[i+1];
}
nparts--;
CalcSizeAll();
return TRUE;
}
}
return FALSE;
}
void CombinedParts::MoveParts(Matrix& m, double scalerate)
{
Matrix m0(m);
Matrix mt;
#if 0
m0.v[0] *= (1.0/m0.v[0].length());
m0.v[1] *= (1.0/m0.v[1].length());
m0.v[2] *= (1.0/m0.v[2].length());
if (scalerate < 0) {
scalerate = -scalerate;
s = TRUE;
}
#endif
for (int i = 0; i < nparts; i++) {
parts[i]->scale *= scalerate;
mt = m0.move(parts[i]->position)
.rotz(parts[i]->rotation.z)
.roty(parts[i]->rotation.y)
.rotx(parts[i]->rotation.x);
mt.v[0] *= (1.0/mt.v[0].length());
mt.v[1] *= (1.0/mt.v[1].length());
mt.v[2] *= (1.0/mt.v[2].length());
if (scalerate < 0) {
mt.v[0] *= -1;
mt.v[1] *= -1;
mt.v[2] *= -1;
}
parts[i]->position = mt.v[3]; mt.v[3] = Vector(0,0,0);
parts[i]->rotation = mt.GetRotation();
}
}
void CombinedParts::MoveParts(void)
{
int p, r, s;
p = (old_position == position);
r = (old_rotation == rotation);
s = (old_scale == scale);
if (p && r && s) {
return;
} else if (!p && r && s) {
Vector v = position - old_position;
for (int i = 0; i < nparts; i++) {
parts[i]->position += v;
}
} else {
Matrix m0 = Matrix(1).move(old_position)
.rotz(old_rotation.z).roty(old_rotation.y).rotx(old_rotation.x)
.scale(old_scale);
Matrix m1 = Matrix(1).move(position)
.rotz(rotation.z).roty(rotation.y).rotx(rotation.x)
.scale(scale);
Matrix m = m1 * m0.inv();
MoveParts(m1 * m0.inv(), scale.x/old_scale.x);
}
old_position = position;
old_rotation = rotation;
old_scale = scale;
}
void CombinedParts::CalcPoints(Matrix& m)
{
MoveParts();
Matrix mt;
mt = m * GetMatrix().inv();
for (int i = 0; i < nparts; i++) {
parts[i]->CalcPoints(mt * parts[i]->GetMatrix());
}
}
void CombinedParts::CalcView(Matrix& m)
{
MoveParts ();
Matrix mt;
mt = m * GetMatrix().inv();
for (int i = 0; i < nparts; i++) {
parts[i]->CalcView(mt * parts[i]->GetMatrix());
}
}
void CombinedParts::DeleteAllParts(void)
{
nparts = 0;
#if 0
position = rotation = Vector(0,0,0);
scale = Vector(1,1,1);
minx = miny = minz = 32767;
maxx = maxy = maxz = -32767;
#endif
}
void CombinedParts::AddAllParts(Parts *p)
{
DeleteAllParts();
int i;
for (i = 0; p != NULL && i < MaxParts; p = p->next) {
parts[i++] = p;
}
nparts = i;
CalcSizeAll();
}