void OcclusionBuffer::DrawTriangle(Vector4* vertices) { unsigned clipMask = 0; unsigned andClipMask = 0; bool drawOk = false; Vector3 projected[3]; // Build the clip plane mask for the triangle for (unsigned i = 0; i < 3; ++i) { unsigned vertexClipMask = 0; if (vertices[i].x_ > vertices[i].w_) vertexClipMask |= CLIPMASK_X_POS; if (vertices[i].x_ < -vertices[i].w_) vertexClipMask |= CLIPMASK_X_NEG; if (vertices[i].y_ > vertices[i].w_) vertexClipMask |= CLIPMASK_Y_POS; if (vertices[i].y_ < -vertices[i].w_) vertexClipMask |= CLIPMASK_Y_NEG; if (vertices[i].z_ > vertices[i].w_) vertexClipMask |= CLIPMASK_Z_POS; if (vertices[i].z_ < 0.0f) vertexClipMask |= CLIPMASK_Z_NEG; clipMask |= vertexClipMask; if (!i) andClipMask = vertexClipMask; else andClipMask &= vertexClipMask; } // If triangle is fully behind any clip plane, can reject quickly if (andClipMask) return; // Check if triangle is fully inside if (!clipMask) { projected[0] = ViewportTransform(vertices[0]); projected[1] = ViewportTransform(vertices[1]); projected[2] = ViewportTransform(vertices[2]); if (CheckFacing(projected[0], projected[1], projected[2])) { DrawTriangle2D(projected); drawOk = true; } } else { bool triangles[64]; // Initial triangle triangles[0] = true; unsigned numTriangles = 1; if (clipMask & CLIPMASK_X_POS) ClipVertices(Vector4(-1.0f, 0.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_X_NEG) ClipVertices(Vector4(1.0f, 0.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Y_POS) ClipVertices(Vector4(0.0f, -1.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Y_NEG) ClipVertices(Vector4(0.0f, 1.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Z_POS) ClipVertices(Vector4(0.0f, 0.0f, -1.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Z_NEG) ClipVertices(Vector4(0.0f, 0.0f, 1.0f, 0.0f), vertices, triangles, numTriangles); // Draw each accepted triangle for (unsigned i = 0; i < numTriangles; ++i) { if (triangles[i]) { unsigned index = i * 3; projected[0] = ViewportTransform(vertices[index]); projected[1] = ViewportTransform(vertices[index + 1]); projected[2] = ViewportTransform(vertices[index + 2]); if (CheckFacing(projected[0], projected[1], projected[2])) { DrawTriangle2D(projected); drawOk = true; } } } } if (drawOk) ++numTriangles_; }
void BattleGesture::RenderHints() { glm::mat4 transform = ViewportTransform(_battleView->GetFrame()); vertexbuffer<plain_vertex> shape; shape._mode = GL_LINES; for (UnitCounter* unitMarker : _battleView->GetUnitCounters()) { bounds2f bounds = GetUnitCurrentBounds(unitMarker->_unit); shape._vertices.push_back(plain_vertex(bounds.p11())); shape._vertices.push_back(plain_vertex(bounds.p12())); shape._vertices.push_back(plain_vertex(bounds.p12())); shape._vertices.push_back(plain_vertex(bounds.p22())); shape._vertices.push_back(plain_vertex(bounds.p22())); shape._vertices.push_back(plain_vertex(bounds.p21())); shape._vertices.push_back(plain_vertex(bounds.p21())); shape._vertices.push_back(plain_vertex(bounds.p11())); bounds = GetUnitFutureBounds(unitMarker->_unit); if (!bounds.is_empty()) { shape._vertices.push_back(plain_vertex(bounds.p11())); shape._vertices.push_back(plain_vertex(bounds.p12())); shape._vertices.push_back(plain_vertex(bounds.p12())); shape._vertices.push_back(plain_vertex(bounds.p22())); shape._vertices.push_back(plain_vertex(bounds.p22())); shape._vertices.push_back(plain_vertex(bounds.p21())); shape._vertices.push_back(plain_vertex(bounds.p21())); shape._vertices.push_back(plain_vertex(bounds.p11())); } bounds = GetUnitModifierBounds(unitMarker->_unit); if (!bounds.is_empty()) { shape._vertices.push_back(plain_vertex(bounds.p11())); shape._vertices.push_back(plain_vertex(bounds.p12())); shape._vertices.push_back(plain_vertex(bounds.p12())); shape._vertices.push_back(plain_vertex(bounds.p22())); shape._vertices.push_back(plain_vertex(bounds.p22())); shape._vertices.push_back(plain_vertex(bounds.p21())); shape._vertices.push_back(plain_vertex(bounds.p21())); shape._vertices.push_back(plain_vertex(bounds.p11())); } } renderers::singleton->_plain_renderer->get_uniform<glm::mat4>("transform").set_value(transform); renderers::singleton->_plain_renderer->get_uniform<float>("point_size").set_value(1); renderers::singleton->_plain_renderer->get_uniform<glm::vec4>("color").set_value(glm::vec4(0, 0, 0, 0.2f)); renderers::singleton->_plain_renderer->render(shape); /*PlainLineRenderer renderer; renderer.Reset(); for (UnitCounter* unitMarker : _battleView->GetBattleSimulator()->_unitMarkers) { glm::vec2 center = !unitMarker->_unit->command.path.empty() ? unitMarker->_unit->command.path.back() : unitMarker->_unit->state.center; float facing = unitMarker->_unit->command.facing; glm::vec2 p1 = center + MODIFIER_AREA_RADIUS_MAX * vector2_from_angle(facing - 0.5f * glm::half_pi<float>()); glm::vec2 p2 = center + MODIFIER_AREA_RADIUS_MAX * vector2_from_angle(facing + 0.5f * glm::half_pi<float>()); renderer.AddLine(_battleView->GetPosition(center), _battleView->GetPosition(p1)); renderer.AddLine(_battleView->GetPosition(center), _battleView->GetPosition(p2)); for (int i = 1; i <= 10; ++i) { float a1 = facing + ((i - 1) / 10.0f - 0.5f) * glm::half_pi<float>(); float a2 = facing + (i / 10.0f - 0.5f) * glm::half_pi<float>(); p1 = center + MODIFIER_AREA_RADIUS_MIN * vector2_from_angle(a1); p2 = center + MODIFIER_AREA_RADIUS_MIN * vector2_from_angle(a2); renderer.AddLine(_battleView->GetPosition(p1), _battleView->GetPosition(p2)); p1 = center + MODIFIER_AREA_RADIUS_MAX * vector2_from_angle(a1); p2 = center + MODIFIER_AREA_RADIUS_MAX * vector2_from_angle(a2); renderer.AddLine(_battleView->GetPosition(p1), _battleView->GetPosition(p2)); } } renderer.Draw(_battleView->GetTransform(), glm::vec4(0, 0, 0, 0.2f));*/ }
void GenerateSnapshot (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i; // Get some parameters int iInitialUpdateTime = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("initialUpdate"), 0, -1, 10); int iUpdateTime = pCmdLine->GetAttributeInteger(CONSTLIT("wait")); bool bObjOnly = pCmdLine->GetAttributeBool(CONSTLIT("objOnly")); // Criteria CString sNode = pCmdLine->GetAttribute(CONSTLIT("node")); CString sCriteria = pCmdLine->GetAttribute(CONSTLIT("criteria")); // Number of snapshots int iTotalCount = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); // Output int cxWidth; int cyHeight; if (pCmdLine->FindAttributeInteger(CONSTLIT("size"), &cxWidth)) { cyHeight = cxWidth; } else { cxWidth = 1024; cyHeight = 1024; } // Paint flags DWORD dwPaintFlags = 0; if (pCmdLine->GetAttributeBool(CONSTLIT("noStars"))) dwPaintFlags |= CSystem::VWP_NO_STAR_FIELD; // Output file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output")); if (!sFilespec.IsBlank()) sFilespec = pathStripExtension(sFilespec); // Output image CG32bitImage Output; Output.Create(cxWidth, cyHeight); // Update context SSystemUpdateCtx Ctx; Ctx.bForceEventFiring = true; Ctx.bForcePainted = true; RECT rcViewport; rcViewport.left = 0; rcViewport.top = 0; rcViewport.right = cxWidth; rcViewport.bottom = cyHeight; // Loop over all systems until we find what we're looking for int iLoops = 20; int iNodeIndex = 0; int iSnapshotIndex = 0; CTopologyNode *pNode = Universe.GetTopologyNode(iNodeIndex); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // If this is the node we want, then search CSpaceObject *pTarget; if (sNode.IsBlank() || strEquals(sNode, pNode->GetID())) { printf("Searching %s...\n", pNode->GetSystemName().GetASCIIZPointer()); // Set the POV CSpaceObject *pPOV = pSystem->GetObject(0); Universe.SetPOV(pPOV); pSystem->SetPOVLRS(pPOV); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); // Update for a while for (i = 0; i < iInitialUpdateTime; i++) { Universe.Update(Ctx); Universe.PaintPOV(Output, rcViewport, 0); } // Compose the criteria CSpaceObject::Criteria Criteria; CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria); // Get the list of all objects in the system that match the criteria CSpaceObject::SCriteriaMatchCtx Ctx(Criteria); TArray<CSpaceObject *> Results; for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); if (pObj && pObj->MatchesCriteria(Ctx, Criteria)) Results.Insert(pObj); } // Pick the appropriate object from the list if (Results.GetCount() == 0) pTarget = NULL; else if (Criteria.bNearestOnly || Criteria.bFarthestOnly) pTarget = Ctx.pBestObj; else pTarget = Results[mathRandom(0, Results.GetCount() - 1)]; } else pTarget = NULL; // If we found the target, then output if (pTarget) { Universe.SetPOV(pTarget); // Wait a bit // // NOTE: After we update, pTarget could be invalid (i.e., destroyed) // so we can't use it again. CString sTargetName = pTarget->GetNounPhrase(0); for (i = 0; i < iUpdateTime; i++) { if ((i % 100) == 99) printf("."); Universe.Update(Ctx); Universe.PaintPOV(Output, rcViewport, 0); } if (iUpdateTime >= 99) printf("\n"); // Paint if (bObjOnly) { SViewportPaintCtx Ctx; Ctx.pObj = Universe.GetPOV(); Ctx.XForm = ViewportTransform(Universe.GetPOV()->GetPos(), g_KlicksPerPixel, cxWidth / 2, cyHeight / 2); Ctx.XFormRel = Ctx.XForm; Ctx.fNoRecon = true; Ctx.fNoDockedShips = true; Ctx.fNoSelection = true; Ctx.fNoStarfield = true; CSpaceObject *pPOV = pSystem->GetObject(0); CSpaceObject::Criteria Criteria; CSpaceObject::ParseCriteria(pPOV, sCriteria, &Criteria); // Paint all objects that match the criteria CSpaceObject::SCriteriaMatchCtx CriteriaCtx(Criteria); for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); if (pObj && pObj->MatchesCriteria(CriteriaCtx, Criteria)) { Ctx.pObj = pObj; int xObj; int yObj; Ctx.XForm.Transform(pObj->GetPos(), &xObj, &yObj); pObj->Paint(Output, xObj, yObj, Ctx); } } } else { Universe.PaintPOV(Output, rcViewport, 0); } // Write to file if (!sFilespec.IsBlank()) { CString sBmpFilespec; if (iTotalCount > 100) sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%03d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp")); else if (iTotalCount > 1) sBmpFilespec = pathAddExtensionIfNecessary(strPatternSubst(CONSTLIT("%s%02d"), sFilespec, iSnapshotIndex + 1), CONSTLIT(".bmp")); else sBmpFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp")); CFileWriteStream OutputFile(sBmpFilespec); if (OutputFile.Create() != NOERROR) { printf("ERROR: Unable to create '%s'\n", sBmpFilespec.GetASCIIZPointer()); return; } Output.WriteToWindowsBMP(&OutputFile); OutputFile.Close(); printf("Found %s: Saved to %s\n", sTargetName.GetASCIIZPointer(), sBmpFilespec.GetASCIIZPointer()); } // Otherwise, clipboard else { if (error = Output.CopyToClipboard()) { printf("ERROR: Unable to copy image to clipboard.\n"); return; } printf("Found %s: Copied to clipboard.\n", sTargetName.GetASCIIZPointer()); } // Reset maximum loops iLoops = 20; // Done iSnapshotIndex++; if (iSnapshotIndex >= iTotalCount) break; } // Done with old system Universe.DestroySystem(pSystem); // Loop to the next node do { iNodeIndex = ((iNodeIndex + 1) % Universe.GetTopologyNodeCount()); pNode = Universe.GetTopologyNode(iNodeIndex); } while (pNode == NULL || pNode->IsEndGame()); // If we're back to the first node again, restart if (iNodeIndex == 0) { if (--iLoops > 0) { // Reinitialize Universe.Reinit(); CString sError; if (Universe.InitGame(0, &sError) != NOERROR) { printf("ERROR: %s\n", sError.GetASCIIZPointer()); return; } iNodeIndex = 0; pNode = Universe.GetTopologyNode(iNodeIndex); } else { printf("ERROR: Specified target could not be found.\n"); return; } } } }