the Trans_* mesh-transformation-functions are now implemented in the Engine instead of System.ocg

issue1247
David Dormagen 2013-07-07 15:54:35 +02:00 committed by Sven Eberhardt
parent ad1c2760b0
commit fb1ee2f88f
2 changed files with 131 additions and 71 deletions

View File

@ -1,71 +0,0 @@
/*--
MeshTransformation.c
Authors: ck
Some common transformation matrices, and a function to multiply them together to produce more complex transformations.
--*/
global func Trans_Identity()
{
return [1000, 0, 0, 0,
0, 1000, 0, 0,
0, 0, 1000, 0];
}
global func Trans_Translate(int dx, int dy, int dz)
{
return [1000, 0, 0, dx,
0, 1000, 0, dy,
0, 0, 1000, dz];
}
global func Trans_Scale(int sx, int sy, int sz)
{
if (sy == nil && sz == nil)
sz = sy = sx;
return [sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0];
}
global func Trans_Rotate(int angle, int rx, int ry, int rz)
{
var c = Cos(angle, 1000);
var s = Sin(angle, 1000);
var n = Sqrt(rx*rx + ry*ry + rz*rz);
rx = 1000 * rx / n;
ry = 1000 * ry / n;
rz = 1000 * rz / n;
// Note that 0 <= rx,ry,rz,c,s <= 1000, so we don't overflow here.
return [
rx*rx*(1000-c)/1000000+c, rx*ry*(1000-c)/1000000-rz*s/1000, rx*rz*(1000-c)/1000000+ry*s/1000, 0,
ry*rx*(1000-c)/1000000+rz*s/1000, ry*ry*(1000-c)/1000000+c, ry*rz*(1000-c)/1000000-rx*s/1000, 0,
rz*rx*(1000-c)/1000000-ry*s/1000, ry*rz*(1000-c)/1000000+rx*s/1000, rz*rz*(1000-c)/1000000+c, 0];
}
global func Trans_Mul(array lhs, array rhs)
{
if (!rhs)
return lhs;
var result = [
lhs[0]*rhs[0]/1000 + lhs[1]*rhs[4]/1000 + lhs[ 2]*rhs[ 8]/1000,
lhs[0]*rhs[1]/1000 + lhs[1]*rhs[5]/1000 + lhs[ 2]*rhs[ 9]/1000,
lhs[0]*rhs[2]/1000 + lhs[1]*rhs[6]/1000 + lhs[ 2]*rhs[10]/1000,
lhs[0]*rhs[3]/1000 + lhs[1]*rhs[7]/1000 + lhs[ 2]*rhs[11]/1000 + lhs[3],
lhs[4]*rhs[0]/1000 + lhs[5]*rhs[4]/1000 + lhs[ 6]*rhs[ 8]/1000,
lhs[4]*rhs[1]/1000 + lhs[5]*rhs[5]/1000 + lhs[ 6]*rhs[ 9]/1000,
lhs[4]*rhs[2]/1000 + lhs[5]*rhs[6]/1000 + lhs[ 6]*rhs[10]/1000,
lhs[4]*rhs[3]/1000 + lhs[5]*rhs[7]/1000 + lhs[ 6]*rhs[11]/1000 + lhs[7],
lhs[8]*rhs[0]/1000 + lhs[9]*rhs[4]/1000 + lhs[10]*rhs[ 8]/1000,
lhs[8]*rhs[1]/1000 + lhs[9]*rhs[5]/1000 + lhs[10]*rhs[ 9]/1000,
lhs[8]*rhs[2]/1000 + lhs[9]*rhs[6]/1000 + lhs[10]*rhs[10]/1000,
lhs[8]*rhs[3]/1000 + lhs[9]*rhs[7]/1000 + lhs[10]*rhs[11]/1000 + lhs[11] ];
return Trans_Mul(result, ...);
}

View File

@ -154,6 +154,132 @@ C4Value C4AulDefFunc::Exec(C4PropList * p, C4Value pPars[], bool fPassErrors)
//=============================== C4Script Functions ====================================
#define MAKE_AND_RETURN_ARRAY(values) do { \
C4ValueArray *matrix = new C4ValueArray(sizeof(values) / sizeof(*values)); \
for (long i = 0; i < sizeof(values) / sizeof(*values); ++i) \
(*matrix)[i] = C4VInt(values[i]); \
return matrix; \
} while (0)
static C4ValueArray *FnTrans_Identity(C4PropList * _this)
{
long values[] =
{
1000, 0, 0, 0,
0, 1000, 0, 0,
0, 0, 1000, 0
};
MAKE_AND_RETURN_ARRAY(values);
}
static C4ValueArray *FnTrans_Translate(C4PropList * _this, long dx, long dy, long dz)
{
long values[] =
{
1000, 0, 0, dx,
0, 1000, 0, dy,
0, 0, 1000, dz
};
MAKE_AND_RETURN_ARRAY(values);
}
static C4ValueArray *FnTrans_Scale(C4PropList * _this, long sx, long sy, long sz)
{
if (sy == 0 && sz == 0)
sy = sz = sx;
long values[] =
{
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0
};
MAKE_AND_RETURN_ARRAY(values);
}
static C4ValueArray *FnTrans_Rotate(C4PropList * _this, long angle, long rx, long ry, long rz)
{
long c = fixtoi(Cos(itofix(angle, 1)), 1000);
long s = fixtoi(Sin(itofix(angle, 1)), 1000);
long sqrt_val = rx * rx + ry * ry + rz * rz;
long n = long(sqrt(double(sqrt_val)));
if (n * n < sqrt_val) n++;
else if (n * n > sqrt_val) n--;
rx = (1000 * rx) / n;
ry = (1000 * ry) / n;
rz = (1000 * rz) / n;
long values[] =
{
rx*rx*(1000-c)/1000000+c, rx*ry*(1000-c)/1000000-rz*s/1000, rx*rz*(1000-c)/1000000+ry*s/1000, 0,
ry*rx*(1000-c)/1000000+rz*s/1000, ry*ry*(1000-c)/1000000+c, ry*rz*(1000-c)/1000000-rx*s/1000, 0,
rz*rx*(1000-c)/1000000-ry*s/1000, ry*rz*(1000-c)/1000000+rx*s/1000, rz*rz*(1000-c)/1000000+c, 0
};
MAKE_AND_RETURN_ARRAY(values);
}
static C4Value FnTrans_Mul(C4PropList * _this, C4Value *pars)
{
const int32_t matrixSize = 12;
long values[] =
{
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
// Read all parameters
bool first = true;
for (int32_t i = 0; i < C4AUL_MAX_Par; i++)
{
C4Value Data = *(pars++);
// No data given?
if (!Data) break;
C4ValueArray *factorArray = Data.getArray();
if (!factorArray || factorArray->GetSize() != matrixSize) continue;
if (first)
{
first = false;
for (int32_t c = 0; c < matrixSize; ++c)
values[c] = (*factorArray)[c].getInt();
continue;
}
// multiply current matrix with new one
long values_rhs[matrixSize], values_result[matrixSize];
for (int32_t c = 0; c < matrixSize; ++c)
values_rhs[c] = (*factorArray)[c].getInt();
// matrix multiplication
values_result[ 0] = values[0]*values_rhs[0]/1000 + values[1]*values_rhs[4]/1000 + values[ 2]*values_rhs[ 8]/1000;
values_result[ 1] = values[0]*values_rhs[1]/1000 + values[1]*values_rhs[5]/1000 + values[ 2]*values_rhs[ 9]/1000;
values_result[ 2] = values[0]*values_rhs[2]/1000 + values[1]*values_rhs[6]/1000 + values[ 2]*values_rhs[10]/1000;
values_result[ 3] = values[0]*values_rhs[3]/1000 + values[1]*values_rhs[7]/1000 + values[ 2]*values_rhs[11]/1000 + values[3];
values_result[ 4] = values[4]*values_rhs[0]/1000 + values[5]*values_rhs[4]/1000 + values[ 6]*values_rhs[ 8]/1000;
values_result[ 5] = values[4]*values_rhs[1]/1000 + values[5]*values_rhs[5]/1000 + values[ 6]*values_rhs[ 9]/1000;
values_result[ 6] = values[4]*values_rhs[2]/1000 + values[5]*values_rhs[6]/1000 + values[ 6]*values_rhs[10]/1000;
values_result[ 7] = values[4]*values_rhs[3]/1000 + values[5]*values_rhs[7]/1000 + values[ 6]*values_rhs[11]/1000 + values[7];
values_result[ 8] = values[8]*values_rhs[0]/1000 + values[9]*values_rhs[4]/1000 + values[10]*values_rhs[ 8]/1000;
values_result[ 9] = values[8]*values_rhs[1]/1000 + values[9]*values_rhs[5]/1000 + values[10]*values_rhs[ 9]/1000;
values_result[10] = values[8]*values_rhs[2]/1000 + values[9]*values_rhs[6]/1000 + values[10]*values_rhs[10]/1000;
values_result[11] = values[8]*values_rhs[3]/1000 + values[9]*values_rhs[7]/1000 + values[10]*values_rhs[11]/1000 + values[11];
for (int32_t c = 0; c < matrixSize; ++c)
values[c] = values_result[c];
}
// unlike in the other Trans_*-functions, we have to put the array into a C4Value manually here
C4ValueArray *matrix = new C4ValueArray(sizeof(values) / sizeof(*values));
for (long i = 0; i < sizeof(values) / sizeof(*values); ++i)
(*matrix)[i] = C4VInt(values[i]);
return C4VArray(matrix);
}
#undef MAKE_AND_RETURN_ARRAY
static C4PropList * FnCreatePropList(C4PropList * _this, C4PropList * prototype)
{
return C4PropList::New(prototype);
@ -631,6 +757,7 @@ C4ScriptFnDef C4ScriptFnMap[]=
{ "Log", 1, C4V_Bool, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnLog },
{ "DebugLog", 1, C4V_Bool, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnDebugLog },
{ "Format", 1, C4V_String, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnFormat },
{ "Trans_Mul", 1, C4V_Array, { C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnTrans_Mul},
{ NULL, 0, C4V_Nil, { C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil}, 0 }
};
@ -684,6 +811,10 @@ void InitCoreFunctionMap(C4AulScriptEngine *pEngine)
F(SortArray);
F(SortArrayByProperty);
F(SortArrayByArrayElement);
F(Trans_Identity);
F(Trans_Translate);
F(Trans_Scale);
F(Trans_Rotate);
F(LocateFunc);
F(FileWrite);