void STLModule::bounds(const js::Value &args, js::Sink &sink) {
  SmartPointer<js::Value> facets = args.get("stl")->get("facets");
  Rectangle3F bounds;

  unsigned length = facets->length();
  for (unsigned i = 0; i < length; i++) {
    SmartPointer<js::Value> facet = facets->get(i);

    for (unsigned j = 0; j < 3; j++)
      bounds.add(toVector3F(*facet->get(j)));
  }

  sink.beginList();
  append(sink, bounds.getMin());
  append(sink, bounds.getMax());
  sink.endList();
}
Example #2
0
void ParticleScene::DoTick( U32 deltaTime )
{
	for( int i=0; i<buttonArr.Size(); ++i ) {
		ToggleButton* toggle = buttonArr[i]->ToToggleButton();
		if ( toggle && toggle->Down() ) {
			Vector3F pos = { SIZE/2, 0.01f, SIZE/2 };
			Vector3F normal = { 0, 1, 0 };
			//Vector3F dir = { 1, 0, 0 };
			ParticleDef* def = &particleDefArr[i];

			if ( def->spread == ParticleDef::SPREAD_POINT ) {
				engine->particleSystem->EmitPD( *def, pos, normal, deltaTime );
			}
			else {
				Rectangle3F r;
				r.Set( pos.x-0.5f, pos.y, pos.z-0.5f, pos.x+0.5f, pos.y, pos.z+0.5f ); 
				engine->particleSystem->EmitPD( *def, r, normal, deltaTime );
			}
		}
	}
}
Example #3
0
Chit* LumosChitBag::NewItemChit( const grinliz::Vector3F& _pos, GameItem* orphanItem, bool fuzz, bool onGround, int selfDestructTimer )
{
	GLASSERT( !orphanItem->Intrinsic() );
	GLASSERT( !orphanItem->IResourceName().empty() );

	Vector3F pos = _pos;
	if ( fuzz ) {
		pos.x = floorf(pos.x) + random.Uniform();
		pos.z = floorf(pos.z) + random.Uniform();
	}

	Chit* chit = this->NewChit();
	chit->Add( new ItemComponent( orphanItem ));
	chit->Add( new RenderComponent( orphanItem->ResourceName() ));
	chit->Add(new GameMoveComponent());

	if ( onGround ) {
		const ModelResource* res = chit->GetRenderComponent()->MainResource();
		Rectangle3F aabb = res->AABB();
		pos.y = -aabb.min.y;

		if ( aabb.SizeY() < 0.1f ) {
			pos.y += 0.1f;
		}
	}
	chit->SetPosition( pos );
	chit->Add( new HealthComponent());

	if (!selfDestructTimer && orphanItem->keyValues.Has(ISC::selfDestruct)) {
		orphanItem->keyValues.Get("selfDestruct", &selfDestructTimer);
		selfDestructTimer *= 1000;
	}
	if ( selfDestructTimer ) {
		chit->Add( new CountDownScript( selfDestructTimer ));
	}
	return chit;
}
Example #4
0
void DecalMesh::SetPosV( const Vector3F& newPos, const Matrix4& _newRot )
{
	float zRot = _newRot.CalcRotationAroundAxis(2);
	zRot = NormalizeAngleDegrees( zRot );
	
	Matrix4 newRot;
	newRot.SetZRotation( zRot );

	// We don't need to ask the container (the TerrainMesh) where we
	// will be, since the decal is patched to the terrain.
	if ( newPos.x != pos.x || newPos.y != pos.y || newRot != rotation || !InList() )
	{
		pos = newPos;
		rotation = newRot;

		Rectangle3F base;
		base.Set( -size / 2.0f, -size / 2.0f, (TERRAIN_MIN+0.01f),
				  size / 2.0f,  size / 2.0f,  (TERRAIN_MAX-0.01f) );

		if ( InList() )
			ListRemove();

		ComputeTransform();
		CalcAABB( base );
		Lilith3D::Instance()->GetQuadTree()->AddMesh( this );

		// Compute the texture matrix for this decal.
		Matrix4 center, inverse, scale;

		Transform().Invert( &inverse );				// position the texture with the mesh
		center.SetTranslation( 0.5f, 0.5f, 0.5f );	// center the decal
		scale.SetScale( 1.0f / size );		

		texMat = center * scale * inverse;
	}
}
int grinliz::IntersectRayAllAABB(	const Vector3F& origin, const Vector3F& dir,
                                    const Rectangle3F& aabb,
                                    int* inTest,
                                    Vector3F* inIntersect,
                                    int *outTest,
                                    Vector3F* outIntersect )
{
    // Could be more efficient, but looking for simplicity as I write this.
    float t;

    // First check if we hit the box at all, and that establishes in test.
    *inTest = IntersectRayAABB( origin, dir, aabb, inIntersect, &t );
    if ( *inTest == grinliz::REJECT ) {
        *outTest = grinliz::REJECT;
        return grinliz::REJECT;
    }

    // Could get fancy and intersect from the inside. But that's hard, so I'll run
    // the ray out and shoot it backwards.
    float deltaLen = aabb.SizeX() + aabb.SizeY() + aabb.SizeZ();

    Vector3F dirNormal = dir;
    dirNormal.Normalize();
    Vector3F invOrigin = origin + dir*deltaLen;
    Vector3F invDir = -dirNormal;

    *outTest = IntersectRayAABB( invOrigin, invDir, aabb, outIntersect, &t );

    GLASSERT( *outTest != grinliz::INSIDE );	// bad algorith.
    if ( *outTest == grinliz::REJECT ) {
        // some strange floating point thing. Hit a corner. Reject everything.
        *inTest = grinliz::REJECT;
        return grinliz::REJECT;
    }
    return grinliz::INTERSECT;
}
Model* SpaceTree::QueryRay( const Vector3F& _origin, 
							const Vector3F& _direction, 
							int required, int excluded, const Model** ignore,
							HitTestMethod testType,
							Vector3F* intersection ) 
{
	//GLOUTPUT(( "query ray\n" ));
	modelRoot = 0;
	nodesVisited = 0;
	modelsFound = 0;
	requiredFlags = required;
	excludedFlags = excluded | Model::MODEL_HIDDEN_FROM_TREE;
	++queryID;

	Vector3F dummy;
	if ( !intersection ) {
		intersection = &dummy;
	}

	Vector3F dir = _direction;
	dir.Normalize();

	Rectangle3F aabb;
	aabb.min.Set( 0, yMin, 0 );
	aabb.max.Set( Map::SIZE, yMax, Map::SIZE );

	// Where does this ray enter and leave the spaceTree?
	// It enters at 'p0' and leaves at 'p1'
	int p0Test, p1Test;
	Vector3F p0, p1;
	int test = IntersectRayAllAABB( _origin, dir, aabb, &p0Test, &p0, &p1Test, &p1 );
	if ( test != grinliz::INTERSECT ) {
		// Can click outside of AABB pretty commonly, actually.
		return 0;
	}
	Plane planes[6];
	Rectangle3F rect;
	rect.FromPair( p0, p1 );
	Plane::CreatePlanes( rect, planes );

	Model* modelRoot = Query( planes, 6, required, excluded );

	// We now have a batch of models. Are any of them a hit??
	GLASSERT( testType == TEST_HIT_AABB || testType == TEST_TRI );

	float close = FLT_MAX;
	Model* closeModel = 0;
	Vector3F testInt;
	float t;

	for( Model* root=modelRoot; root; root=root->next ) {
		if ( Ignore( root, ignore ) )
			continue;

		//GLOUTPUT(( "Consider: %s\n", root->GetResource()->header.name ));
		int result = grinliz::REJECT;

		if ( testType == TEST_HIT_AABB ) {
			Rectangle3F modelAABB;

			root->CalcHitAABB( &modelAABB );
			result = IntersectRayAABB( p0, dir, modelAABB, &testInt, &t );
		}
		else if ( testType == TEST_TRI ) {
			t = FLT_MAX;
			result = root->IntersectRay( p0, dir, &testInt );

			if ( result == grinliz::INTERSECT ) {
				Vector3F delta = p0 - testInt;
				t = delta.LengthSquared();
				//GLOUTPUT(( "Hit: %s t=%.2f\n", root->GetResource()->header.name, t ));
			}	
		}

		if ( result == grinliz::INTERSECT ) {
			// Ugly little bug: check for t>=0, else could collide with objects
			// that touch the bounding box but are before the ray starts.
			if ( t >= 0.0f && t < close ) {
				closeModel = root;
				*intersection = testInt;
				close = t;
			}
		}
	}
	if ( closeModel ) {
		return closeModel;
	}
	return 0;
}
Example #7
0
Lilith3D::Lilith3D(  U32 msecPerDay, U32 msecStart )
	: timeClock( msecPerDay, msecStart ),
	  pointLightSentinel( InnerCircle<PointLight>::SENTINEL )
{
	int viewPort[4];
	glGetIntegerv(GL_VIEWPORT, viewPort);
	surfaceWidth  = viewPort[2]-viewPort[0];
	surfaceHeight = viewPort[3]-viewPort[1];

	InitShadows();

	instance = this;
	displayPerfData = false;
	infoDisplay = INFO_DEFAULT;
	renderMode = RENDER_FLAT;
	mapSize = 0.0f;
	targetMapSize = 0.0f;

	// Lilith doesn't have a performance meauring system (yet), so
	// use the shader flag as a performance measure for now.
	bool powerful = ShaderManager::Instance()->PowerFragments();
	renderFoliage = powerful;
	renderShadows = true;		// I like the shadows too much to default them off

	Rectangle3F bounds;
	bounds.Set( 0.0f, 0.0f, TERRAIN_MIN,
				(float) MAPSIZE, (float) MAPSIZE, WORLD_CEILING );
	
	terrainMesh = new TerrainMesh();
	quadTree = new QuadTree();	// quadtree depends on the terrain, construct 2nd

	camera.SetCamera( 20.0f, 0.0f, 32.0f, 55.0f, 23.0f );
	//camera.SetCamera( 20.0f, 0.0f, 32.0f, 0.0f, 0.0f, 0.0f );
	sequenceStart = 0;
	sequenceLength = 0;

	// ------- Set up the perspective -----------
	GLfloat ratio;
	ratio = ( float )surfaceWidth / ( float )surfaceHeight;
	glViewport( 0, 0, surfaceWidth, surfaceHeight );

	glMatrixMode( GL_PROJECTION );
	glLoadIdentity( );

	// The further the near plane can be pushed out, the better the resolution 
	// that can be obtained.
	gluPerspective( VIEW_ANGLE, ratio, 1.0f, FAR_PLANE_DISTANCE );

	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity( );

	terrainDecor = new TerrainDecor();

	gravityParticles = new GravParticles();
	rainDropParticles = new RainDropParticles();
	rainSplashParticles = new RainSplashParticles();

	RegisterParticleSystem( gravityParticles );
	RegisterParticleSystem( rainDropParticles );
	RegisterParticleSystem( rainSplashParticles );
	
	GLLOG(( "Sizeof Vertex=%d\n", sizeof( Vertex ) ));
}
Example #8
0
int grinliz::IntersectionRayAABB(	const Ray& ray,
									const Rectangle3F& aabb,
									Rectangle3F* result )
{
	bool hasStart = false;
	bool hasEnd = false;
	Vector3F start, end;

	GLASSERT( Equal( ray.direction.Length(), 1.0f, 0.001f ) );

	if ( aabb.Contains( ray.origin ) )
	{
		hasStart = true;
		start = ray.origin;
	}

	// Check for an intersection with each face. If t>0 and it is a 
	// positive dot then it is an 'end'. If t>0 and it is a negative
	// dot, then it is a 'start'.

	Vector3F at;
	float t;			

	for( int k=0; k<=1; ++k )
	{
		Vector3F originToPlane;
		if ( k == 0 ) {
			// min
			originToPlane.Set(	aabb.min.x - ray.origin.x,
								aabb.min.y - ray.origin.y,
								aabb.min.z - ray.origin.z );
		}
		else {
			// max
			originToPlane.Set(	aabb.max.x - ray.origin.x,
								aabb.max.y - ray.origin.y,
								aabb.max.z - ray.origin.z );
		}

		for ( int i=0; i<3 && !(hasEnd && hasStart); ++i ) {
			int i1 = (i + 1)%3;
			int i2 = (i + 2)%3;

			Vector3F planeNormal = { 0.0f, 0.0f, 0.0f };
			planeNormal.X(i) = ( k == 0 ) ? -1.0f : 1.0f;
			float dot = DotProduct( originToPlane, planeNormal );

			int hit = IntersectRayAAPlane(	ray.origin, ray.direction,
											i, 
											(k==0) ? aabb.min.X(i) : aabb.max.X(i),
											&at, &t );
			if (    hit == INTERSECT 
				 && t > 0.0f
				 && InRange( at.X(i1), aabb.min.X(i1), aabb.max.X(i1) )
				 && InRange( at.X(i2), aabb.min.X(i2), aabb.max.X(i2) ) )
			{
				// We have hit a face of the AABB
				if ( dot > 0.0f ) {
					GLASSERT( !hasEnd );
					hasEnd = true;
					if ( t > ray.length )
						end = ray.origin + ray.direction*t;
					else
						end = at;
				}
				else if ( dot < 0.0f ) {
					GLASSERT( !hasStart );
					hasStart = true;
					if ( t > ray.length ) {
						return REJECT;	// the start never gets to the AABB
					}
					start = at;
				}
			}
		}
	}
	if( !hasStart || !hasEnd ) {
		return REJECT;
	}
	for( int i=0; i<3; ++i ) {
		result->min.X(i) = Min( start.X(i), end.X(i) );
		result->max.X(i) = Max( start.X(i), end.X(i) );
	}
	return INTERSECT;
}