コード例 #1
0
ファイル: pipe.c プロジェクト: dancahill/nsp
void pipe_murder(nsp_state *N, obj_t *cobj)
{
#define __FN__ __FILE__ ":pipe_murder()"
	//	PIPE_CONN *conn;

	n_warn(N, __FN__, "reaper is claiming another lost soul");
	if ((cobj->val->type != NT_CDATA) || (cobj->val->d.str == NULL) || (nc_strcmp(cobj->val->d.str, "pipe-conn") != 0))
		n_error(N, NE_SYNTAX, __FN__, "expected a pipe conn");
	//	conn=(PIPE_CONN *)cobj->val->d.str;
	n_free(N, (void *)&cobj->val->d.str, sizeof(PIPE_CONN) + 1);
	return;
#undef __FN__
}
コード例 #2
0
bool CInputMappingEvent::Init(CStrID Name, const CParams& Desc)
{
	const nString& InEvent = Desc.Get<nString>(CStrID("InEvent"));
	if (InEvent == "KeyDown")
	{
		InEventID = &Event::KeyDown::RTTI;
		Key = (EKey)Desc.Get<int>(CStrID("Key"));
	}
	else if (InEvent == "KeyUp")
	{
		InEventID = &Event::KeyUp::RTTI;
		Key = (EKey)Desc.Get<int>(CStrID("Key"));
	}
	else if (InEvent == "Char")
	{
		InEventID = &Event::CharInput::RTTI;
		Char = (ushort)Desc.Get<int>(CStrID("Char"));
	}
	else if (InEvent == "MouseBtnDown")
	{
		InEventID = &Event::MouseBtnDown::RTTI;
		MouseBtn = (EMouseButton)Desc.Get<int>(CStrID("MouseBtn"));
	}
	else if (InEvent == "MouseBtnUp")
	{
		InEventID = &Event::MouseBtnUp::RTTI;
		MouseBtn = (EMouseButton)Desc.Get<int>(CStrID("MouseBtn"));
	}
	else if (InEvent == "MouseDoubleClick")
	{
		InEventID = &Event::MouseDoubleClick::RTTI;
		MouseBtn = (EMouseButton)Desc.Get<int>(CStrID("MouseBtn"));
	}
	else if (InEvent == "MouseWheelFwd")
	{
		InEventID = &Event::MouseWheel::RTTI;
		WheelFwd = true;
	}
	else if (InEvent == "MouseWheelBack")
	{
		InEventID = &Event::MouseWheel::RTTI;
		WheelFwd = false;
	}
	else n_error("CInputMappingEvent::Init -> Unsupported input event!");

	OutEventID = Name;

	OK;
}
コード例 #3
0
ファイル: tcp.c プロジェクト: dancahill/nsp
/*
 * this is the function that terminates orphans
 */
void tcp_murder(nsp_state *N, obj_t *cobj)
{
#define __FN__ __FILE__ ":tcp_murder()"
	TCP_SOCKET *sock;

	n_warn(N, __FN__, "reaper is claiming another lost soul");
	if (cobj->val->type != NT_CDATA || cobj->val->d.str == NULL || strcmp(cobj->val->d.str, "sock4") != 0)
		n_error(N, NE_SYNTAX, __FN__, "expected a socket");
	sock = (TCP_SOCKET *)cobj->val->d.str;
	tcp_close(N, sock, 1);
	n_free(N, (void *)&cobj->val->d.str, sizeof(TCP_SOCKET) + 1);
	cobj->val->size = 0;
	return;
#undef __FN__
}
コード例 #4
0
ファイル: Command.cpp プロジェクト: moltenguy1/deusexmachina
// Execute a compiled command and gather the result
bool CCommand::Execute(const PDatabase& DB)
{
	n_assert(DB.isvalid()); //!!!only for error msg!
	n_assert(IsValid());

	if (VT.isvalid()) VT->SetModifiedTracking(false);

	bool Done = false;
	while (!Done)
	{
		switch (sqlite3_step(SQLiteStmt))
		{
			case SQLITE_DONE:	Done = true; break;
			case SQLITE_BUSY:	n_sleep(0.0001); break;
			case SQLITE_ROW:	if (VT.isvalid()) ReadRow(); break;
			case SQLITE_ERROR:	SetError(sqlite3_errmsg(DB->GetSQLiteHandle())); FAIL;
			case SQLITE_MISUSE:
			{
				n_error("CCommand::Execute(): sqlite3_step() returned SQLITE_MISUSE!");
				FAIL;
			}
			default:
			{
				n_error("CCommand::Execute(): unknown error code returned from sqlite3_step()");
				FAIL;
			}
		}
	}

	// Reset the command, this clears the bound values
	n_assert(sqlite3_reset(SQLiteStmt) == SQLITE_OK);

	if (VT.isvalid()) VT->SetModifiedTracking(true);

	OK;
}
コード例 #5
0
ファイル: mysql.c プロジェクト: dancahill/nsp
void mysql_murder(nsp_state *N, obj_t *cobj)
{
#define __FN__ __FILE__ ":mysql_murder()"
	MYSQL_CONN *conn;

	n_warn(N, __FN__, "reaper is claiming another lost soul");
	if ((cobj->val->type != NT_CDATA) || (cobj->val->d.str == NULL) || (nc_strcmp(cobj->val->d.str, "mysql-conn") != 0))
		n_error(N, NE_SYNTAX, __FN__, "expected a mysql conn");
	conn = (MYSQL_CONN *)cobj->val->d.str;
	mysqlDisconnect(N, conn);
	n_free(N, (void *)&cobj->val->d.str, sizeof(MYSQL_CONN) + 1);
	cobj->val->size = 0;
	return;
#undef __FN__
}
コード例 #6
0
const bbox3& CShapeEntity::GetShadowBox()
{
	uint CurrFrameID = GfxSrv->GetFrameID();
	if (CurrFrameID != ShadowBoxFrameID)
	{
		ShadowBoxFrameID = CurrFrameID;
		ShadowBBox = GetBox();

		const float DirExtrudeLength = ShadowBBox.size().y;
		const vector3& Pos = GetTransform().pos_component();

		vector3 LightVector, ExtrudeVector;
		nArray<PEntity>& LightLinks = Links[LightLink];
		for (int i = 0; i < LightLinks.Size(); i++)
		{
			CLightEntity* pLightEntity = (CLightEntity*)LightLinks[i].get();
			n_assert(pLightEntity->IsA(CLightEntity::RTTI));
			if (pLightEntity->Light.GetCastShadows())
			{
				const nLight& Light = pLightEntity->Light;
				nLight::Type LightType = Light.GetType();
				if (nLight::Directional == LightType)
				{
					LightVector = pLightEntity->GetTransform().z_component();
					LightVector.norm();
					ExtrudeVector = LightVector * DirExtrudeLength;
					ShadowBBox.extend(ShadowBBox.vmin - ExtrudeVector);
					ShadowBBox.extend(ShadowBBox.vmax - ExtrudeVector);
				}
				else if (nLight::Point == LightType)
				{
					const vector3& LightPos = pLightEntity->GetTransform().pos_component();
					LightVector = Pos - LightPos;
					LightVector.norm();
					ExtrudeVector = LightVector * Light.GetRange();
					ShadowBBox.extend(LightPos + ExtrudeVector);
				}
				else
				{
					// FIXME: unsupported Light type
					n_error("IMPLEMENT ME!!!");
				}
			}
		}
	}
	return ShadowBBox;
}
コード例 #7
0
void CNebula2Logger::logEvent(const CEGUI::String& message, CEGUI::LoggingLevel level)
{
	if (Enable && level <= getLoggingLevel())
		switch (level) 
		{
			case CEGUI::Errors:
				//nKernelServer::Instance()->Error("%s\n", message.c_str()); ///!!! TODO
				//break;
			case CEGUI::Standard:
			case CEGUI::Informative:
			case CEGUI::Insane:
				n_printf("%s\n", message.c_str());
				break;
			default:
				n_error("Unknown CEGUI logging level\n");
        }
}
コード例 #8
0
void CInputMappingEvent::Enable()
{
	if (Sub_InputEvent.isvalid()) return;

	bool(CInputMappingEvent::*CB)(const CEventBase& Event);

	if (InEventID == &Event::KeyDown::RTTI) CB = &CInputMappingEvent::OnKeyDown;
	else if (InEventID == &Event::KeyUp::RTTI) CB = &CInputMappingEvent::OnKeyUp;
	else if (InEventID == &Event::CharInput::RTTI) CB = &CInputMappingEvent::OnCharInput;
	else if (InEventID == &Event::MouseBtnDown::RTTI) CB = &CInputMappingEvent::OnMouseBtnDown;
	else if (InEventID == &Event::MouseBtnUp::RTTI) CB = &CInputMappingEvent::OnMouseBtnUp;
	else if (InEventID == &Event::MouseDoubleClick::RTTI) CB = &CInputMappingEvent::OnMouseDoubleClick;
	else if (InEventID == &Event::MouseWheel::RTTI) CB = &CInputMappingEvent::OnMouseWheel;
	else n_error("Unsupported input event!");

	Sub_InputEvent = InputSrv->Subscribe(InEventID, this, CB, InputPriority_Mapping);
}
コード例 #9
0
ファイル: Command.cpp プロジェクト: moltenguy1/deusexmachina
void CCommand::BindValue(int Idx, const CData& Val)
{
	n_assert(SQLiteStmt);
	int Error = SQLITE_OK;
	if (Val.IsVoid()) ; //equal to "Error = sqlite3_bind_null(SQLiteStmt, Idx + 1);"
	else if (Val.IsA<int>()) Error = sqlite3_bind_int(SQLiteStmt, Idx + 1, Val);
	else if (Val.IsA<float>()) Error = sqlite3_bind_double(SQLiteStmt, Idx + 1, (double)Val.GetValue<float>());
	else if (Val.IsA<bool>()) Error = sqlite3_bind_int(SQLiteStmt, Idx + 1, (bool)Val ? 1 : 0);
	else if (Val.IsA<nString>())
	{
		// NOTE: the string should be in UTF-8 format.
		Error = sqlite3_bind_text(SQLiteStmt, Idx + 1, Val.GetValuePtr<nString>()->Get(),
			-1, SQLITE_TRANSIENT);
	}
	else if (Val.IsA<CStrID>())
	{
		// NOTE: the string should be in UTF-8 format.
		Error = sqlite3_bind_text(SQLiteStmt, Idx + 1, Val.GetValue<CStrID>().CStr(),
			-1, SQLITE_TRANSIENT);
	}
	else if (Val.IsA<vector4>())
	{
		// NOTE: float4's will be saved as blobs in the DB, since the 
		// float4 may go away at any time, let SQLite make its own copy of the data
		Error = sqlite3_bind_blob(SQLiteStmt, Idx + 1, Val.GetValuePtr<vector4>(),
			sizeof(vector4), SQLITE_TRANSIENT);
	}
	else if (Val.IsA<matrix44>())
	{
		// NOTE: matrix44's will be saved as blobs in the DB, since the 
		// matrix44 may go away at any time, let SQLite make its own copy of the data
		Error = sqlite3_bind_blob(SQLiteStmt, Idx + 1, Val.GetValuePtr<matrix44>(),
			sizeof(matrix44), SQLITE_TRANSIENT);
	}                   
	else if (Val.IsA<CBuffer>())
	{
		const CBuffer* Blob = Val.GetValuePtr<CBuffer>();
		if (!Blob->IsValid()) return;
		Error = sqlite3_bind_blob(SQLiteStmt, Idx + 1, Blob->GetPtr(), Blob->GetSize(), SQLITE_TRANSIENT);
	}
	else n_error("CCommand::ReadResultRow(): invalid attribute type!");
	n_assert(SQLITE_OK == Error);
}
コード例 #10
0
ファイル: compile.c プロジェクト: dancahill/nsp
/* Advance readptr to next matching quote */
static void n_skipquote(nsp_state *N, unsigned short c, cstate *state, unsigned short verbatim)
{
#define __FN__ __FILE__ ":n_skipquote()"
	settrace();
	while (*N->readptr) {
		if (*N->readptr == '\\' && !verbatim) {
			N->readptr++;
		}
		else if (*N->readptr == c) {
			N->readptr++;
			break;
		}
		else if (*N->readptr == '\n') {
			++state->lineno;
		}
		N->readptr++;
		if (!*N->readptr) n_error(N, NE_SYNTAX, __FN__, "unterminated string");
	}
	return;
#undef __FN__
}
コード例 #11
0
ファイル: Shape.cpp プロジェクト: moltenguy1/deusexmachina
// The ODENearCallback for CShape::Collide.
//
// 31-May-05   floh    invert contact normal if necessary, the contact normal
//                     in ODE always points into pShape1, however, we want
//                     the contact normal always to point away from the
//                     "other" object
void CShape::ODENearCallback(void* data, dGeomID o1, dGeomID o2)
{
	CShape* pThis = (CShape*)data;

	// collide geom with sub-space
	if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
	{
		dSpaceCollide2(o1, o2, data, &ODENearCallback);
		return;
	}

	CShape* pShape1 = CShape::GetShapeFromGeom(o1);
	CShape* pShape2 = CShape::GetShapeFromGeom(o2);
	CShape* pOtherShape;
	if (pShape1 == pThis) pOtherShape = pShape2;
	else if (pShape2 == pThis) pOtherShape = pShape1;
	else n_error("No self in collision");

	if (CShape::CollideFilterSet->CheckShape(pOtherShape)) return;

	// do collision detection, only check for one contact
	dContactGeom ODEContact;
	int CurrCollCount;
	if (pShape1 == pThis) CurrCollCount = dCollide(o1, o2, 1, &ODEContact, sizeof(dContactGeom));
	else CurrCollCount = dCollide(o2, o1, 1, &ODEContact, sizeof(dContactGeom));

	CContactPoint ContactPt;
	if (CurrCollCount > 0)
	{
		ContactPt.Position.set(ODEContact.pos[0], ODEContact.pos[1], ODEContact.pos[2]);
		ContactPt.UpVector.set(ODEContact.normal[0], ODEContact.normal[1], ODEContact.normal[2]);
		ContactPt.Material = pOtherShape->GetMaterialType();
		ContactPt.Depth = ODEContact.depth;
		CEntity* pEntity = pOtherShape->GetEntity();
		if (pEntity) ContactPt.EntityID = pEntity->GetUniqueID();
		CRigidBody* pRigidBody = pOtherShape->GetRigidBody();
		if (pRigidBody) ContactPt.RigidBodyID = pRigidBody->GetUniqueID();
		CShape::CollideContacts->Append(ContactPt);
	}
}
コード例 #12
0
ファイル: Command.cpp プロジェクト: moltenguy1/deusexmachina
// This compiles an SQL statement against the provided DB. The SQL
// statement may contain placeholders which should be filled with 
// values using the various BindValue() methods. After values have been
// bound, the statement can be executed using the Execute() method.
// Remember that the SQL statement string must be UTF-8 encoded!
bool CCommand::Compile(const PDatabase& DB)
{
	n_assert(DB.isvalid());
	n_assert(!SQLiteStmt);

	//!!!can clear SQLCmd & use sqlite3_sql to retrieve SQL code!

	const char* pTail = NULL;
	if (sqlite3_prepare_v2(DB->GetSQLiteHandle(), SQLCmd.Get(), -1, &SQLiteStmt, &pTail) != SQLITE_OK)
	{
		SetError(sqlite3_errmsg(DB->GetSQLiteHandle()));
		FAIL;
	}
	n_assert(SQLiteStmt);

	// check if more then one SQL statement was in the string, we don't support that
	n_assert(pTail);
	if (pTail[0])
	{
		n_error("CCommand::Compile(): Only one SQL statement allowed (SQL: %s)\n", SQLCmd.Get());
		Clear();
		FAIL;
	}

	// If VT changed, create an index map to map value table indices to sqlite Result indices
	if (VT.isvalid() && ResultIdxMap.Size() == 0)
	{
		int ColCount = sqlite3_column_count(SQLiteStmt);
		if (ColCount > 0)
		{
			if (VT->GetNumColumns() == 0)
			{
				// SELECT * -> add all table columns, ignore unknown
				VT->BeginAddColumns();
				for (int ResultColIdx = 0; ResultColIdx < ColCount; ResultColIdx++)
				{
					CAttrID ID = DBSrv->FindAttrID(sqlite3_column_name(SQLiteStmt, ResultColIdx));
					if (ID)
					{
						ResultIdxMap.Append(VT->GetNumColumns());
						VT->AddColumn(ID, false);
					}
					else ResultIdxMap.Append(-1);
				}
				VT->EndAddColumns();
			}
			else
			{
				for (int ResultColIdx = 0; ResultColIdx < ColCount; ResultColIdx++)
				{
					//???assert NULL ID & inexistent VT column?
					CAttrID ID = DBSrv->FindAttrID(sqlite3_column_name(SQLiteStmt, ResultColIdx));
					if (ID && VT->HasColumn(ID))
						ResultIdxMap.Append(VT->GetColumnIndex(ID));
					else ResultIdxMap.Append(-1);
				}
			}
		}
	}

	OK;
}
コード例 #13
0
ファイル: Command.cpp プロジェクト: moltenguy1/deusexmachina
// Gather row of Result values from SQLite and add them to the Result CValueTable.
// Note that modification tracking is turned off in the value table, because reading
// from the DB doesn't count as modification.
void CCommand::ReadRow()
{
	n_assert(SQLiteStmt);
	n_assert(VT.isvalid());

	int RowIdx = VT->AddRow();
	int ResultColIdx;
	const int ColCount = sqlite3_data_count(SQLiteStmt);
	for (ResultColIdx = 0; ResultColIdx < ColCount; ResultColIdx++)
	{
		int ResultColType = sqlite3_column_type(SQLiteStmt, ResultColIdx);
		if (SQLITE_NULL == ResultColType) continue;

		int ColIdx = ResultIdxMap[ResultColIdx];
		if (ColIdx < 0) continue;

		const CType* Type = VT->GetColumnValueType(ColIdx);
		if (Type == TInt)
		{
			n_assert(SQLITE_INTEGER == ResultColType);
			int Val = sqlite3_column_int(SQLiteStmt, ResultColIdx);
			VT->Set<int>(ColIdx, RowIdx, Val);
		}
		else if (Type == TFloat)
		{
			n_assert(SQLITE_FLOAT == ResultColType);
			float Val = (float)sqlite3_column_double(SQLiteStmt, ResultColIdx);                        
			VT->Set<float>(ColIdx, RowIdx, Val);
		}
		else if (Type == TBool)
		{
			n_assert(SQLITE_INTEGER == ResultColType);
			int Val = sqlite3_column_int(SQLiteStmt, ResultColIdx);
			VT->Set<bool>(ColIdx, RowIdx, (Val == 1));
		}
		else if (Type == TString)
		{
			n_assert(SQLITE_TEXT == ResultColType);
			nString Val = (LPCSTR)sqlite3_column_text(SQLiteStmt, ResultColIdx);
			VT->Set<nString>(ColIdx, RowIdx, Val);
		}
		else if (Type == TStrID)
		{
			n_assert(SQLITE_TEXT == ResultColType);
			CStrID Val((LPCSTR)sqlite3_column_text(SQLiteStmt, ResultColIdx));
			VT->Set<CStrID>(ColIdx, RowIdx, Val);
		}
		else if (Type == TVector4)
		{
			n_assert(SQLITE_BLOB == ResultColType);
			const void* ptr = sqlite3_column_blob(SQLiteStmt, ResultColIdx);
			uint size = sqlite3_column_bytes(SQLiteStmt, ResultColIdx);                        
			const float* fptr = (const float*)ptr;

			vector4 value;
			if (size < sizeof(vector4))
			{
				n_assert(size == 12); // vector3
				value.set(fptr[0], fptr[1], fptr[2], 0);
			}
			else
			{
				n_assert(size == sizeof(vector4));
				value.set(fptr[0], fptr[1], fptr[2], fptr[3]);
			}

			VT->Set<vector4>(ColIdx, RowIdx, value);
		}
		else if (Type == TMatrix44)
		{
			n_assert(SQLITE_BLOB == ResultColType);
			n_assert(sqlite3_column_bytes(SQLiteStmt, ResultColIdx) == sizeof(matrix44));
			matrix44 mtx(*(const matrix44*)sqlite3_column_blob(SQLiteStmt, ResultColIdx));
			VT->Set<matrix44>(ColIdx, RowIdx, mtx);                                            
		}                   
		else if (Type == TBuffer)
		{
			n_assert(SQLITE_BLOB == ResultColType);
			const void* ptr = sqlite3_column_blob(SQLiteStmt, ResultColIdx);
			int size = sqlite3_column_bytes(SQLiteStmt, ResultColIdx);
			CBuffer Blob(ptr, size);
			VT->Set<CBuffer>(ColIdx, RowIdx, Blob);
		}
		else if (!Type)
		{
			// Variable type column, it supports int, float & string. Bool is represented as int.
			// If ScriptObject wants to save bool to DB & then restore it, this object should
			// implement OnLoad scripted method or smth and convert int values to bool inside.
			switch (ResultColType)
			{
				case SQLITE_INTEGER:
					VT->Set<int>(ColIdx, RowIdx, sqlite3_column_int(SQLiteStmt, ResultColIdx));
					break;
				case SQLITE_FLOAT:
					VT->Set<float>(ColIdx, RowIdx, (float)sqlite3_column_double(SQLiteStmt, ResultColIdx));
					break;
				case SQLITE_TEXT:
					VT->Set<nString>(ColIdx, RowIdx, nString((LPCSTR)sqlite3_column_text(SQLiteStmt, ResultColIdx)));
					break;
				default: n_error("CCommand::ReadResultRow(): invalid attribute type!");
			}
		}
		else n_error("CCommand::ReadResultRow(): invalid attribute type!");
	}
}
コード例 #14
0
// Create a mesh shape object, add it to ODE's collision space, and initialize the mass member.
bool CMeshShape::Attach(dSpaceID SpaceID)
{
    if (!CShape::Attach(SpaceID)) FAIL;

	n_assert(!pVBuffer);
	n_assert(!pIBuffer);

	//!!!REVISIT IT! Now it's copypaste from A. Sysoev's code
	if (pInitMesh)
	{
		// load the vertices and indices
		VertexCount = pInitMesh->GetNumVertices();
		IndexCount  = 3 * pInitMesh->GetNumIndices() - 6;
		VertexWidth = pInitMesh->GetVertexWidth();

		// allocate vertex and index buffer
		int VBSize = pInitMesh->GetVertexBufferByteSize();
		int IBSize = IndexCount * sizeof(int);
		pVBuffer = (float*)n_malloc(VBSize);
		pIBuffer = (int*)n_malloc(IBSize);

		pInitMesh->SetUsage(nMesh2::ReadOnly);
		
		// read vertices and indices
		float *pVBuf = pInitMesh->LockVertices();
		memcpy(pVBuffer,pVBuf,VBSize);
		pInitMesh->UnlockVertices();
	    
		ushort *pIBuf = pInitMesh->LockIndices();

		// copy with conversion TriStrip -> TriList
		pIBuffer[0] = pIBuf[0];
		pIBuffer[1] = pIBuf[1];
		pIBuffer[2] = pIBuf[2];
		for(int i = 3, j = 2; i < pInitMesh->GetNumIndices(); i++)
		{
			pIBuffer[++j] = pIBuffer[j - 2];
			pIBuffer[++j] = pIBuffer[j - 2];
			pIBuffer[++j] = pIBuf[i];
		}
		pInitMesh->UnlockIndices();
	}
	else
	{
		n_assert(FileName.IsValid());

		if (FileName.CheckExtension("nvx2"))
		{
			nNvx2Loader MeshLoader;
			if (!LoadFromFile(MeshLoader)) FAIL;
		}
		else if (FileName.CheckExtension("n3d2"))
		{
			nN3d2Loader MeshLoader;
			if (!LoadFromFile(MeshLoader)) FAIL;
		}
		else
		{
			n_error("CMeshShape: invalid file extension in '%Sphere'", FileName.Get());
			FAIL;
		}
    }

	// fix my collide bits, we don't need to collide against other static and disabled entities
	SetCategoryBits(Static);
	SetCollideBits(Dynamic);

	// create an ODE TriMeshData object from the loaded vertices and indices
	ODETriMeshDataID = dGeomTriMeshDataCreate();

	//!!!CHECK IT!
	// index buffer оказывается должен быть всегда типа int[]
	// хм, эта функция похоже никак не реагирует на передаваемый TriStride,
	// пришлось конвертировать TriStrip в TriList
	dGeomTriMeshDataBuildSingle(ODETriMeshDataID,
								pVBuffer,
								VertexWidth * sizeof(float),
								VertexCount,
								pIBuffer,
								IndexCount,
								3 * sizeof(int));

	ODETriMeshID = dCreateTriMesh(0, ODETriMeshDataID, 0, 0, 0);
	AttachGeom(ODETriMeshID, SpaceID);

	//!!!!!!!FIXME: apply shape mass here!

	OK;
}