void TrashCanEntity::Update() { transformContext = 0; u8 derp = (u8)(updateCount % 30); float32 periodic = 0.5*sin(3.14159*(float32)derp/30.0); float32 derp2 = periodic + 1.0; oamRotateScale(&oamSub, 0, degreesToAngle(periodic*10-30), floatToFixed(derp2, 8), floatToFixed(derp2, 8) ); if (shouldBeRemoved) return; if (IsTouchedByNearbyPlayer()) { LivingEntity::Damage(gpPlayerEntity->mStats->attack); printf("Trashcan Ouch %d!\n", mStats->health); } Sprite::Update(); }
vect3D Quaternion_toEuler(Quaternion q) { //http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm vect3D v; int32 test = mulf32(q.x, q.y) + mulf32(q.z, q.w); if(test > floatToFixed(0.499f, 12)) { // singularity at north pole v.x = 2 * atan2Lerp(q.x, q.w); v.y = floatToFixed(M_PI / 2.0f, 12); v.z = 0; return v; } if(test < floatToFixed(-0.499f, 12)) { // singularity at south pole v.x = -2 * atan2Lerp(q.x, q.w); v.y = floatToFixed(-M_PI / 2.0f, 12); v.z = 0; return v; } int32 sqx = mulf32(q.x, q.x); int32 sqy = mulf32(q.y, q.y); int32 sqz = mulf32(q.z, q.z); v.x = atan2Lerp(2 * mulf32(q.y, q.w) - 2 * mulf32(q.x, q.z), (1 << 12) - 2 * sqy - 2 * sqz); v.y = asinLerp(2 * test); v.z = atan2Lerp(2 * mulf32(q.x, q.w) - 2 * mulf32(q.y, q.z), (1 << 12) - 2 * sqx - 2 * sqz); return v; }
void TerrainFile::setSize( U32 newSize, bool clear ) { // Make sure the resolution is a power of two. newSize = getNextPow2( newSize ); // if ( clear ) { mLayerMap.setSize( newSize * newSize ); mLayerMap.compact(); dMemset( mLayerMap.address(), 0, mLayerMap.memSize() ); // Initialize the elevation to something above // zero so that we have room to excavate by default. U16 elev = floatToFixed( 512.0f ); mHeightMap.setSize( newSize * newSize ); mHeightMap.compact(); for ( U32 i = 0; i < mHeightMap.size(); i++ ) mHeightMap[i] = elev; } else { // We're resizing here! } mSize = newSize; _buildGridMap(); }
void Tracker::buildUndistO2ITable(Camera* pCam) { int x, y; ARFloat cx, cy, ox, oy; unsigned int fixed; char* cachename = NULL; bool loaded = false; if (loadCachedUndist) { assert(pCam->getFileName() != ""); cachename = new char[strlen(pCam->getFileName().c_str()) + 5]; strcpy(cachename, pCam->getFileName().c_str()); strcat(cachename, ".LUT"); } // we have to take care here when using a memory manager that can not free memory // (usually this lookup table should only be built once - unless we change camera resolution) // if (undistO2ITable) delete[] undistO2ITable; undistO2ITable = new unsigned int[arImXsize * arImYsize]; if (loadCachedUndist) { if (FILE* fp = fopen(cachename, "rb")) { size_t numBytes = fread(undistO2ITable, 1, arImXsize * arImYsize * sizeof(unsigned int), fp); fclose(fp); if (numBytes == arImXsize * arImYsize * sizeof(unsigned int)) loaded = true; } } if (!loaded) { for (x = 0; x < arImXsize; x++) { for (y = 0; y < arImYsize; y++) { arCameraObserv2Ideal_std(pCam, (ARFloat) x, (ARFloat) y, &cx, &cy); floatToFixed(cx, cy, fixed); fixedToFloat(fixed, ox, oy); undistO2ITable[x + y * arImXsize] = fixed; } } if (loadCachedUndist) if (FILE* fp = fopen(cachename, "wb")) { fwrite(undistO2ITable, 1, arImXsize * arImYsize * sizeof(unsigned int), fp); fclose(fp); } } delete[] cachename; }
bool TerrainBlock::buildPolyList(AbstractPolyList* polyList, const Box3F &box, const SphereF&) { if (box.maxExtents.z < -TerrainThickness || box.minExtents.z > fixedToFloat(gridMap[BlockShift]->maxHeight)) return false; // Transform the bounding sphere into the object's coord space. Note that this // not really optimal. Box3F osBox = box; mWorldToObj.mul(osBox); AssertWarn(mObjScale == Point3F::One, "Error, handle the scale transform on the terrain"); // Setup collision state data polyList->setTransform(&getTransform(), getScale()); polyList->setObject(this); S32 xStart = (S32)mFloor( osBox.minExtents.x / mSquareSize ); S32 xEnd = (S32)mCeil ( osBox.maxExtents.x / mSquareSize ); S32 yStart = (S32)mFloor( osBox.minExtents.y / mSquareSize ); S32 yEnd = (S32)mCeil ( osBox.maxExtents.y / mSquareSize ); if (!mTile && xStart<0) xStart = 0; S32 xExt = xEnd - xStart; if (xExt > MaxExtent) xExt = MaxExtent; xEnd = xStart + xExt; mHeightMax = floatToFixed(osBox.maxExtents.z); mHeightMin = (osBox.minExtents.z < 0.0f)? 0.0f: floatToFixed(osBox.minExtents.z); // Index of shared points U32 bp[(MaxExtent + 1) * 2],*vb[2]; vb[0] = &bp[0]; vb[1] = &bp[xExt + 1]; clrbuf(vb[1],xExt + 1); bool emitted = false; for (S32 y = yStart; y < yEnd; y++) { S32 yi = y & BlockMask; swap(vb[0],vb[1]); clrbuf(vb[1],xExt + 1); // for (S32 x = xStart; x < xEnd; x++) { S32 xi = x & BlockMask; GridSquare *gs = findSquare(0, Point2I(xi, yi)); // If we disable repeat, then skip non-primary if(!mTile && (x!=xi || y!=yi)) continue; // holes only in the primary terrain block if (((gs->flags & GridSquare::Empty) && x == xi && y == yi) || gs->minHeight > mHeightMax || gs->maxHeight < mHeightMin) continue; emitted = true; // Add the missing points U32 vi[5]; for (int i = 0; i < 4 ; i++) { S32 dx = i >> 1; S32 dy = dx ^ (i & 1); U32* vp = &vb[dy][x - xStart + dx]; if (*vp == U32_MAX) { Point3F pos; pos.x = (F32)((x + dx) * mSquareSize); pos.y = (F32)((y + dy) * mSquareSize); pos.z = fixedToFloat(getHeight(xi + dx, yi + dy)); *vp = polyList->addPoint(pos); } vi[i] = *vp; } U32* vp = &vi[0]; if (!(gs->flags & GridSquare::Split45)) vi[4] = vi[0], vp++; BaseMatInstance* material = getMaterialInst( xi, yi ); U32 surfaceKey = ((xi << 16) + yi) << 1; polyList->begin(material,surfaceKey); polyList->vertex(vp[0]); polyList->vertex(vp[1]); polyList->vertex(vp[2]); polyList->plane(vp[0],vp[1],vp[2]); polyList->end(); polyList->begin(material,surfaceKey + 1); polyList->vertex(vp[0]); polyList->vertex(vp[2]); polyList->vertex(vp[3]); polyList->plane(vp[0],vp[2],vp[3]); polyList->end(); } } return emitted; }
void TerrainBlock::buildConvex(const Box3F& box,Convex* convex) { sTerrainConvexList.collectGarbage(); // if (box.maxExtents.z < -TerrainThickness || box.minExtents.z > fixedToFloat(gridMap[BlockShift]->maxHeight)) return; // Transform the bounding sphere into the object's coord space. Note that this // not really optimal. Box3F osBox = box; mWorldToObj.mul(osBox); AssertWarn(mObjScale == Point3F(1, 1, 1), "Error, handle the scale transform on the terrain"); S32 xStart = (S32)mFloor( osBox.minExtents.x / mSquareSize ); S32 xEnd = (S32)mCeil ( osBox.maxExtents.x / mSquareSize ); S32 yStart = (S32)mFloor( osBox.minExtents.y / mSquareSize ); S32 yEnd = (S32)mCeil ( osBox.maxExtents.y / mSquareSize ); S32 xExt = xEnd - xStart; if (xExt > MaxExtent) xExt = MaxExtent; mHeightMax = floatToFixed(osBox.maxExtents.z); mHeightMin = (osBox.minExtents.z < 0)? 0: floatToFixed(osBox.minExtents.z); for (S32 y = yStart; y < yEnd; y++) { S32 yi = y & BlockMask; // for (S32 x = xStart; x < xEnd; x++) { S32 xi = x & BlockMask; GridSquare *gs = findSquare(0, Point2I(xi, yi)); // If we disable repeat, then skip non-primary if(!mTile && (x!=xi || y!=yi)) continue; // holes only in the primary terrain block if (((gs->flags & GridSquare::Empty) && x == xi && y == yi) || gs->minHeight > mHeightMax || gs->maxHeight < mHeightMin) continue; U32 sid = (x << 16) + (y & ((1 << 16) - 1)); Convex* cc = 0; // See if the square already exists as part of the working set. CollisionWorkingList& wl = convex->getWorkingList(); for (CollisionWorkingList* itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext) if (itr->mConvex->getType() == TerrainConvexType && static_cast<TerrainConvex*>(itr->mConvex)->squareId == sid) { cc = itr->mConvex; break; } if (cc) continue; // Create a new convex. TerrainConvex* cp = new TerrainConvex; sTerrainConvexList.registerObject(cp); convex->addToWorkingList(cp); cp->halfA = true; cp->square = 0; cp->mObject = this; cp->squareId = sid; cp->material = getMaterial(xi,yi)->index;//RDTODO cp->box.minExtents.set((F32)(x * mSquareSize), (F32)(y * mSquareSize), fixedToFloat(gs->minHeight)); cp->box.maxExtents.x = cp->box.minExtents.x + mSquareSize; cp->box.maxExtents.y = cp->box.minExtents.y + mSquareSize; cp->box.maxExtents.z = fixedToFloat(gs->maxHeight); mObjToWorld.mul(cp->box); // Build points Point3F* pos = cp->point; for (int i = 0; i < 4 ; i++,pos++) { S32 dx = i >> 1; S32 dy = dx ^ (i & 1); pos->x = (F32)((x + dx) * mSquareSize); pos->y = (F32)((y + dy) * mSquareSize); pos->z = fixedToFloat(getHeight(xi + dx, yi + dy)); } // Build normals, then split into two Convex objects if the // square is concave if ((cp->split45 = gs->flags & GridSquare::Split45) == true) { VectorF *vp = cp->point; mCross(vp[0] - vp[1],vp[2] - vp[1],&cp->normal[0]); cp->normal[0].normalize(); mCross(vp[2] - vp[3],vp[0] - vp[3],&cp->normal[1]); cp->normal[1].normalize(); if (mDot(vp[3] - vp[1],cp->normal[0]) > 0) { TerrainConvex* nc = new TerrainConvex(*cp); sTerrainConvexList.registerObject(nc); convex->addToWorkingList(nc); nc->halfA = false; nc->square = cp; cp->square = nc; } } else { VectorF *vp = cp->point; mCross(vp[3] - vp[0],vp[1] - vp[0],&cp->normal[0]); cp->normal[0].normalize(); mCross(vp[1] - vp[2],vp[3] - vp[2],&cp->normal[1]); cp->normal[1].normalize(); if (mDot(vp[2] - vp[0],cp->normal[0]) > 0) { TerrainConvex* nc = new TerrainConvex(*cp); sTerrainConvexList.registerObject(nc); convex->addToWorkingList(nc); nc->halfA = false; nc->square = cp; cp->square = nc; } } } } }
bool TerrainBlock::buildPolyList(PolyListContext, AbstractPolyList* polyList, const Box3F &box, const SphereF&) { PROFILE_SCOPE( TerrainBlock_buildPolyList ); // First check to see if the query misses the // terrain elevation range. const Point3F &terrainPos = getPosition(); if ( box.maxExtents.z - terrainPos.z < -TerrainThickness || box.minExtents.z - terrainPos.z > fixedToFloat( mFile->getMaxHeight() ) ) return false; // Transform the bounding sphere into the object's coord // space. Note that this is really optimal. Box3F osBox = box; mWorldToObj.mul(osBox); AssertWarn(mObjScale == Point3F::One, "Error, handle the scale transform on the terrain"); // Setup collision state data polyList->setTransform(&getTransform(), getScale()); polyList->setObject(this); S32 xStart = (S32)mFloor( osBox.minExtents.x / mSquareSize ); S32 xEnd = (S32)mCeil ( osBox.maxExtents.x / mSquareSize ); S32 yStart = (S32)mFloor( osBox.minExtents.y / mSquareSize ); S32 yEnd = (S32)mCeil ( osBox.maxExtents.y / mSquareSize ); if ( xStart < 0 ) xStart = 0; S32 xExt = xEnd - xStart; if ( xExt > MaxExtent ) xExt = MaxExtent; xEnd = xStart + xExt; U32 heightMax = floatToFixed(osBox.maxExtents.z); U32 heightMin = (osBox.minExtents.z < 0.0f)? 0.0f: floatToFixed(osBox.minExtents.z); // Index of shared points U32 bp[(MaxExtent + 1) * 2],*vb[2]; vb[0] = &bp[0]; vb[1] = &bp[xExt + 1]; clrbuf(vb[1],xExt + 1); const U32 BlockMask = mFile->mSize - 1; bool emitted = false; for (S32 y = yStart; y < yEnd; y++) { S32 yi = y & BlockMask; swap(vb[0],vb[1]); clrbuf(vb[1],xExt + 1); // for (S32 x = xStart; x < xEnd; x++) { S32 xi = x & BlockMask; const TerrainSquare *sq = mFile->findSquare( 0, xi, yi ); if ( x != xi || y != yi ) continue; // holes only in the primary terrain block if ( ( ( sq->flags & TerrainSquare::Empty ) && x == xi && y == yi ) || sq->minHeight > heightMax || sq->maxHeight < heightMin ) continue; emitted = true; // Add the missing points U32 vi[5]; for (int i = 0; i < 4 ; i++) { S32 dx = i >> 1; S32 dy = dx ^ (i & 1); U32* vp = &vb[dy][x - xStart + dx]; if (*vp == U32_MAX) { Point3F pos; pos.x = (F32)((x + dx) * mSquareSize); pos.y = (F32)((y + dy) * mSquareSize); pos.z = fixedToFloat( mFile->getHeight(xi + dx, yi + dy) ); *vp = polyList->addPoint(pos); } vi[i] = *vp; } U32* vp = &vi[0]; if ( !( sq->flags & TerrainSquare::Split45 ) ) vi[4] = vi[0], vp++; BaseMatInstance *material = NULL; //getMaterialInst( xi, yi ); U32 surfaceKey = ((xi << 16) + yi) << 1; polyList->begin(material,surfaceKey); polyList->vertex(vp[0]); polyList->vertex(vp[1]); polyList->vertex(vp[2]); polyList->plane(vp[0],vp[1],vp[2]); polyList->end(); polyList->begin(material,surfaceKey + 1); polyList->vertex(vp[0]); polyList->vertex(vp[2]); polyList->vertex(vp[3]); polyList->plane(vp[0],vp[2],vp[3]); polyList->end(); } } return emitted; }
void TerrainFile::import( const GBitmap &heightMap, F32 heightScale, const Vector<U8> &layerMap, const Vector<String> &materials, bool flipYAxis ) { AssertFatal( heightMap.getWidth() == heightMap.getHeight(), "TerrainFile::import - Height map is not square!" ); AssertFatal( isPow2( heightMap.getWidth() ), "TerrainFile::import - Height map is not power of two!" ); const U32 newSize = heightMap.getWidth(); if ( newSize != mSize ) { mHeightMap.setSize( newSize * newSize ); mHeightMap.compact(); mSize = newSize; } // Convert the height map to heights. U16 *oBits = mHeightMap.address(); if ( heightMap.getFormat() == GFXFormatR5G6B5 ) { const F32 toFixedPoint = ( 1.0f / (F32)U16_MAX ) * floatToFixed( heightScale ); const U16 *iBits = (const U16*)heightMap.getBits(); if ( flipYAxis ) { for ( U32 i = 0; i < mSize * mSize; i++ ) { U16 height = convertBEndianToHost( *iBits ); *oBits = (U16)mCeil( (F32)height * toFixedPoint ); ++oBits; ++iBits; } } else { for(S32 y = mSize - 1; y >= 0; y--) { for(U32 x = 0; x < mSize; x++) { U16 height = convertBEndianToHost( *iBits ); mHeightMap[x + y * mSize] = (U16)mCeil( (F32)height * toFixedPoint ); ++iBits; } } } } else { const F32 toFixedPoint = ( 1.0f / (F32)U8_MAX ) * floatToFixed( heightScale ); const U8 *iBits = heightMap.getBits(); if ( flipYAxis ) { for ( U32 i = 0; i < mSize * mSize; i++ ) { *oBits = (U16)mCeil( ((F32)*iBits) * toFixedPoint ); ++oBits; iBits += heightMap.getBytesPerPixel(); } } else { for(S32 y = mSize - 1; y >= 0; y--) { for(U32 x = 0; x < mSize; x++) { mHeightMap[x + y * mSize] = (U16)mCeil( ((F32)*iBits) * toFixedPoint ); iBits += heightMap.getBytesPerPixel(); } } } } // Copy over the layer map. AssertFatal( layerMap.size() == mHeightMap.size(), "TerrainFile::import - Layer map is the wrong size!" ); mLayerMap = layerMap; mLayerMap.compact(); // Resolve the materials. _resolveMaterials( materials ); // Rebuild the collision grid map. _buildGridMap(); }