void VrmlNodeGroup::render(Viewer *viewer) { if (!haveToRender()) { return; } if (d_viewerObject && isModified()) { viewer->removeObject(d_viewerObject); d_viewerObject = 0; } checkAndRemoveNodes(viewer); if (d_viewerObject) viewer->insertReference(d_viewerObject); else if (d_children.size() > 0) { int i, n = d_children.size(); int nSensors = 0; d_viewerObject = viewer->beginObject(name(), 0, this); // Draw nodes that impact their siblings (DirectionalLights, // TouchSensors, any others? ...) for (i = 0; i < n; ++i) { VrmlNode *kid = d_children[i]; //if ( kid->toLight() ) && ! (kid->toPointLight() || kid->toSpotLight()) ) // kid->render(viewer); //else if (kid && ((kid->toTouchSensor() && kid->toTouchSensor()->isEnabled()) || (kid->toPlaneSensor() && kid->toPlaneSensor()->isEnabled()) || (kid->toCylinderSensor() && kid->toCylinderSensor()->isEnabled()) || (kid->toSphereSensor() && kid->toSphereSensor()->isEnabled()) || (kid->toSpaceSensor() && kid->toSpaceSensor()->isEnabled()))) { if (++nSensors == 1) viewer->setSensitive(this); } } // Do the rest of the children (except the scene-level lights) for (i = 0; i < n; ++i) { if (d_children[i]) { if (!(/*d_children[i]->toLight() ||*/ d_children[i]->toPlaneSensor() || d_children[i]->toCylinderSensor() || d_children[i]->toSpaceSensor() || d_children[i]->toTouchSensor())) d_children[i]->render(viewer); } } // Turn off sensitivity if (nSensors > 0) viewer->setSensitive(0); viewer->endObject(); } clearModified(); }
void VrmlScene::replaceWorld( VrmlMFNode &nodes, VrmlNamespace *ns, Doc *url, Doc *urlLocal ) { theSystem->debug("replaceWorld( url %s )\n", url->url()); delete d_namespace; delete d_url; delete d_urlLocal; d_namespace = ns; d_url = url; d_urlLocal = urlLocal; // Clear bindable stacks. bindableRemoveAll( d_backgroundStack ); bindableRemoveAll( d_fogStack ); bindableRemoveAll( d_navigationInfoStack ); bindableRemoveAll( d_viewpointStack ); // Get rid of current world: pending events, nodes. flushEvents(); d_nodes.removeChildren(); // Do this to set the relative URL d_nodes.addToScene( (VrmlScene *) this, urlDoc()->url() ); // Add the nodes to a Group and put the group in the scene. // This will load EXTERNPROTOs and Inlines. d_nodes.addChildren( nodes ); // Send initial set_binds to bindable nodes double timeNow = theSystem->time(); VrmlSFBool flag(true); VrmlNode *bindable = 0; // compiler warning if (d_backgrounds->size() > 0 && (bindable = d_backgrounds->front()) != 0) bindable->eventIn( timeNow, "set_bind", &flag ); if (d_fogs->size() > 0 && (bindable = d_fogs->front()) != 0) bindable->eventIn( timeNow, "set_bind", &flag ); if (d_navigationInfos->size() > 0 && (bindable = d_navigationInfos->front()) != 0) bindable->eventIn( timeNow, "set_bind", &flag ); if (d_viewpoints->size() > 0 && (bindable = d_viewpoints->front()) != 0) bindable->eventIn( timeNow, "set_bind", &flag ); // Notify anyone interested that the world has changed doCallbacks( REPLACE_WORLD ); setModified(); }
bool VrmlScene::load(const char *url, const char *localCopy) { // Look for '#Viewpoint' syntax. There ought to be a current // scene if this format is used. VrmlSFBool flag(true); if (*url == '#') { VrmlNode *vp = d_namespace ? d_namespace->findNode(url+1) : 0; // spec: ignore if named viewpoint not found if (vp) { vp->eventIn( theSystem->time(), "set_bind", &flag ); setModified(); } return true; } // Try to load a file. Prefer a local copy if available. Doc *tryUrl; if (localCopy) tryUrl = new Doc( localCopy, 0 ); else tryUrl = new Doc( url, d_url); VrmlNamespace *newScope = new VrmlNamespace(); VrmlMFNode *newNodes = readWrl( tryUrl, newScope ); if ( newNodes ) { Doc *sourceUrl = tryUrl, *urlLocal = 0; if (localCopy) { sourceUrl = new Doc( url ); urlLocal = tryUrl; } replaceWorld( *newNodes, newScope, sourceUrl, urlLocal ); delete newNodes; // Look for '#Viewpoint' syntax if ( sourceUrl->urlModifier() ) { VrmlNode *vp = d_namespace->findNode( sourceUrl->urlModifier()+1 ); double timeNow = theSystem->time(); if (vp) vp->eventIn( timeNow, "set_bind", &flag ); } return true; // Success. } delete tryUrl; return false; }
void VrmlNodeGroup::checkAndRemoveNodes(Viewer *viewer) { if (d_childrenToRemove.size()) { viewer->beginObject(name(), 0, this); int i, n = d_childrenToRemove.size(); for (i = 0; i < n; i++) { Viewer::Object child_viewerObject = 0; VrmlNode *kid = d_childrenToRemove[i]; if (kid->toGeometry()) child_viewerObject = kid->toGeometry()->getViewerObject(); else if (kid->toGroup()) child_viewerObject = kid->toGroup()->d_viewerObject; else if (kid->toProto()) child_viewerObject = kid->toProto()->getViewerObject(); else if (kid->toShape()) child_viewerObject = kid->toShape()->getViewerObject(); if (child_viewerObject) viewer->removeChild(child_viewerObject); } viewer->endObject(); } while (d_childrenToRemove.size()) { d_childrenToRemove.removeNode(d_childrenToRemove[0]); } }
void VrmlNodeGroup::accumulateTransform(VrmlNode *parent) { d_parentTransform = parent; int i, n = d_children.size(); for (i = 0; i < n; ++i) { VrmlNode *kid = d_children[i]; if (kid) kid->accumulateTransform(parent); } }
void VrmlScene::sensitiveEvent( void *object, double timeStamp, bool isOver, bool isActive, double *point ) { VrmlNode *n = (VrmlNode *)object; if (n) { VrmlNodeAnchor *a = n->toAnchor(); if ( a ) { // This should really be (isOver && !isActive && n->wasActive) // (ie, button up over the anchor after button down over the anchor) if (isActive && isOver) { a->activate(); //theSystem->inform(""); } else if (isOver) { const char *description = a->description(); const char *url = a->url(); if (description && url) theSystem->inform("%s (%s)", description, url); else if (description || url) theSystem->inform("%s", description ? description : url); //else //theSystem->inform(""); } //else //theSystem->inform(""); } // The parent grouping node is registered for Touch/Drag Sensors else { VrmlNodeGroup *g = n->toGroup(); if (g) { //theSystem->inform(""); g->activate( timeStamp, isOver, isActive, point ); setModified(); } } } //else //theSystem->inform(""); }
// Set the value of one of the node fields. void VrmlNodeGroup::setField(const char *fieldName, const VrmlField &fieldValue) { if TRY_FIELD(bboxCenter, SFVec3f) else if TRY_FIELD(bboxSize, SFVec3f) else if (!strcmp(fieldName, "children")) { if (fieldValue.toMFNode()) { for (int i = 0; i < d_children.size(); i++) { if (d_children[i]) { d_children[i]->decreaseTraversalForce(); d_children[i]->parentList.remove(this); } else { cerr << "VrmlNodeGroup::setField(children): had NULL child" << endl; } } d_children = (VrmlMFNode &)fieldValue; for (int i = 0; i < d_children.size(); i++) { VrmlNode *child = d_children[i]; if (child == NULL) { continue; } child->parentList.push_back(this); if (child->getTraversalForce() > 0) { forceTraversal(false, child->getTraversalForce()); } } } else System::the->error("Invalid type (%s) for %s field of %s node (expected %s).\n", fieldValue.fieldTypeName(), "children", nodeType()->getName(), "MFNode"); } else VrmlNodeChild::setField(fieldName, fieldValue); }
void VrmlNodeTransform::inverseTransform(Viewer *viewer) { VrmlNode *parentTransform = getParentTransform(); if (parentTransform) parentTransform->inverseTransform(viewer); // Build the inverse float trans[3] = { -d_translation.x(), -d_translation.y(), -d_translation.z() }; float rot[4] = { d_rotation.x(), d_rotation.y(), d_rotation.z(), -d_rotation.r() }; // Invert scale (1/x) float scale[3] = { d_scale.x(), d_scale.y(), d_scale.z() }; if (!FPZERO(scale[0])) scale[0] = 1.0f / scale[0]; if (!FPZERO(scale[1])) scale[1] = 1.0f / scale[1]; if (!FPZERO(scale[2])) scale[2] = 1.0f / scale[2]; // Apply transforms (this may need to be broken into separate // calls to perform the ops in reverse order...) viewer->setTransform(d_center.get(), rot, scale, d_scaleOrientation.get(), trans, true); }
void VrmlNodeGroup::addChildren(const VrmlMFNode &children) { int nNow = d_children.size(); int n = children.size(); for (int i = 0; i < n; ++i) { VrmlNode *child = children[i]; if (child == NULL) { continue; } child->parentList.push_back(this); if (child->getTraversalForce() > 0) { forceTraversal(false, child->getTraversalForce()); } VrmlNodeProto *p = 0; // Add legal children and un-instantiated EXTERNPROTOs // Is it legal to add null children nodes? if (child == 0 || child->toChild() || ((p = child->toProto()) != 0 && p->size() == 0)) { d_children.addNode(child); if (child) { child->addToScene(d_scene, d_relative.get()); child->accumulateTransform(d_parentTransform); } } else System::the->error("Error: Attempt to add a %s node as a child of a %s node.\n", child->nodeType()->getName(), nodeType()->getName()); } if (nNow != d_children.size()) { //??eventOut( d_scene->timeNow(), "children_changed", d_children ); setModified(); } }
VrmlNodeBackground *VrmlScene::bindableBackgroundTop() { VrmlNode *b = bindableTop( d_backgroundStack ); return b ? b->toBackground() : 0; }
// // The update method is where the events are processed. It should be // called after each frame is rendered. // bool VrmlScene::update( double timeStamp ) { if (timeStamp <= 0.0) timeStamp = theSystem->time(); VrmlSFTime now( timeStamp ); d_deltaTime = DEFAULT_DELTA; // Update each of the timers. VrmlNodeList::iterator i, end = d_timers->end(); for (i = d_timers->begin(); i != end; ++i) { VrmlNodeTimeSensor *t = (*i)->toTimeSensor(); if (t) t->update( now ); } // Update each of the clips. end = d_audioClips->end(); for (i = d_audioClips->begin(); i != end; ++i) { VrmlNodeAudioClip *c = (*i)->toAudioClip(); if (c) c->update( now ); } // Update each of the scripts. end = d_scripts->end(); for (i = d_scripts->begin(); i != end; ++i) { VrmlNodeScript *s = (*i)->toScript(); if (s) s->update( now ); } // Update each of the movies. end = d_movies->end(); for (i = d_movies->begin(); i != end; ++i) { VrmlNodeMovieTexture *m = (*i)->toMovieTexture(); if (m) m->update( now ); } // Pass along events to their destinations while (d_firstEvent != d_lastEvent && ! d_pendingUrl && ! d_pendingNodes) { Event *e = &d_eventMem[d_firstEvent]; d_firstEvent = (d_firstEvent+1) % MAXEVENTS; // Ensure that the node is in the scene graph VrmlNode *n = e->toNode; if (this != n->scene()) { theSystem->debug("VrmlScene::update: %s::%s is not in the scene graph yet.\n", n->nodeType()->getName(), n->name()); n->addToScene((VrmlScene*)this, urlDoc()->url() ); } n->eventIn(e->timeStamp, e->toEventIn, e->value); // this needs to change if event values are shared... delete e->value; } if (d_pendingNodes) { replaceWorld( *d_pendingNodes, d_pendingScope ); delete d_pendingNodes; d_pendingNodes = 0; d_pendingScope = 0; } else if (d_pendingUrl) { (void) loadUrl( d_pendingUrl, d_pendingParameters ); delete d_pendingUrl; delete d_pendingParameters; d_pendingUrl = 0; d_pendingParameters = 0; } // Signal a redisplay if necessary return isModified(); }
void VrmlNodeTransform::inverseTransform(double *m) { VrmlNode *parentTransform = getParentTransform(); if (strncmp(name(), "StaticCave", 10) == 0) { Midentity(m); } else { if (parentTransform) { parentTransform->inverseTransform(m); } else Midentity(m); } // Invert this transform float rot[4] = { d_rotation.x(), d_rotation.y(), d_rotation.z(), -d_rotation.r() }; float nsrot[4] = { d_scaleOrientation.x(), d_scaleOrientation.y(), d_scaleOrientation.z(), -d_scaleOrientation.r() }; float srot[4] = { d_scaleOrientation.x(), d_scaleOrientation.y(), d_scaleOrientation.z(), d_scaleOrientation.r() }; float trans[3] = { (-d_translation.x()), (-d_translation.y()), (-d_translation.z()) }; float center[3] = { (d_center.x()), (d_center.y()), (d_center.z()) }; float ncenter[3] = { (-d_center.x()), (-d_center.y()), (-d_center.z()) }; double M[16]; Mtrans(M, trans); MM(m, M); Mtrans(M, ncenter); MM(m, M); // Invert scale (1/x) float scale[3] = { d_scale.x(), d_scale.y(), d_scale.z() }; if (!FPZERO(scale[0])) scale[0] = 1.0f / scale[0]; if (!FPZERO(scale[1])) scale[1] = 1.0f / scale[1]; if (!FPZERO(scale[2])) scale[2] = 1.0f / scale[2]; Mrotation(M, rot); MM(m, M); if (!FPEQUAL(scale[0], 1.0) || !FPEQUAL(scale[1], 1.0) || !FPEQUAL(scale[2], 1.0)) { //fprintf(stderr, "invTr: scale\n"); if (!FPZERO(srot[3])) { //fprintf(stderr, "invTr: rot\n"); Mrotation(M, nsrot); MM(m, M); Mscale(M, scale); MM(m, M); Mrotation(M, srot); MM(m, M); } else { Mscale(M, scale); MM(m, M); } } Mtrans(M, center); MM(m, M); }
Viewer::Object VrmlNodeILineSet::insertGeometry(Viewer *viewer) { Viewer::Object obj = 0; if (d_coord.get()) { VrmlMFVec3f &coord = d_coord.get()->toCoordinate()->coordinate(); int nvert = coord.size(); int ncoord = nvert; float *color = NULL; int nci = 0, *ci = NULL; int *localci = NULL; int *cdi = NULL, *localcdi = NULL; if (d_coordIndex.size() > 0) { cdi = &d_coordIndex[0]; ncoord = d_coordIndex.size(); } else { localcdi = new int[ncoord]; cdi = localcdi; for (int i = 0; i < ncoord; i++) { cdi[i] = i; } } // check #colors is consistent with colorPerVtx, colorIndex... int componentsPerColor = 3; int cSize = -1; VrmlNode *colorNode = d_color.get(); if (colorNode && (strcmp(colorNode->nodeType()->getName(), "ColorRGBA") == 0)) { VrmlMFColorRGBA &c = d_color.get()->toColorRGBA()->color(); color = &c[0][0]; cSize = c.size(); componentsPerColor = 4; } else if (d_color.get()) { VrmlMFColor &c = d_color.get()->toColor()->color(); color = &c[0][0]; cSize = c.size(); } if (cSize > -1) { nci = d_colorIndex.size(); if (nci) { ci = d_colorIndex.get(); } else { nci = cSize; localci = new int[cSize]; ci = localci; for (int i = 0; i < nci; i++) { ci[i] = i; } } } obj = viewer->insertLineSet(nvert, &coord[0][0], ncoord, cdi, d_colorPerVertex.get(), color, componentsPerColor, nci, ci, name()); delete[] localcdi; delete[] localci; } if (d_color.get()) d_color.get()->clearModified(); if (d_coord.get()) d_coord.get()->clearModified(); return obj; }
void VrmlNodeGroup::activate(double time, bool isOver, bool isActive, double *p, double *M) { int i, n = d_children.size(); for (i = 0; i < n; ++i) { VrmlNode *kid = d_children[i]; if (kid == NULL) continue; if (kid->toTouchSensor() && kid->toTouchSensor()->isEnabled()) { kid->toTouchSensor()->activate(time, isOver, isActive, p); break; } else if (kid->toPlaneSensor() && kid->toPlaneSensor()->isEnabled()) { kid->toPlaneSensor()->activate(time, isActive, p); break; } else if (kid->toSpaceSensor() && kid->toSpaceSensor()->isEnabled()) { kid->toSpaceSensor()->activate(time, isActive, p, M); break; } else if (kid->toSphereSensor() && kid->toSphereSensor()->isEnabled()) { kid->toSphereSensor()->activate(time, isActive, p); break; } else if (kid->toCylinderSensor() && kid->toCylinderSensor()->isEnabled()) { kid->toCylinderSensor()->activate(time, isActive, p); break; } } }
VrmlNodeFog *VrmlScene::bindableFogTop() { VrmlNode *f = bindableTop( d_fogStack ); return f ? f->toFog() : 0; }
void VrmlNodeProto::instantiate() { System::the->debug("%s::%s instantiate\n", d_nodeType->getName(), name()); if (!d_nodes) { VrmlMFNode *protoNodes = d_nodeType->getImplementationNodes(); int nNodes = protoNodes ? protoNodes->size() : 0; int i; d_scope = new VrmlNamespace(); // Clear all flags - encountering a set flag during cloning // indicates a USEd node, which should be referenced rather // than cloned. for (i = 0; i < nNodes; ++i) protoNodes->get(i)->clearFlags(); // Clone nodes // Those squeamish about broken encapsulations shouldn't look... d_nodes = new VrmlMFNode(nNodes, 0); VrmlNode **clone = d_nodes->get(); for (i = 0; i < nNodes; ++i) { clone[i] = protoNodes->get(i)->clone(d_scope)->reference(); clone[i]->parentList.push_back(this); if (clone[i]->getTraversalForce() > 0) { forceTraversal(false, clone[i]->getTraversalForce()); } } // Copy internal (to the PROTO implementation) ROUTEs. for (i = 0; i < nNodes; ++i) protoNodes->get(i)->copyRoutes(d_scope); // Collect eventIns coming from outside the PROTO. // A list of eventIns along with their maps to local // nodes/eventIns is constructed for each instance. VrmlNodeType::FieldList &eventIns = d_nodeType->eventIns(); VrmlNodeType::FieldList::iterator ev; VrmlNodeType::ISMap *ismap; VrmlNodeType::ISMap::const_iterator j; for (ev = eventIns.begin(); ev != eventIns.end(); ++ev) { EventDispatch *ed = new EventDispatch; char *eventName = (*ev)->name; ed->name = new char[strlen(eventName) + 1]; strcpy(ed->name, eventName); ismap = &(*ev)->thisIS; d_eventDispatch.push_front(ed); for (j = ismap->begin(); j != ismap->end(); ++j) { VrmlNodeType::NodeFieldRec *nf = new VrmlNodeType::NodeFieldRec; nf->node = d_scope->findNode((*j)->node->name()); nf->fieldName = new char[strlen((*j)->fieldName) + 1]; strcpy(nf->fieldName, (*j)->fieldName); ed->ismap.push_front(nf); } } // Distribute eventOuts. Each eventOut ROUTE is added // directly to the local nodes that have IS'd the PROTO // eventOut. VrmlNodeType::FieldList &eventOuts = d_nodeType->eventOuts(); for (Route *r = d_routes; r; r = r->next()) for (ev = eventOuts.begin(); ev != eventOuts.end(); ++ev) if (strcmp((*ev)->name, r->fromEventOut()) == 0) { ismap = &(*ev)->thisIS; for (j = ismap->begin(); j != ismap->end(); ++j) { VrmlNode *n = d_scope->findNode((*j)->node->name()); if (n) n->addRoute((*j)->fieldName, r->toNode(), r->toEventIn()); } } // Set IS'd field values in the implementation nodes to // the values specified in the instantiation. list<NameValueRec *>::iterator ifld; for (ifld = d_fields.begin(); ifld != d_fields.end(); ++ifld) { VrmlField *value = (*ifld)->value; #ifdef DEBUG cerr << d_nodeType->getName() << "::" << name() << " setting IS field " << (*ifld)->name; if (value) cerr << " to " << *value << endl; else cerr << " to null\n"; #endif if (!value) continue; if ((ismap = d_nodeType->getFieldISMap((*ifld)->name)) != 0) { for (j = ismap->begin(); j != ismap->end(); ++j) { // cerr << (*j)->node->name() << endl; VrmlNode *n = d_scope->findNode((*j)->node->name()); #ifdef DEBUG cerr << " on " << n->name() << "::" << (*j)->fieldName << endl; #endif if (n) n->setField((*j)->fieldName, *value); } } } } d_instantiated = true; }
VrmlNodeNavigationInfo *VrmlScene::bindableNavigationInfoTop() { VrmlNode *n = bindableTop( d_navigationInfoStack ); return n ? n->toNavigationInfo() : 0; }
void ModelNodeSetImpl::extractChildNodes (JointNodeSetPtr jointNodeSet, MFNode& childNodes, const ProtoIdSet acceptableProtoIds, const Matrix44& T) { for(size_t i = 0; i < childNodes.size(); i++){ VrmlNode* childNode = childNodes[i].get(); const Matrix44* pT; if(childNode->isCategoryOf(GROUPING_NODE)){ VrmlGroup* groupNode = static_cast<VrmlGroup*>(childNode); VrmlTransform* transformNode = dynamic_cast<VrmlTransform*>(groupNode); Matrix44 T2; if( transformNode ){ Matrix44 Tlocal; calcTransformMatrix(transformNode, Tlocal); T2 = T * Tlocal; pT = &T2; } else { pT = &T; } extractChildNodes(jointNodeSet, groupNode->getChildren(), acceptableProtoIds, *pT); } else if(childNode->isCategoryOf(LIGHT_NODE)){ jointNodeSet->lightNodes.push_back(std::make_pair(T,childNode)); } else if(childNode->isCategoryOf(PROTO_INSTANCE_NODE)){ VrmlProtoInstance* protoInstance = static_cast<VrmlProtoInstance*>(childNode); int id = PROTO_UNDEFINED; bool doTraverseChildren = false; ProtoIdSet acceptableChildProtoIds(acceptableProtoIds); const string& protoName = protoInstance->proto->protoName; ProtoNameToInfoMap::iterator p = protoNameToInfoMap.find(protoName); if(p == protoNameToInfoMap.end()){ doTraverseChildren = true; } else { id = p->second.id; if(!acceptableProtoIds.test(id)){ throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); } } messageIndent += 2; switch(id){ case PROTO_JOINT: if(T != Matrix44::Identity()) throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); jointNodeSet->childJointNodeSets.push_back(addJointNodeSet(protoInstance)); break; case PROTO_SENSOR: if(T != Matrix44::Identity()) throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); jointNodeSet->sensorNodes.push_back(protoInstance); putMessage(protoName + protoInstance->defName); break; case PROTO_HARDWARECOMPONENT: if(T != Matrix44::Identity()) throw ModelNodeSet::Exception(protoName + " node is not in a correct place."); jointNodeSet->hwcNodes.push_back(protoInstance); putMessage(protoName + protoInstance->defName); break; case PROTO_SEGMENT: { jointNodeSet->segmentNodes.push_back(protoInstance); jointNodeSet->transforms.push_back(T); putMessage(string("Segment node ") + protoInstance->defName); doTraverseChildren = true; acceptableChildProtoIds.reset(); acceptableChildProtoIds.set(PROTO_SENSOR); } break; default: break; } if(doTraverseChildren){ if (protoInstance->fields.count("children")){ MFNode& childNodes = protoInstance->fields["children"].mfNode(); extractChildNodes(jointNodeSet, childNodes, acceptableChildProtoIds, T); } } messageIndent -= 2; } } }
VrmlNodeViewpoint *VrmlScene::bindableViewpointTop() { VrmlNode *t = bindableTop( d_viewpointStack ); return t ? t->toViewpoint() : 0; }