bool CActor::checkAttack( CVectorD &pos ) { /* if we're close to an actor then attack them */ CAABBox box; box.setCenter(CVector(_x*0.001f, _y*0.001f, 0.0f)); box.setHalfSize(CVector(5.0f, 5.0f, 1.0f)); CMoveManager::Grid.clearSelection(); CMoveManager::Grid.select(box); CMoveManager::TObstacleGrid::CIterator it; for (it=CMoveManager::Grid.begin(); it!=CMoveManager::Grid.end(); ++it) { CObstacle &other = (*it); // attacks player if close to me CVector d = pos-other.Position; d.z = 0.0f; if (other.Id.getType() == RYZOMID::player && d.norm() <= _AttackDistance) { nlinfo("Actor <%s> attacks player because _AttackDistance = %f and separation = %f", _name.c_str(), _AttackDistance, d.norm()); doFight(other.Id); return true; } } return false; }
/* * render() */ void CPrimChecker::render(CPrimZone *zone, uint8 bits) { if (zone->VPoints.size() < 3) return; string name; if (zone->getPropertyByName("name", name) && Verbose) nlinfo("Rendering CPrimZone '%s'", name.c_str()); // get the bouding box of the CPrimZone CAABBox box; box.setCenter(zone->VPoints[0]); box.setHalfSize(CVector::Null); uint i; for (i=1; i<zone->VPoints.size(); ++i) box.extend(zone->VPoints[i]); sint32 xmin, ymin, xmax, ymax; xmin = (sint32)(floor(box.getMin().x)); ymin = (sint32)(floor(box.getMin().y)); xmax = (sint32)(ceil(box.getMax().x)); ymax = (sint32)(ceil(box.getMax().y)); // Fill grid with points that belong to the CPrimZone sint32 x, y; for (y=ymin; y<=ymax; ++y) for (x=xmin; x<=xmax; ++x) if (zone->contains(CVector((float)x, (float)y, 0.0f))) _Grid.set(x, y, bits); }
void computeRetriever(CCollisionMeshBuild &cmb, CLocalRetriever &lr, CVector &translation, bool useCmbTrivialTranslation) { // set the retriever lr.setType(CLocalRetriever::Interior); // if should use the own cmb bbox, then compute it if (useCmbTrivialTranslation) { translation = cmb.computeTrivialTranslation(); // snap the translation vector to a meter wide grid translation.x = (float)ceil(translation.x); translation.y = (float)ceil(translation.y); translation.z = 0.0f; } uint i, j; for (i=0; i<cmb.Faces.size(); ++i) { CVector normal = ((cmb.Vertices[cmb.Faces[i].V[1]]-cmb.Vertices[cmb.Faces[i].V[0]])^(cmb.Vertices[cmb.Faces[i].V[2]]-cmb.Vertices[cmb.Faces[i].V[0]])).normed(); if (normal.z < 0.0f) { nlwarning("Face %d in cmb (%s) has negative normal! -- face is flipped", i, cmb.Faces[i].Surface == CCollisionFace::InteriorSurfaceFirst ? "interior" : "exterior"); /* std::swap(cmb.Faces[i].V[1], cmb.Faces[i].V[2]); std::swap(cmb.Faces[i].Visibility[1], cmb.Faces[i].Visibility[2]); */ } } // first link faces /* linkMesh(cmb, false); linkMesh(cmb, true); */ vector<string> errors; cmb.link(false, errors); cmb.link(true, errors); if (!errors.empty()) { nlwarning("Edge issues reported !!"); uint i; for (i=0; i<errors.size(); ++i) nlwarning("%s", errors[i].c_str()); nlerror("Can't continue."); } // translate the meshbuild to the local axis cmb.translate(translation); // find the exterior mesh border CExteriorMesh extMesh; buildExteriorMesh(cmb, extMesh); lr.setExteriorMesh(extMesh); // build the surfaces in the local retriever buildSurfaces(cmb, lr); // create the snapping faces and vertices // after the build surfaces because the InternalSurfaceId is filled within buildSurfaces()... buildSnapping(cmb, lr); // lr.computeLoopsAndTips(); lr.findBorderChains(); lr.updateChainIds(); lr.computeTopologies(); lr.unify(); lr.computeCollisionChainQuad(); /* // for (i=0; i<lr.getSurfaces().size(); ++i) lr.dumpSurface(i); */ // linkExteriorToInterior(lr); // compute the bbox of the retriever CAABBox bbox; bool first = true; for (i=0; i<extMesh.getEdges().size(); ++i) if (!first) bbox.extend(extMesh.getEdge(i).Start); else bbox.setCenter(extMesh.getEdge(i).Start), first=false; for (i=0; i<lr.getOrderedChains().size(); ++i) for (j=0; j<lr.getOrderedChain(i).getVertices().size(); ++j) if (!first) bbox.extend(lr.getOrderedChain(i)[j].unpack3f()); else bbox.setCenter(lr.getOrderedChain(i)[j].unpack3f()), first=false; CVector bboxhs = bbox.getHalfSize(); bboxhs.z = 10000.0f; bbox.setHalfSize(bboxhs); lr.setBBox(bbox); }
// *************************************************************************** void NLPACS::CZoneTessellation::build() { sint el; uint i, j; NL3D::CLandscape landscape; landscape.init(); vector<CVector> normals; vector<CVector> vectorCheck; bool useNoHmZones = true; { NL3D::CLandscape landscapeNoHm; landscapeNoHm.init(); // // load the 9 landscape zones // for (i=0; i<_ZoneIds.size(); ++i) { string filename = getZoneNameById(_ZoneIds[i])+ZoneExt; CIFile file(CPath::lookup(filename)); CZone zone; zone.serial(file); file.close(); if (Verbose) nlinfo("use zone %s %d", filename.c_str(), zone.getZoneId()); if (zone.getZoneId() != _ZoneIds[i]) { nlwarning ("Zone %s ID is wrong. Abort.", filename.c_str()); return; } landscape.addZone(zone); if (useNoHmZones) { string filenameNH = getZoneNameById(_ZoneIds[i])+ZoneNHExt; string loadZ = CPath::lookup(filenameNH, false, false); if (!loadZ.empty()) { CIFile fileNH(loadZ); CZone zoneNH; zoneNH.serial(fileNH); fileNH.close(); if (zoneNH.getZoneId() != _ZoneIds[i]) { nlwarning ("Zone %s ID is wrong. Abort.", filenameNH.c_str()); return; } landscapeNoHm.addZone(zoneNH); } else { useNoHmZones = false; } } _ZonePtrs.push_back(landscape.getZone(_ZoneIds[i])); } landscape.setNoiseMode(false); landscape.checkBinds(); if (useNoHmZones) { landscapeNoHm.setNoiseMode(false); landscapeNoHm.checkBinds(); } BestFittingBBox.setCenter(CVector::Null); BestFittingBBox.setHalfSize(CVector::Null); BestFittingBBoxSetuped= false; // Compute best fitting bbox for (i=0; i<_ZoneIds.size(); ++i) { if (_ZoneIds[i] == CentralZoneId) { if(_ZonePtrs[i]->getNumPatchs()>0) { BestFittingBBox = _ZonePtrs[i]->getZoneBB().getAABBox(); BestFittingBBoxSetuped= true; } } } CAABBox enlBBox = BestFittingBBox; enlBBox.setHalfSize(enlBBox.getHalfSize()+CVector(8.0f, 8.0f, 1000.0f)); // Add neighbor patch for (i=0; i<_ZoneIds.size(); ++i) { if (_ZoneIds[i] == CentralZoneId) { for (j=0; (sint)j<_ZonePtrs[i]->getNumPatchs(); ++j) { landscape.excludePatchFromRefineAll(_ZoneIds[i], j, false); if (useNoHmZones) landscapeNoHm.excludePatchFromRefineAll(_ZoneIds[i], j, false); } if (Verbose) nlinfo(" - selected %d/%d patches for zone %d", _ZonePtrs[i]->getNumPatchs(), _ZonePtrs[i]->getNumPatchs(), _ZoneIds[i]); } else { uint nump = 0; for (j=0; (sint)j<_ZonePtrs[i]->getNumPatchs(); ++j) { CAABBox pbox = _ZonePtrs[i]->getPatch(j)->buildBBox(); bool inters = enlBBox.intersect(pbox); if (inters) { landscape.excludePatchFromRefineAll(_ZoneIds[i], j, false); if (useNoHmZones) landscapeNoHm.excludePatchFromRefineAll(_ZoneIds[i], j, false); ++nump; } else { landscape.excludePatchFromRefineAll(_ZoneIds[i], j, true); if (useNoHmZones) landscapeNoHm.excludePatchFromRefineAll(_ZoneIds[i], j, true); } } if (Verbose) nlinfo(" - selected %d/%d patches for zone %d", nump, _ZonePtrs[i]->getNumPatchs(), _ZoneIds[i]); } } // tessellate the landscape, get the leaves (the tessellation faces), and convert them // into surf elements if (Verbose) nlinfo("Compute landscape tessellation"); if (Verbose) nlinfo(" - tessellate landscape"); if (useNoHmZones) { // Before tesselate, verify that the 2 landscape zones have at least the same binds! // Else there will be errors because of not the same tesselation checkSameLandscapeHmBinds(landscape, landscapeNoHm); // Tesselate landscapeNoHm.setThreshold(0.0f); landscapeNoHm.setTileMaxSubdivision(TessellateLevel); landscapeNoHm.refineAll(CVector::Null); landscapeNoHm.averageTesselationVertices(); // get the faces vector<const CTessFace *> leavesNoHm; landscapeNoHm.getTessellationLeaves(leavesNoHm); for (el=0; el<(sint)leavesNoHm.size(); ++el) { const CTessFace *face = leavesNoHm[el]; const CVector *v[3]; // get the vertices of the face v[0] = &(face->VBase->EndPos); v[1] = &(face->VLeft->EndPos); v[2] = &(face->VRight->EndPos); normals.push_back( ((*(v[1])-*(v[0])) ^ (*(v[2])-*(v[0]))).normed() ); vectorCheck.push_back(*(v[0])); vectorCheck.push_back(*(v[1])); vectorCheck.push_back(*(v[2])); } } } // Build the lanscape with heightmap landscape.setThreshold(0.0f); landscape.setTileMaxSubdivision(TessellateLevel); landscape.refineAll(CVector::Null); landscape.averageTesselationVertices(); vector<const CTessFace *> leaves; landscape.getTessellationLeaves(leaves); if (Verbose) { if (useNoHmZones) nlinfo(" - used no height map zones"); nlinfo(" - generated %d leaves", leaves.size()); } // If don't use NoHm zones, build normals and vectorCheck directly from std landscape if (!useNoHmZones) { for (el=0; el<(sint)leaves.size(); ++el) { const CTessFace *face = leaves[el]; const CVector *v[3]; // get the vertices of the face v[0] = &(face->VBase->EndPos); v[1] = &(face->VLeft->EndPos); v[2] = &(face->VRight->EndPos); normals.push_back( ((*(v[1])-*(v[0])) ^ (*(v[2])-*(v[0]))).normed() ); vectorCheck.push_back(*(v[0])); vectorCheck.push_back(*(v[1])); vectorCheck.push_back(*(v[2])); } } // check that there is the same number of faces from landscape with and without heightmap if (normals.size() != leaves.size()) { nlwarning ("ERROR : The heightmaped landscape has not the same number of polygon than the nonheightmaped landscape: %d/%d.", normals.size(), leaves.size()); exit (0); } // generate a vector of vertices and of surf element CHashMap<const CVector *, uint32, CHashPtr<const CVector> > vremap; CHashMap<const CVector *, uint32, CHashPtr<const CVector> >::iterator vremapit; CHashMap<const CTessFace *, CSurfElement *, CHashPtr<const CTessFace> > fremap; CHashMap<const CTessFace *, CSurfElement *, CHashPtr<const CTessFace> >::iterator fremapit; _Vertices.clear(); _Tessellation.resize(leaves.size()); if (Verbose) nlinfo(" - make and remap surface elements"); for (el=0; el<(sint)leaves.size(); ++el) fremap[leaves[el]] = &(_Tessellation[el]); uint check = 0; float dist, maxdist = 0.0f; for (el=0; el<(sint)leaves.size(); ++el) { const CTessFace *face = leaves[el]; const CVector *v[3]; CSurfElement &element = _Tessellation[el]; // setup zone id element.ZoneId = face->Patch->getZone()->getZoneId(); // get the vertices of the face v[0] = &(face->VBase->EndPos); v[1] = &(face->VLeft->EndPos); v[2] = &(face->VRight->EndPos); { CVector vcheck; vcheck = vectorCheck[check++] - *(v[0]); vcheck.z = 0; dist = vcheck.norm(); if (dist > maxdist) maxdist = dist; //nlassert(vcheck.norm() < 0.1f); vcheck = vectorCheck[check++] - *(v[1]); vcheck.z = 0; dist = vcheck.norm(); if (dist > maxdist) maxdist = dist; //nlassert(vcheck.norm() < 0.1f); vcheck = vectorCheck[check++] - *(v[2]); vcheck.z = 0; dist = vcheck.norm(); if (dist > maxdist) maxdist = dist; //nlassert(vcheck.norm() < 0.1f); } //element.Normal = ((*(v[1])-*(v[0])) ^ (*(v[2])-*(v[0]))).normed(); element.Normal = normals[el]; // search the vertices in the map for (i=0; i<3; ++i) { // if doesn't exist, create a new vertex if ((vremapit = vremap.find(v[i])) == vremap.end()) { element.Tri[i] = (uint32)_Vertices.size(); _Vertices.push_back(*(v[i])); vremap.insert(make_pair(v[i], element.Tri[i])); } // else use previous else { element.Tri[i] = vremapit->second; } } // setup the vertices pointer element.Vertices = &_Vertices; CTessFace *edge[3]; edge[0] = face->FBase; edge[1] = face->FRight; edge[2] = face->FLeft; for (i=0; i<3; ++i) { fremapit = fremap.find(edge[i]); element.EdgeLinks[i] = (fremapit != fremap.end() ? fremapit->second : NULL); } } for (el=0; el<(sint)_Tessellation.size(); ++el) { // add the element to the list of valid elements Elements.push_back(&(_Tessellation[el])); } landscape.clear(); }
// *************************************************************************** void IShape::getAABBox(CAABBox &bbox) const { bbox.setCenter(CVector::Null); bbox.setHalfSize(CVector::Null); }
bool CExportNel::mirrorPhysiqueSelection(INode &node, TimeValue tvTime, const std::vector<uint> &vertIn, float threshold) { bool ok; uint i; // no vertices selected? if(vertIn.empty()) return true; // **** Get all the skeleton node std::vector<INode*> skeletonNodes; INode *skelRoot= getSkeletonRootBone(node); if(!skelRoot) return false; getObjectNodes(skeletonNodes, tvTime, skelRoot); // **** Build the Vector (world) part std::vector<CTempSkinVertex> tempVertex; uint vertCount; // Get a pointer on the object's node. ObjectState os = node.EvalWorldState(tvTime); Object *obj = os.obj; // Check if there is an object ok= false; if (obj) { // Object can be converted in triObject ? if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) { // Get a triobject from the node TriObject *tri = (TriObject*)obj->ConvertToType(tvTime, Class_ID(TRIOBJ_CLASS_ID, 0)); if (tri) { // Note that the TriObject should only be deleted // if the pointer to it is not equal to the object // pointer that called ConvertToType() bool deleteIt=false; if (obj != tri) deleteIt = true; // Get the node matrix. TODO: Matrix headhache? /*Matrix3 nodeMatrixMax; CMatrix nodeMatrix; getLocalMatrix (nodeMatrixMax, node, tvTime); convertMatrix (nodeMatrix, nodeMatrixMax);*/ // retrive Position geometry vertCount= tri->NumPoints(); tempVertex.resize(vertCount); for(uint i=0;i<vertCount;i++) { Point3 v= tri->GetPoint(i); tempVertex[i].Pos.set(v.x, v.y, v.z); } // Delete the triObject if we should... if (deleteIt) tri->MaybeAutoDelete(); tri = NULL; // ok! ok= true; } } } if(!ok) return false; // no vertices? abort if(vertCount==0) return true; // **** Mark all Input vertices for(i=0;i<vertIn.size();i++) { nlassert(vertIn[i]<vertCount); tempVertex[vertIn[i]].Input= true; } // **** Build the output vertices std::vector<uint> vertOut; vertOut.reserve(tempVertex.size()); // Build the in bbox CAABBox bbox; bbox.setCenter(tempVertex[vertIn[0]].Pos); for(i=0;i<vertIn.size();i++) { bbox.extend(tempVertex[vertIn[i]].Pos); } bbox.setHalfSize(bbox.getHalfSize()+CVector(threshold, threshold, threshold)); // mirror in X CVector vMin= bbox.getMin(); CVector vMax= bbox.getMax(); vMin.x= -vMin.x; vMax.x= -vMax.x; std::swap(vMin.x, vMax.x); bbox.setMinMax(vMin, vMax); // get all out vertices in the mirrored bbox. for(i=0;i<tempVertex.size();i++) { if(bbox.include(tempVertex[i].Pos)) { vertOut.push_back(i); } } // **** Build the skin information // Get the skin modifier Modifier* skin=getModifier (&node, PHYSIQUE_CLASS_ID); // Found it ? ok= false; if (skin) { // Get a com_skin2 interface IPhysiqueExport *physiqueInterface=(IPhysiqueExport *)skin->GetInterface (I_PHYINTERFACE); // Found com_skin2 ? if (physiqueInterface) { // Get local data IPhyContextExport *localData= physiqueInterface->GetContextInterface(&node); // Found ? if (localData) { // Use rigid export localData->ConvertToRigid (TRUE); // Allow blending localData->AllowBlending (TRUE); // Skinned ok=true; // TODO? nlassert(tempVertex.size()<=(uint)localData->GetNumberVertices()); // For each vertex for (uint vert=0; vert<vertCount; vert++) { // Get a vertex interface IPhyVertexExport *vertexInterface= localData->GetVertexInterface (vert); // Check if it is a rigid vertex or a blended vertex IPhyRigidVertex *rigidInterface=NULL; IPhyBlendedRigidVertex *blendedInterface=NULL; int type=vertexInterface->GetVertexType (); if (type==RIGID_TYPE) { // this is a rigid vertex rigidInterface=(IPhyRigidVertex*)vertexInterface; } else { // It must be a blendable vertex nlassert (type==RIGID_BLENDED_TYPE); blendedInterface=(IPhyBlendedRigidVertex*)vertexInterface; } // Get bones count for this vertex uint boneCount; if (blendedInterface) { // If blenvertex, only one bone boneCount=blendedInterface->GetNumberNodes(); } else { // If rigid vertex, only one bone boneCount=1; } if(boneCount>TEMP_MAX_WEIGHT) boneCount= TEMP_MAX_WEIGHT; // NB: if input 0, won't be mirrored tempVertex[vert].NumWeight= boneCount; for(uint bone=0;bone<boneCount;bone++) { if (blendedInterface) { tempVertex[vert].Bone[bone]= blendedInterface->GetNode(bone); nlassert(tempVertex[vert].Bone[bone]); tempVertex[vert].Weight[bone]= blendedInterface->GetWeight(bone); } else { tempVertex[vert].Bone[bone]= rigidInterface->GetNode(); tempVertex[vert].Weight[bone]= 1; } } // Release vertex interfaces localData->ReleaseVertexInterface (vertexInterface); } } // release context interface physiqueInterface->ReleaseContextInterface(localData); } // Release the interface skin->ReleaseInterface (I_PHYINTERFACE, physiqueInterface); } if(!ok) return false; // **** Real Algo stuff: // For all vertices wanted to be mirrored std::vector<CSortVertex> sortVert; sortVert.reserve(tempVertex.size()); for(i=0;i<vertIn.size();i++) { CTempSkinVertex &svIn= tempVertex[vertIn[i]]; // if it still has no bones set, skip if(svIn.NumWeight==0) continue; // mirror vert to test CVector vertTest= svIn.Pos; vertTest.x*= -1; // get the best vertex sortVert.clear(); // Search for all output vertices if ones match for(uint j=0;j<vertOut.size();j++) { uint dstIdx= vertOut[j]; nlassert(dstIdx<tempVertex.size()); CTempSkinVertex &skinv= tempVertex[dstIdx]; // take only if not an input, and if not already mirrored if(!skinv.Input && !skinv.Mirrored) { CSortVertex sortv; sortv.Index= dstIdx; sortv.SqrDist= (skinv.Pos - vertTest).sqrnorm(); // Finally, take it only if sufficiently near if(sortv.SqrDist <= threshold*threshold) sortVert.push_back(sortv); } } // if some found. if(!sortVert.empty()) { // sort array. std::sort(sortVert.begin(), sortVert.end()); // take the first, mirror setup uint dstIdx= sortVert[0].Index; tempVertex[dstIdx].NumWeight= svIn.NumWeight; for(uint k=0;k<svIn.NumWeight;k++) { tempVertex[dstIdx].Weight[k]= svIn.Weight[k]; tempVertex[dstIdx].Bone[k]= getMirrorBone( skeletonNodes, svIn.Bone[k] ); } // mark as mirrored! tempVertex[dstIdx].Mirrored= true; } } // **** Write the result to the skin. ok= false; if (skin) { // Get a com_skin2 interface IPhysiqueImport *physiqueInterface=(IPhysiqueImport *)skin->GetInterface (I_PHYIMPORT); // Found com_skin2 ? if (physiqueInterface) { // Get local data IPhyContextImport *localData= physiqueInterface->GetContextInterface(&node); // TODO? nlassert(tempVertex.size()<=(uint)localData->GetNumberVertices()); // Found ? if (localData) { // Skinned ok=true; for(uint i=0;i<tempVertex.size();i++) { CTempSkinVertex &sv= tempVertex[i]; // if its a mirrored output vertex if(sv.Mirrored) { IPhyBlendedRigidVertexImport *blendedInterface= NULL; blendedInterface= (IPhyBlendedRigidVertexImport*)localData->SetVertexInterface(i, RIGID_BLENDED_TYPE); if(blendedInterface) { // set the vertex data for(uint bone=0;bone<sv.NumWeight;bone++) { blendedInterface->SetWeightedNode(sv.Bone[bone], sv.Weight[bone], bone==0); } // UI bonus: lock it blendedInterface->LockVertex(TRUE); // release localData->ReleaseVertexInterface(blendedInterface); } } } } // release physiqueInterface->ReleaseContextInterface(localData); } // release skin->ReleaseInterface(I_PHYIMPORT, physiqueInterface); } return ok; }