void CC3MeshNode::addShadowVolumesForLight( CC3Light* aLight ) { // If I shouldn't cast a shadow, or if I already have a shadow volume, just leave. if ( !shouldCastShadows() || getShadowVolumeForLight( aLight ) ) return; #pragma _NOTE_TODO( "CC3MeshNode::addShadowVolumesForLight( CC3Light* aLight )" ) std::string svName = CC3String::stringWithFormat( "%s-SV-%s", getName().c_str(), aLight->getName().c_str() ); CC3ShadowVolumeMeshNode* sv = CC3ShadowVolumeMeshNode::nodeWithName( svName ); sv->selectShaders(); // Retain data required to build shadow volume mesh retainVertexLocations(); retainVertexIndices(); setShouldCacheFaces( true ); prewarmForShadowVolumes(); // Force heavy face calcs now instead of lazily during drawing. // Set the active camera to infinite depth of field to accomodate infinite shadow volumes getActiveCamera()->setHasInfiniteDepthOfField( true ); aLight->addShadow( sv ); // Add to light before notifying scene a descendant has been added addChild( sv ); // The last thing we do is add the SV to the scene... // ...because we might be doing this on a background thread. //LogTrace(@"Added shadow volume %@ to %@", sv, self); super::addShadowVolumesForLight( aLight ); }
void Plane::draw(std::shared_ptr< FrameEventArgs > args) { auto scene = this->getGameObjectSet().lock()->getOwner(); auto camera = scene->getActiveCamera(); auto cameraTransform = camera->getComponents()->getSingleByClass<Transform>(); this->recalculateForPositionAndTime(cameraTransform->getPosition(), args->getTotalSeconds()); if(this->axesVisible) { drawAxes(50); } Vertex* base = this->vertices.get(); Vertex* v1 = 0; Vertex* v2 = 0; Vertex* v3 = 0; Vertex* v4 = 0; this->setupMaterial(); glBegin(GL_TRIANGLES); for(int xsegment = 0; xsegment < this->segments; ++xsegment) { for(int zsegment = 0; zsegment < this->segments; ++zsegment) { v1 = base + this->vertexIndex(xsegment, zsegment); v2 = base + this->vertexIndex(xsegment + 1, zsegment); v3 = base + this->vertexIndex(xsegment + 1, zsegment + 1); v4 = base + this->vertexIndex(xsegment, zsegment + 1); // These normals are here only to show lighting effect, they're not proper normals glNormal3fv(v1->normal); glTexCoord2fv(v1->texcoord); glVertex3fv(v1->position); glNormal3fv(v2->normal); glTexCoord2fv(v2->texcoord); glVertex3fv(v2->position); glNormal3fv(v4->normal); glTexCoord2fv(v4->texcoord); glVertex3fv(v4->position); glNormal3fv(v2->normal); glTexCoord2fv(v2->texcoord); glVertex3fv(v2->position); glNormal3fv(v3->normal); glTexCoord2fv(v3->texcoord); glVertex3fv(v3->position); glNormal3fv(v4->normal); glTexCoord2fv(v4->texcoord); glVertex3fv(v4->position); } } glEnd(); glDisable(GL_TEXTURE_2D); if(this->normalsVisible) { this->drawNormals(); } }
/** * Returns a 4D directional vector which can be added to each vertex when creating * the shadow volume vertices from the corresponding shadow caster vertices. * * The returned vector is in the local coordinate system of the shadow caster. * * The returned directional vector is a small offset vector in the direction away * from the light. A unit vector in that direction is scaled by both the distance * from the center of the shadow casting node to the camera and the * shadowVolumeVertexOffsetFactor property. Hence, if the shadow caster is farther * away from the camera, the returned value will be larger, to reduce the chance * of Z-fighting between the faces of the shadow volume and the shadow caster. */ CC3Vector4 CC3ShadowVolumeMeshNode::getShadowVolumeVertexOffsetForLightAt( const CC3Vector4& localLightPos ) { CC3Vector scLoc = getShadowCaster()->getLocalContentCenterOfGeometry(); CC3Vector lgtLoc = localLightPos.cc3Vector(); CC3Vector camLoc = getShadowCaster()->getGlobalTransformMatrixInverted()->transformLocation( getActiveCamera()->getGlobalLocation() ); // Get a unit offset vector in the direction away from the light CC3Vector offsetDir = (_light->isDirectionalOnly() ? lgtLoc.negate() : scLoc.difference( lgtLoc )).normalize(); // Get the distance from the shadow caster CoG and the camera, and scale the // unit offset vector by that distance and the shadowVolumeVertexOffsetFactor GLfloat camDist = scLoc.distance( camLoc ); CC3Vector offset = offsetDir.scaleUniform( camDist * _shadowVolumeVertexOffsetFactor ); CC3_TRACE("CC3ShadowVolumeMeshNode nudging vertices by %s", offset.stringfy().c_str()); // Create and return a 4D directional vector from the offset return CC3Vector4().fromDirection(offset); }