//---------------------------------------------------------------------------- void ReflectionsAndShadows::CreatePlanarShadow () { Light* projector = new0 Light(Light::LT_POINT); projector->Position = APoint(30.0f, -50.0f, 80.0f); LightNode* projectorNode = new0 LightNode(projector); mScene->AttachChild(projectorNode); mPSEffect = new0 PlanarShadowEffect(1, mBiped); Float4 shadowColor(0.0f, 0.0f, 0.0f, 0.5f); mPSEffect->SetPlane(0, mPlane0); mPSEffect->SetProjector(0, projector); mPSEffect->SetShadowColor(0, shadowColor); }
//---------------------------------------------------------------------------- void Castle::CreateLights () { mDLight = new0 Light(Light::LT_DIRECTIONAL); mDLight->Ambient = Float4(1.0f, 1.0f, 1.0f, 1.0f); mDLight->Diffuse = Float4(1.0f, 1.0f, 1.0f, 1.0f); mDLight->Specular = Float4(1.0f, 1.0f, 1.0f, 1.0f); LightNode* lightNode = new0 LightNode(mDLight); lightNode->LocalTransform.SetTranslate(APoint(1628.448730f, -51.877197f, 0.0f)); lightNode->LocalTransform.SetRotate(HMatrix(AVector(-1.0f, 0.0f, 0.0f), Mathf::HALF_PI)); mDLightRoot = new0 Node(); mDLightRoot->LocalTransform.SetTranslate(APoint(-1824.998657f, -1531.269775f, 3886.592773f)); mDLightRoot->LocalTransform.SetRotate(HMatrix(AVector(-0.494124f, 0.325880f, 0.806005f), 1.371538f)); mDLightRoot->AttachChild(lightNode); mDLightRoot->Update(); }
void NodeGraphDisplay::draw(GlInterface &gl) { if(visible && isolateViewport(gl)) { //Draw background drawBackground(gl); //Draw graph behind nodes drawGraph(gl); //Draw nodes drawChildren(gl); transformGl(gl); //Draw selection rect if(selectionRect.space != TSpace::INVALID) { std::vector<TVertex> points; points.reserve(5); Color col(0.0f, 1.0f, 1.0f, 1.0f); APoint p1 = selectionRect.pos, p2 = p1 + selectionRect.size; points.push_back(TVertex(p1, col)); points.push_back(TVertex(APoint(p1.x, p2.y), col)); points.push_back(TVertex(p2, col)); points.push_back(TVertex(APoint(p2.x, p1.y), col)); points.push_back(TVertex(p1, col)); //Draw rect gl.drawShape(GL_LINE_STRIP, points); } untransformGl(gl); restoreViewport(gl); } }
void GraphDisplay::drawBackground(GlInterface &gl) { Display::drawBackground(gl); //Draw standard scale as the background GPoint v_origin = getVisibleOrigin(gl); GVec v_size = getVisibleSize(gl); GPoint prev_lines( floor(v_origin.x/standardUnitSize.x)*standardUnitSize.x, floor(v_origin.y/standardUnitSize.y)*standardUnitSize.y); APoint start_lines = graphToAbsolutePoint(prev_lines + standardUnitSize); AVec line_step = graphToAbsoluteVec(standardUnitSize); //Vertical lines (x dimension) --> GREY gl.setColor(Color(0.4f, 0.4f, 0.4f, 1.0f)); for(float a_x = start_lines.x; a_x < v_size.x; a_x += line_step.x) gl.drawLine(APoint(a_x, 0.0f), APoint(a_x, size.y)); //Horizontal lines (y dimension) --> GREY gl.setColor(Color(0.4f, 0.4f, 0.4f, 1.0f)); for(float a_y = start_lines.y; a_y < v_size.y; a_y += line_step.y) gl.drawLine(APoint(0.0f, a_y), APoint(size.x, a_y)); }
//---------------------------------------------------------------------------- void WaterDropFormation::CreateWaterRoot () { mWaterRoot = new0 Node(); mTrnNode->AttachChild(mWaterRoot); mWaterRoot->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 0.1f)); mWaterRoot->LocalTransform.SetUniformScale(8.0f); // The texture for the water objects. This will be attached to children // of mWaterRoot when the need arises. mWaterEffect = new0 Texture2DEffect(); std::string path = Environment::GetPathR("WaterWithAlpha.wmtf"); mWaterTexture = Texture2D::LoadWMTF(path); // The texture has an alpha channel of 1/2. mWaterEffect->GetAlphaState(0, 0)->BlendEnabled = true; }
//---------------------------------------------------------------------------- void FoucaultPendulum::PhysicsTick () { mModule.Update(); // Update the pendulum mechanism. The pendulum rod is attached at // (x,y,z) = (0,0,16). The update here has the 16 hard-coded. mPendulum->LocalTransform.SetRotate(mModule.GetOrientation()); mPendulum->Update(); // Draw only the active quantity of pendulum points for the initial // portion of the simulation. Once all points are activated, then all // are drawn. mPath->SetNumPoints(mPath->GetNumPoints() + 1); // Add the new pendulum point to the point system. The initial color is // white. All previously known points have their colors decremented to // cause them to become dim over time. APoint proj = mPendulum->WorldTransform*APoint(0.0f, 0.0f, -16.0f); proj[2] = 0.0f; VertexBufferAccessor vba(mPath); vba.Position<Float3>(mNextPoint) = proj; vba.Color<Float3>(0, mNextPoint) = Float3(1.0f, 1.0f, 1.0f); int i; for (i = 0; i < mNextPoint; ++i) { Float3& color = vba.Color<Float3>(0, i); color[0] -= mColorDiff; color[1] -= mColorDiff; color[2] -= mColorDiff; } for (i = mNextPoint+1; i < vba.GetNumVertices(); ++i) { Float3& color = vba.Color<Float3>(0, i); color[0] -= mColorDiff; color[1] -= mColorDiff; color[2] -= mColorDiff; } // Prepare for the next pendulum point. if (++mNextPoint == vba.GetNumVertices()) { mNextPoint = 0; } mRenderer->Update(mPath->GetVertexBuffer()); }
//---------------------------------------------------------------------------- void IntersectTriangleCylinder::CreateScene () { mScene = new0 Node(); mCullState = new0 CullState(); mCullState->Enabled = false; mRenderer->SetOverrideCullState(mCullState); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(3, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Vector3f>(0) = (const Vector3f&)mTriangleMVertex0; vba.Color<Float3>(0, 0) = Float3(0.0f, 0.0f, 1.0f); vba.Position<Vector3f>(1) = (const Vector3f&)mTriangleMVertex1; vba.Color<Float3>(0, 1) = Float3(0.0f, 0.0f, 1.0f); vba.Position<Vector3f>(2) = (const Vector3f&)mTriangleMVertex2; vba.Color<Float3>(0, 2) = Float3(0.0f, 0.0f, 1.0f); IndexBuffer* ibuffer = new0 IndexBuffer(3, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; mTMesh = new0 TriMesh(vformat, vbuffer, ibuffer); mTMesh->SetEffectInstance( VertexColor3Effect::CreateUniqueInstance()); mTMesh->LocalTransform.SetTranslate(APoint(0.0f, 1.125f, 0.0f)); mCMesh = StandardMesh(vformat).Cylinder(8, 16, mCylinderRadius, mCylinderHeight, false); vba.ApplyTo(mCMesh); for (int i = 0; i < vba.GetNumVertices(); ++i) { vba.Color<Float3>(0, i) = Float3(1.0f, 0.0f, 0.0f); } mCMesh->SetEffectInstance( VertexColor3Effect::CreateUniqueInstance()); mScene->AttachChild(mTMesh); mScene->AttachChild(mCMesh); }
int main() { // initialize the graphics system int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); // move a point across the screen Point APoint(100, 50); // Initial X, Y at 100, 50 APoint.Show(); // APoint turns itself on getch(); // Wait for keypress APoint.MoveTo(300, 150); // APoint moves to 300,150 getch(); // Wait for keypress APoint.Hide(); // APoint turns itself off getch(); // Wait for keypress closegraph(); // Restore original screen return 0; }
void NodeGraphDisplay::onDrag(APoint m_pos, AVec d_pos) { if(valid(Mouse::getButtonStates() & NODEGRAPH_MOVE_OFFSET_BTN)) { moveViewOffset(-absoluteToVirtualVec(d_pos)); } else if(selectionRect.space != TSpace::INVALID) { //Adjust selectionRect if(selectionPivot.x > m_pos.x) { selectionRect.pos.x = m_pos.x; selectionRect.size.x = selectionPivot.x - m_pos.x; } else { selectionRect.pos.x = selectionPivot.x; selectionRect.size.x = m_pos.x - selectionPivot.x; } if(selectionPivot.y > m_pos.y) { selectionRect.pos.y = m_pos.y; selectionRect.size.y = selectionPivot.y - m_pos.y; } else { selectionRect.pos.y = selectionPivot.y; selectionRect.size.y = m_pos.y - selectionPivot.y; } //Clamp selection rect within absolute bounds Rect bounds = Rect(APoint(0, 0), size); selectionRect = Rect::findIntersection(selectionRect, absoluteToVirtualRect(bounds)); if(!stickySelect()) clearSelected(); for(auto c : nodeControls) { if((c->selected && stickySelect()) || Rect::intersects(c->getRect(), selectionRect)) selectNode(c, false); } } }
void MenuBarButton::drawBackground(GlInterface &gl) { //Recede border for padding gl.setColor(bgStateColors[cState]); gl.drawRect(APoint(PADDING), size - PADDING*2.0f); if(inFocus) { AVec offset = PADDING + AVec(0.5f, 0.5f); gl.setColor(Color(1.0f, 0.0f, 0.0f, 1.0f)); gl.drawLine(offset, APoint(offset.x, size.y - offset.y)); gl.drawLine(APoint(offset.x, size.y - offset.y), APoint(size.x - offset.x, size.y - offset.y)); gl.drawLine(APoint(size.x - offset.x, size.y - offset.y), APoint(size.x - offset.x, offset.y)); gl.drawLine(APoint(size.x - offset.x, offset.y), offset); } }
APoint NodeControl::getConnectorPoint(NodeConnectionType io_type) { AVec half_size = size*(1.0f/2.0f); switch(io_type) { case NCType::DATA_INPUT: return pos + AVec(0.0f, half_size.y); case NCType::DATA_OUTPUT: return pos + AVec(size.x, half_size.y); case NCType::INFO_INPUT: return pos + AVec(half_size.x, 0.0f); case NCType::INFO_OUTPUT: return pos + AVec(half_size.x, size.y); default: return APoint(0, 0); } }
void NodeControl::initControl() { setSize(getNodeSize()); if(node) { std::vector<GuiElement*> children; //Label (node name) nodeName = new Label(this, APoint(), DEFAULT_STATE_FLOAT, node->getName(), 12); nodeName->centerAround(size*(1.0f/2.0f)); children.push_back(nodeName); bool hasConnector[static_cast<unsigned int>(NCType::COUNT)] {false}; std::vector<NodeConnector*> c = node->getConnectors(); for(auto con : c) hasConnector[toIndex(con->ioType)] = true; //Create connectors for(unsigned int i = 0; i < toIndex(NCType::COUNT); i++) { if(hasConnector[i]) { connectorControls[i] = new NodeConnectorControl(this, static_cast<NCType>(i)); //children.push_back(connectorControls[i]); } } //init(&children, nullptr); } else { std::cout << "ERRORRRR --> NodeControl's node is null!\n"; } //TODO: Separate this for each node type setBgStateColor(Color(0.2f, 0.2f, 0.2f, 1.0f), CS::NONE); setBgStateColor(Color(0.3f, 0.3f, 0.3f, 1.0f), CS::HOVERING); setBgStateColor(Color(0.05f, 0.05f, 0.05f, 1.0f), CS::CLICKING); setBgStateColor(Color(0.05f, 0.05f, 0.05f, 1.0f), CS::DRAGGING); }
//---------------------------------------------------------------------------- void PlanarShadows::CreatePlanarShadow () { #if 1 Light* projector = new0 Light(Light::LT_POINT); projector->Position = APoint(152.0f, -55.0f, 53.0f); #else Light* projector = new0 Light(Light::LT_DIRECTIONAL); projector->DVector = AVector(0.25f, 0.25f, -1.0f); projector->DVector.Normalize(); #endif mProjectorNode = new0 LightNode(projector); mScene->AttachChild(mProjectorNode); mPSEffect = new0 PlanarShadowEffect(2, mBiped); Float4 shadowColor(0.0f, 0.0f, 0.0f, 0.5f); mPSEffect->SetPlane(0, mPlane0); mPSEffect->SetProjector(0, projector); mPSEffect->SetShadowColor(0, shadowColor); mPSEffect->SetPlane(1, mPlane1); mPSEffect->SetProjector(1, projector); mPSEffect->SetShadowColor(1, shadowColor); }
void AScrollBar::DoMouseDown(AEvent* pEvent) { AMouseEvent* evt = dynamic_cast<AMouseEvent*>(pEvent); if( evt == NULL ) return; m_MouseOnElem = ButtonElemOnPos(evt->m_X,evt->m_Y); m_ptMouse = APoint(evt->m_X,evt->m_Y); m_ElemStatus = SCROLLBAR_STATUS_DOWN; m_iDownPosition = (int)m_iPosition; if( OnMouseDown.IsValid() ) OnMouseDown.Call(this,pEvent); else { int delta = 0; if( m_MouseOnElem == SCROLLBAR_ELEM_BUTTON1 ) delta = -m_iMiniStep; else if( m_MouseOnElem == SCROLLBAR_ELEM_BUTTON2 ) delta = m_iMiniStep; else if( m_MouseOnElem == SCROLLBAR_ELEM_RAIL_1 ) delta = -m_iBigStep; else if( m_MouseOnElem == SCROLLBAR_ELEM_RAIL_2 ) delta = m_iBigStep; if( m_MouseOnElem == SCROLLBAR_ELEM_TOP1 ) { delta = -GetPosition(); } else if( m_MouseOnElem == SCROLLBAR_ELEM_TOP2 ) { delta = GetRange() - GetPosition(); } if( delta != 0 ) { _Change(delta); } Refresh(); } }
//---------------------------------------------------------------------------- void WaterDropFormation::CreateWall () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); StandardMesh sm(vformat); Transform transform; transform.SetTranslate(APoint(-8.0f, 0.0f, 8.0f)); transform.SetRotate(HMatrix(AVector::UNIT_Y, AVector::UNIT_Z, AVector::UNIT_X, APoint::ORIGIN, true)); sm.SetTransform(transform); mWall = sm.Rectangle(2, 2, 16.0f, 8.0f); std::string path = Environment::GetPathR("Stone.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); mWall->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE)); mTrnNode->AttachChild(mWall); }
NodeConnectorControl::NodeConnectorControl(NodeControl *parent_, NCType io_type) : Control(parent_, APoint(), AVec(), true, false), nc_parent(parent_), ngd(parent_->getNgdParent()), ioType(io_type) { //Set size setSize(getConnectorSize(ioType)); APoint c_pos = nc_parent->getConnectorPoint(ioType) - nc_parent->getPos(); AVec half_size = size*(1.0f/2.0f); //Set pos switch(ioType) { case NCType::DATA_INPUT: setPos(c_pos - AVec(0.0f, half_size.y)); break; case NCType::DATA_OUTPUT: setPos(c_pos - AVec(size.x, half_size.y)); break; case NCType::INFO_INPUT: setPos(c_pos - AVec(half_size.x, 0.0f)); break; case NCType::INFO_OUTPUT: setPos(c_pos - AVec(half_size.x, size.y)); break; default: setPos(c_pos - AVec(0.0f, half_size.y)); break; } setBackgroundColor(ControlState::NONE, Color(0.75f, 0.2f, 0.2f, 1.0f)); setBackgroundColor(ControlState::HOVERING, Color(0.9f, 0.3f, 0.3f, 1.0f)); setBackgroundColor(ControlState::CLICKING, Color(1.0f, 0.5f, 0.5f, 1.0f)); setBackgroundColor(ControlState::DRAGGING, Color(1.0f, 0.5f, 0.5f, 1.0f)); }
//---------------------------------------------------------------------------- void ShadowMaps::CreateScene () { CreateScreenSpaceObjects(); CreateShaders(); // Create a scene graph containing a sphere and a plane. The sphere will // cast a shadow on the plane. mScene = new0 Node(); VertexFormat* vformat = VertexFormat::Create(3, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); StandardMesh sm(vformat); TriMesh* plane = sm.Rectangle(128, 128, 16.0f, 16.0f); plane->SetEffectInstance(mPlaneSceneInstance); mScene->AttachChild(plane); TriMesh* sphere = sm.Sphere(64, 64, 1.0f); sphere->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 1.0f)); sphere->SetEffectInstance(mSphereSceneInstance); mScene->AttachChild(sphere); }
void NodeGraphDisplay::drawGraph(GlInterface &gl) { AVec graph_step = virtualToAbsoluteVec(BASE_GRAPH_STEP), inv_graph_step = AVec(1.0f/graph_step.x, 1.0f/graph_step.y), dist_to_origin = virtualToAbsolutePoint(APoint(0, 0)), dist_after_origin = size - dist_to_origin; APoint first_offset = APoint(fmod(dist_to_origin.x, graph_step.x), fmod(dist_to_origin.y, graph_step.y)), last_offset = APoint(fmod(dist_after_origin.x, graph_step.x), fmod(dist_after_origin.y, graph_step.y)); Point2i lines_before_origin = Point2i(floor(dist_to_origin.x*inv_graph_step.x), floor(dist_to_origin.y*inv_graph_step.y)), lines_after_origin = Point2i(floor(dist_after_origin.x*inv_graph_step.x), floor(dist_after_origin.y*inv_graph_step.y)), num_lines = lines_before_origin + Vec2i(1, 1) + lines_after_origin; std::vector<TVertex> points; points.reserve(2*(num_lines.x + num_lines.y)); //Add vertical lines int i = 0; for(float x = first_offset.x; x < size.x; x += graph_step.x, i++) { Color c = (i != lines_before_origin.x ? Color(0.0f, 0.0f, 0.0f, 1.0f) : Color(1.0f, 0.0f, 0.0f, 1.0f)); points.push_back(TVertex(APoint(x, 0.0f), c)); points.push_back(TVertex(APoint(x, size.y), c)); } //Add horizontal lines i = 0; for(float y = first_offset.y; y < size.y; y += graph_step.y, i++) { Color c = (i != lines_before_origin.y ? Color(0.0f, 0.0f, 0.0f, 1.0f) : Color(1.0f, 0.0f, 0.0f, 1.0f)); points.push_back(TVertex(APoint(0.0f, y), c)); points.push_back(TVertex(APoint(size.x, y), c)); } //Draw lines gl.drawShape(GL_LINES, points); }
//---------------------------------------------------------------------------- void GlossMaps::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); // Create vertex and index buffers to be shared by two meshes. VertexFormat* vformat = VertexFormat::Create(3, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); Float3 yVector(0.0f, 1.0f, 0.0f); vba.Position<Float3>(0) = Float3(-0.5f, 0.0f, -0.5f); vba.Position<Float3>(1) = Float3(-0.5f, 0.0f, 0.5f); vba.Position<Float3>(2) = Float3( 0.5f, 0.0f, 0.5f); vba.Position<Float3>(3) = Float3( 0.5f, 0.0f, -0.5f); vba.Normal<Float3>(0) = yVector; vba.Normal<Float3>(1) = yVector; vba.Normal<Float3>(2) = yVector; vba.Normal<Float3>(3) = yVector; vba.TCoord<Float2>(0, 0) = Float2(1.0f, 0.0f); vba.TCoord<Float2>(0, 1) = Float2(1.0f, 1.0f); vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f); vba.TCoord<Float2>(0, 3) = Float2(0.0f, 0.0f); IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 3; indices[3] = 3; indices[4] = 1; indices[5] = 2; // The light and material are used by both the gloss and non-gloss // objects. Light* light = new0 Light(Light::LT_DIRECTIONAL); light->Ambient = Float4(0.1f, 0.1f, 0.1f, 1.0f); light->Diffuse = Float4(0.6f, 0.6f, 0.6f, 1.0f); light->Specular = Float4(1.0f, 1.0f, 1.0f, 1.0f); light->DVector = AVector(0.0f, -1.0f, 0.0f); Material* material = new0 Material(); material->Ambient = Float4(0.2f, 0.2f, 0.2f, 1.0f); material->Diffuse = Float4(0.7f, 0.7f, 0.7f, 1.0f); material->Specular = Float4(1.0f, 1.0f, 1.0f, 25.0f); // Create a non-gloss-mapped square. TriMesh* squareNoGloss = new0 TriMesh(vformat, vbuffer, ibuffer); squareNoGloss->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, -0.25f*Mathf::PI)); squareNoGloss->LocalTransform.SetTranslate(APoint(1.0f, -1.0f, 0.0f)); squareNoGloss->SetEffectInstance( LightDirPerVerEffect::CreateUniqueInstance(light, material)); mTrnNode->AttachChild(squareNoGloss); // Create a gloss-mapped square. TriMesh* squareGloss = new0 TriMesh(vformat, vbuffer, ibuffer); squareGloss->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, -0.25f*Mathf::PI)); squareGloss->LocalTransform.SetTranslate(APoint(-1.0f, -1.0f, 0.0f)); mTrnNode->AttachChild(squareGloss); std::string effectFile = Environment::GetPathR("GlossMap.wmfx"); GlossMapEffect* effect = new0 GlossMapEffect(effectFile); std::string baseName = Environment::GetPathR("Magic.wmtf"); Texture2D* baseTexture = Texture2D::LoadWMTF(baseName); squareGloss->SetEffectInstance(effect->CreateInstance(baseTexture, light, material)); }
//---------------------------------------------------------------------------- void BouncingBall::PhysicsTick () { // Update the ball. mBall->DoSimulationStep(mSimTime); mRenderer->Update(mBall->GetMesh()->GetVertexBuffer()); // Get the ball parameters. float period = mBall->GetPeriod(); float tMin = mBall->GetMinActive(); float tMax = mBall->GetMaxActive(); // Translate the ball. const float yMax = 2.5f, zMax = 0.75f; float yTrn, zTrn, ratio, amp; float time = fmodf(mSimTime, 2.0f*period); if (time < tMin) { ratio = time/tMin; yTrn = yMax*ratio; zTrn = zMax*(1.0f - ratio*ratio); } else if (time < tMax) { yTrn = yMax; amp = mBall->GetAmplitude(time); if (amp <= 0.999f) { zTrn = -(1.0f - Mathf::Sqrt(1.0f - amp + amp*amp))/(1.0f - amp); } else { zTrn = -0.5f; } } else if (time < period + tMin) { yTrn = -yMax*(time - period)/tMin; zTrn = zMax*(time - tMax)*(period + tMin - time) / (tMin*(period - tMax)); } else if (time < period + tMax) { yTrn = -yMax; amp = mBall->GetAmplitude(time - period); if (amp <= 0.999f) { zTrn = -(1.0f - Mathf::Sqrt(1.0f - amp + amp*amp))/(1.0f - amp); } else { zTrn = -0.5f; } } else { yTrn = yMax*(time - 2.0f*period)/(period - tMax); zTrn = zMax*(time - (period + tMax))*(2.0f*period + tMin - time) / (tMin*(period - tMax)); } mBallNode->LocalTransform.SetTranslate(APoint(0.0f, yTrn, zTrn)); // Rotate the ball. float angle = Mathf::HALF_PI + 0.5f*yTrn*Mathf::PI/yMax; mBallNode->LocalTransform.SetRotate(HMatrix(AVector::UNIT_Z, angle)); // Update the scene graph. mBallNode->Update(); // Next simulation time. mSimTime += mSimDelta; }
//---------------------------------------------------------------------------- void BillboardNodes::CreateScene () { mScene = new0 Node(); mCullState = new0 CullState(); mRenderer->SetOverrideCullState(mCullState); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // All triangle meshes have this common vertex format. Use StandardMesh // to create these meshes. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); StandardMesh stdMesh(vformat); // Create the ground. It covers a square with vertices (1,1,0), (1,-1,0), // (-1,1,0), and (-1,-1,0). Multiply the texture coordinates by a factor // to enhance the wrap-around. mGround = stdMesh.Rectangle(2, 2, 16.0f, 16.0f); VertexBufferAccessor vba(mGround); int i; for (i = 0; i < vba.GetNumVertices(); ++i) { Float2& tcoord = vba.TCoord<Float2>(0, i); tcoord[0] *= 128.0f; tcoord[1] *= 128.0f; } // Create a texture effect for the ground. std::string path = Environment::GetPathR("Horizontal.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = Texture2DEffect::CreateUniqueInstance( texture, Shader::SF_LINEAR_LINEAR, Shader::SC_REPEAT, Shader::SC_REPEAT); mGround->SetEffectInstance(instance); mScene->AttachChild(mGround); // Create a rectangle mesh. The mesh is in the xy-plane. Do not apply // local transformations to the mesh. Use the billboard node transforms // to control the mesh location and orientation. mRectangle = stdMesh.Rectangle(2, 2, 0.125f, 0.25f); // Create a texture effect for the rectangle and for the torus. Texture2DEffect* geomEffect = new0 Texture2DEffect(Shader::SF_LINEAR); path = Environment::GetPathR("RedSky.wmtf"); texture = Texture2D::LoadWMTF(path); mRectangle->SetEffectInstance(geomEffect->CreateInstance(texture)); // Create a billboard node that causes a rectangle to always be facing // the camera. This is the type of billboard for an avatar. mBillboard0 = new0 BillboardNode(mCamera); mBillboard0->AttachChild(mRectangle); mScene->AttachChild(mBillboard0); // The billboard rotation is about its model-space up-vector (0,1,0). In // this application, world-space up is (0,0,1). Locally rotate the // billboard so it's up-vector matches the world's. mBillboard0->LocalTransform.SetTranslate(APoint(-0.25f, 0.0f, 0.25f)); mBillboard0->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, Mathf::HALF_PI)); // Create a torus mesh. Do not apply local transformations to the mesh. // Use the billboard node transforms to control the mesh location and // orientation. mTorus = StandardMesh(vformat, false).Torus(16, 16, 1.0f, 0.25f); mTorus->LocalTransform.SetUniformScale(0.1f); // Create a texture effect for the torus. It uses the RedSky image that // the rectangle uses. mTorus->SetEffectInstance(geomEffect->CreateInstance(texture)); // Create a billboard node that causes an object to always be oriented // the same way relative to the camera. mBillboard1 = new0 BillboardNode(mCamera); mBillboard1->AttachChild(mTorus); mScene->AttachChild(mBillboard1); // The billboard rotation is about its model-space up-vector (0,1,0). In // this application, world-space up is (0,0,1). Locally rotate the // billboard so it's up-vector matches the world's. mBillboard1->LocalTransform.SetTranslate(APoint(0.25f, 0.0f, 0.25f)); mBillboard1->LocalTransform.SetRotate(HMatrix(AVector::UNIT_X, Mathf::HALF_PI)); #ifdef DEMONSTRATE_VIEWPORT_BOUNDING_RECTANGLE // The screen camera is designed to map (x,y,z) in [0,1]^3 to (x',y,'z') // in [-1,1]^2 x [0,1]. mSSCamera = new0 Camera(false); mSSCamera->SetFrustum(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); mSSCamera->SetFrame(APoint::ORIGIN, AVector::UNIT_Z, AVector::UNIT_Y, AVector::UNIT_X); // Create a semitransparent screen rectangle. VertexFormat* ssVFormat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT4, 0); int ssVStride = ssVFormat->GetStride(); VertexBuffer* ssVBuffer = new0 VertexBuffer(4, ssVStride); VertexBufferAccessor ssVba(ssVFormat, ssVBuffer); Float4 ssColor(0.0f, 0.0f, 1.0f, 0.25f); ssVba.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.0f); ssVba.Position<Float3>(1) = Float3(1.0f, 0.0f, 0.0f); ssVba.Position<Float3>(2) = Float3(1.0f, 1.0f, 0.0f); ssVba.Position<Float3>(3) = Float3(0.0f, 1.0f, 0.0f); ssVba.Color<Float4>(0, 0) = ssColor; ssVba.Color<Float4>(0, 1) = ssColor; ssVba.Color<Float4>(0, 2) = ssColor; ssVba.Color<Float4>(0, 3) = ssColor; IndexBuffer* ssIBuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ssIBuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; mSSRectangle = new0 TriMesh(ssVFormat, ssVBuffer, ssIBuffer); mSSRectangle->Update(); // Create a vertex color effect for the screen rectangle. VertexColor4Effect* ssEffect = new0 VertexColor4Effect(); mSSRectangle->SetEffectInstance(ssEffect->CreateInstance()); // Alpha blending must be enabled to obtain the semitransparency. ssEffect->GetAlphaState(0, 0)->BlendEnabled = true; #endif }
//---------------------------------------------------------------------------- Node* RoughPlaneSolidBox::CreateBox () { mBox = new0 Node(); float xExtent = (float)mModule.XLocExt; float yExtent = (float)mModule.YLocExt; float zExtent = (float)mModule.ZLocExt; VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); StandardMesh sm(vformat); VertexColor3Effect* effect = new0 VertexColor3Effect(); VertexBufferAccessor vba; Transform transform; TriMesh* face; int i; // +z face Float3 red(1.0f, 0.0f, 0.0f); transform.SetTranslate(APoint(0.0f, 0.0f, zExtent)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, xExtent, yExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = red; vba.Color<Float3>(0, 1) = red; vba.Color<Float3>(0, 2) = red; vba.Color<Float3>(0, 3) = red; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // -z face Float3 darkRed(0.5f, 0.0f, 0.0f); transform.SetTranslate(APoint(0.0f, 0.0f, -zExtent)); transform.SetRotate(HMatrix(AVector::UNIT_Y, AVector::UNIT_X, -AVector::UNIT_Z, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, yExtent, xExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = darkRed; vba.Color<Float3>(0, 1) = darkRed; vba.Color<Float3>(0, 2) = darkRed; vba.Color<Float3>(0, 3) = darkRed; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // +y face Float3 green(0.0f, 1.0f, 0.0f); transform.SetTranslate(APoint(0.0f, yExtent, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_Z, AVector::UNIT_X, AVector::UNIT_Y, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, zExtent, xExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = green; vba.Color<Float3>(0, 1) = green; vba.Color<Float3>(0, 2) = green; vba.Color<Float3>(0, 3) = green; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // -y face Float3 darkGreen(0.0f, 1.0f, 0.0f); transform.SetTranslate(APoint(0.0f, -yExtent, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_X, AVector::UNIT_Z, -AVector::UNIT_Y, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, xExtent, zExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = darkGreen; vba.Color<Float3>(0, 1) = darkGreen; vba.Color<Float3>(0, 2) = darkGreen; vba.Color<Float3>(0, 3) = darkGreen; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // +x face Float3 blue(0.0f, 0.0f, 1.0f); transform.SetTranslate(APoint(xExtent, 0.0f, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_Y, AVector::UNIT_Z, AVector::UNIT_X, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, yExtent, zExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = blue; vba.Color<Float3>(0, 1) = blue; vba.Color<Float3>(0, 2) = blue; vba.Color<Float3>(0, 3) = blue; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); // -x face Float3 darkBlue(0.0f, 0.0f, 1.0f); transform.SetTranslate(APoint(-xExtent, 0.0f, 0.0f)); transform.SetRotate(HMatrix(AVector::UNIT_Z, AVector::UNIT_Y, -AVector::UNIT_X, APoint::ORIGIN, true)); sm.SetTransform(transform); face = sm.Rectangle(2, 2, zExtent, yExtent); vba.ApplyTo(face); for (i = 0; i < 4; ++i) { vba.Color<Float3>(0, 0) = darkBlue; vba.Color<Float3>(0, 1) = darkBlue; vba.Color<Float3>(0, 2) = darkBlue; vba.Color<Float3>(0, 3) = darkBlue; } face->SetEffectInstance(effect->CreateInstance()); mBox->AttachChild(face); MoveBox(); return mBox; }
void AudioDisplay::drawData(GlInterface &gl) { //(Up here for now to minimize flickering) s_time cursor_time = (cursor ? cursor->getSampleRange().start : 0); c_time num_data_chunks = audioData->size(); //Get view origin/size in absolute space APoint av_pos = gl.viewToAbsolutePoint(APoint(0, 0)); AVec v_size = gl.getCurrView().size, av_size = gl.viewToAbsoluteVec(v_size); const float //Basic multipliers sample_mult = 1.0f/AUDIO_MAX_AMPLITUDE, //Multiplier to transform an AudioSample to a 0.0 to 1.0 scale chunk_mult = 1.0f/AUDIO_CHUNK_SIZE, //Multiplier to convert samples to chunks a_to_v = gl.absoluteToViewVec(AVec(1.0, 0.0f)).x, //Converts absolute sizes to view sizes v_to_a = 1.0f/a_to_v, //Samples per physical pixel in absolute and view spaces //TODO: Figure out whether this should be in absolute or view space a_spp = samplesPerPixel, a_pps = 1.0f/a_spp, v_spp = gl.absoluteToViewVec(AVec(samplesPerPixel, 0)).x, v_pps = a_to_v*a_pps,//1.0f/v_spp, //Chunks per pixel a_cpp = a_spp*chunk_mult, a_ppc = (float)AUDIO_CHUNK_SIZE*a_pps, v_cpp = v_spp*chunk_mult, v_ppc = (float)AUDIO_CHUNK_SIZE*v_pps; //Left-most point, centered vertically (VIRTUAL SPACE) APoint origin(0, size.y/2.0f); //Sample values s_time sample_offset = (s_time)(av_pos.x*a_spp), num_samples = (s_time)ceil(av_size.x*a_spp), first_chunk_so = sample_offset % AUDIO_CHUNK_SIZE, last_chunk_so = AUDIO_CHUNK_SIZE - (first_chunk_so + num_samples) % AUDIO_CHUNK_SIZE, total_samples = first_chunk_so + num_samples + last_chunk_so; //Chunk values c_time start_chunk = (c_time)(sample_offset*chunk_mult), num_chunks = (c_time)ceil(total_samples*chunk_mult), last_chunk = start_chunk + num_chunks; //Check for errors if (sample_offset < 0 || start_chunk >= num_data_chunks || num_chunks <= 0) { std::cout << "ERROR --> \n"; if(sample_offset < 0) std::cout << "\t\tSAMPLE_OFFSET LESS THAN 0\n"; if (start_chunk >= num_data_chunks) std::cout << "\t\tSTART_CHUNK_TOO_BIG\n"; if(num_chunks <= 0) std::cout << "\t\tNUM_CHUNKS <= 0\n"; std::cout << "\tSAMPLE_OFFSET: " << sample_offset << "\n"; std::cout << "\tSTART_CHUNK: " << start_chunk << "\n"; std::cout << "\tNUM CHUNKS: " << num_chunks << "\n"; return; } if(start_chunk + num_chunks > num_data_chunks) num_chunks = num_data_chunks - start_chunk; //Get chunk sizes to sample (one sample per on-screen pixel) float desired_chunk_size = v_pps*(float)AUDIO_CHUNK_SIZE; s_time actual_chunk_size = (s_time)ceil(desired_chunk_size); float actual_to_desired = desired_chunk_size/(float)actual_chunk_size; //Converts sampled chunk to desired chunk const AudioChunk** pData = (const AudioChunk**)((*audioData).data() + start_chunk); //Number of pixels up until start_chunk float start_px = start_chunk*a_ppc; //Allocate space for sampled chunks AudioChunk **s_data = new AudioChunk*[num_chunks]; for(c_time i = 0; i < num_chunks; i++) s_data[i] = new AudioChunk(actual_chunk_size); //Sample chunks AStatus status = sampleChunks(pData, s_data, num_chunks, SampleMethod::AVERAGE, false); if(!statusGood(status)) { std::cout << "AUDIO DISPLAY -->\n" << status << "\n"; return; } ////DRAW//// std::vector<TVertex> points; Color col; //Draw status highlights if(drawStatuses) { for(c_time c = 0; c < num_chunks; c++) { //Set status color switch(pData[c]->getStatus()) { case DataStatus::CLEAN: gl.setColor(0.5f, 0.65f, 0.55f); break; case DataStatus::DIRTY: gl.setColor(0.65f, 0.5f, 0.5f); break; default: //Unknown status gl.setColor(1.0f, 0.0f, 1.0f); } //Draw current chain gl.drawRect(APoint((start_chunk + c)*a_ppc, 0.0f), AVec(a_ppc, size.y)); } /* DataStatus curr_status = pData[0]->getStatus(); ChunkRange c_r(-1, -1); for(c_time c = 0; c < num_chunks; c++) { c_time d_c = start_chunk + c; DataStatus d_status = pData[c]->getStatus(); bool continue_chain = (d_status == curr_status); if(continue_chain || c + 1 == num_chunks) { //Continue chain c_r.start = (c_r.start < 0 ? d_c : c_r.start); c_r.end = d_c + 1; } if(!continue_chain || c + 1 == num_chunks) { //Set status color switch(curr_status)//aData[d_c]->status) { case DataStatus::CLEAN: gl.setColor(0.5f, 0.65f, 0.55f); break; case DataStatus::DIRTY: gl.setColor(0.65f, 0.5f, 0.5f); break; default: //Unknown status gl.setColor(1.0f, 0.0f, 1.0f); } //Draw current chain gl.drawRect(APoint(c_r.start*a_ppc, 0.0f), AVec(c_r.length()*a_ppc, size.y)); //Start new chain c_r.start = d_c; c_r.end = d_c + 1; curr_status = d_status; } } */ } //Draw center line gl.setColor(0.2f, 0.2f, 0.2f, 1.0f); gl.drawLine(APoint(start_px, origin.y), APoint(start_px + total_samples*a_pps, origin.y)); //TEST: Draw every data point (to compare approximation with) if(Keyboard::keyDown(Keys::K_Q)) { points.clear(); points.reserve(num_samples); col = Color(1.0f, 0.0f, 0.0f, 1.0f); const c_time c_start = (flipChunks ? (num_chunks - 1) : 0), c_step = (flipChunks ? -1 : 1); const s_time s_start = (flipChunkSamples ? (AUDIO_CHUNK_SIZE - 1) : 0), s_step = (flipChunkSamples ? -1 : 1); for(c_time c = c_start; (!flipChunks && c < num_chunks) || (flipChunks && c >= 0); c += c_step) { const AudioSample *c_data = pData[c]->getData(); for(s_time s = s_start; (!flipChunkSamples && s < AUDIO_CHUNK_SIZE) || (flipChunkSamples && s >= 0); s += s_step) { //Calculate number of samples from the start (adjusting for flipped data or chunks) s_time s_x = (flipChunks ? (num_chunks - 1 - c) : c)*AUDIO_CHUNK_SIZE + (flipChunkSamples ? (AUDIO_CHUNK_SIZE - 1 - s) : s); APoint p(start_px + s_x*a_pps, origin.y - origin.y*(float)c_data[s]*sample_mult); points.push_back(TVertex(p, col)); } } gl.drawShape(GL_LINE_STRIP, points); } //Draw lines connecting samples (with approximate, sampled data) points.clear(); points.reserve(num_chunks*desired_chunk_size); col = Color(0.0f, 0.0f, 0.0f, 1.0f); const c_time c_start = (flipChunks ? (num_chunks - 1) : 0), c_step = (flipChunks ? -1 : 1); const s_time s_start = (flipChunkSamples ? (actual_chunk_size - 1) : 0), s_step = (flipChunkSamples ? -1 : 1); for(c_time c = c_start; (!flipChunks && c < num_chunks) || (flipChunks && c >= 0); c += c_step) { const AudioSample *c_data = s_data[c]->getData(); for(s_time s = s_start; (!flipChunkSamples && s < actual_chunk_size) || (flipChunkSamples && s >= 0); s += s_step) { const s_time s_x = (flipChunks ? (num_chunks - 1 - c) : c)*actual_chunk_size + (flipChunkSamples ? (actual_chunk_size - 1 - s) : s); APoint p(start_px + s_x*actual_to_desired*v_to_a, origin.y - origin.y*(float)c_data[s]*sample_mult); points.push_back(TVertex(p, col)); } } gl.drawShape(GL_LINE_STRIP, points); /* glBegin(GL_LINE_STRIP); glColor3f(0.0f, 0.0f, 0.0f); s_time sample = 0; for(c_time c = 0; c < num_chunks; c++) { std::vector<AudioSample> &c_data = s_data[c]->data; for(s_time s = first_chunk_po*(c == 0); s < actual_chunk_size && sample < num_samples; s++, sample++) { GlPoint gl_pos = toGlPoint(APoint((float)sample*chunk_ratio, origin.y*(1.0f - (float)c_data[s]*sample_mult)), vv_size); glVertex2f(gl_pos.x, gl_pos.y); } } glEnd(); */ /* //Draw lines connecting samples (as squares) glBegin(GL_QUADS); glColor3f(0.0f, 0.0f, 0.0f); s_time sample = 0; for(c_time c = 0; c < num_chunks; c++) { std::vector<AudioSample> &c_data_max = s_max[c]->data, &c_data_min = s_min[c]->data; for(s_time s = first_chunk_po*(c == 0); s < actual_chunk_size && sample < num_pixels; s++, sample++) { float p_x = (float)sample*chunk_ratio; GlPoint gl_pos_max = toGlPoint(APoint(p_x - 0.5f, origin.y*(1.0f - (float)c_data_max[s]*sample_mult)), vv_size), gl_pos_min = toGlPoint(APoint(p_x + 0.5f, origin.y*(1.0f - (float)c_data_min[s]*sample_mult)), vv_size); //Draw vertical bar from max to min -- 1 pixel wide glVertex2f(gl_pos_max.x, gl_pos_max.y); glVertex2f(gl_pos_max.x, gl_pos_min.y); glVertex2f(gl_pos_min.x, gl_pos_max.y); glVertex2f(gl_pos_min.x, gl_pos_min.y); } } glEnd(); */ if(DRAW_CHUNK_LINES) { points.clear(); points.reserve(2*num_chunks); col = Color(0.4f, 0.4f, 0.9f, 0.3f); float x = av_pos.x + (AUDIO_CHUNK_SIZE - first_chunk_so)*a_pps; for(c_time c = 0; c < num_chunks; c++, x += a_ppc) { if(pData[c]->NOTE_ON) { gl.setColor(Color(1.0f, 0.0f, 0.0f, 0.5f)); gl.drawRect(APoint(x - AUDIO_CHUNK_SIZE*a_pps, 0.0f), AVec(AUDIO_CHUNK_SIZE*a_pps, size.y)); } col = Color(0.4f, 0.4f, 0.9f, 0.3f); points.push_back(TVertex(APoint(x, 0.0f), col)); points.push_back(TVertex(APoint(x, size.y), col)); } gl.drawShape(GL_LINES, points); points.clear(); } //Draw cursor if(cursor) { float x = cursor_time*a_pps; gl.setColor(0.8f, 0.8f, 0.1f); gl.drawLine(APoint(x, 0.0f), APoint(x, size.y)); } //Release sampled data if(s_data) { for(int i = 0; i < num_chunks; i++) delete s_data[i]; delete[] s_data; } /* if(s_max) { for(int i = 0; i < num_chunks; i++) delete s_max[i]; delete[] s_max; } if(s_min) { for(int i = 0; i < num_chunks; i++) delete s_min[i]; delete[] s_min; } */ }
//---------------------------------------------------------------------------- void ScreenPolygons::CreateScene () { // The screen camera is designed to map (x,y,z) in [0,1]^3 to (x',y,'z') // in [-1,1]^2 x [0,1]. mScreenCamera = new0 Camera(false); mScreenCamera->SetFrustum(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f); mScreenCamera->SetFrame(APoint::ORIGIN, AVector::UNIT_Z, AVector::UNIT_Y, AVector::UNIT_X); // Load the biped just for some model to display. #ifdef WM5_LITTLE_ENDIAN std::string path = Environment::GetPathR("SkinnedBipedPN.wmof"); #else std::string path = Environment::GetPathR("SkinnedBipedPN.be.wmof"); #endif InStream source; source.Load(path); mScene = DynamicCast<Node>(source.GetObjectAt(0)); assertion(mScene != 0, "Error in biped stream.\n"); // The background is a textured screen polygon (z = 1). VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(0.0f, 0.0f, 1.0f); vba.Position<Float3>(1) = Float3(1.0f, 0.0f, 1.0f); vba.Position<Float3>(2) = Float3(1.0f, 1.0f, 1.0f); vba.Position<Float3>(3) = Float3(0.0f, 1.0f, 1.0f); vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f); vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f); vba.TCoord<Float2>(0, 2) = Float2(1.0f, 1.0f); vba.TCoord<Float2>(0, 3) = Float2(0.0f, 1.0f); IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; mBackPoly = new0 TriMesh(vformat, vbuffer, ibuffer); path = Environment::GetPathR("RedSky.wmtf"); Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR); Texture2D* texture = Texture2D::LoadWMTF(path); mBackPoly->SetEffectInstance(effect->CreateInstance(texture)); // The middle polygon, which may be translated via '+' or '-'. vbuffer = new0 VertexBuffer(4, vstride); vba.ApplyTo(vformat, vbuffer); vba.Position<Float3>(0) = Float3(0.0f, 0.3f, 0.0f); vba.Position<Float3>(1) = Float3(1.0f, 0.3f, 0.0f); vba.Position<Float3>(2) = Float3(1.0f, 0.7f, 0.0f); vba.Position<Float3>(3) = Float3(0.0f, 0.7f, 0.0f); vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.3f); vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.3f); vba.TCoord<Float2>(0, 2) = Float2(1.0f, 0.7f); vba.TCoord<Float2>(0, 3) = Float2(0.0f, 0.7f); mMidPoly = new0 TriMesh(vformat, vbuffer, ibuffer); path = Environment::GetPathR("BallTexture.wmtf"); texture = Texture2D::LoadWMTF(path); mMidPoly->SetEffectInstance(effect->CreateInstance(texture)); mLinearZ = 1.0f; mDepthZ = 1.0f; mMidPoly->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, mLinearZ)); // A portion of the foreground is a textured screen polygon (z = 0). vbuffer = new0 VertexBuffer(5, vstride); vba.ApplyTo(vformat, vbuffer); vba.Position<Float3>(0) = Float3(0.0f, 0.0f, 0.0f); vba.Position<Float3>(1) = Float3(0.5f, 0.0f, 0.0f); vba.Position<Float3>(2) = Float3(0.75f, 0.5f, 0.0f); vba.Position<Float3>(3) = Float3(0.5f, 0.75f, 0.0f); vba.Position<Float3>(4) = Float3(0.0f, 0.5f, 0.0f); vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f); vba.TCoord<Float2>(0, 1) = Float2(0.67f, 0.0f); vba.TCoord<Float2>(0, 2) = Float2(1.0f, 0.67f); vba.TCoord<Float2>(0, 3) = Float2(0.67f, 1.0f); vba.TCoord<Float2>(0, 4) = Float2(0.0f, 0.67f); ibuffer = new0 IndexBuffer(9, sizeof(int)); indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; indices[6] = 0; indices[7] = 3; indices[8] = 4; mForePoly = new0 TriMesh(vformat, vbuffer, ibuffer); path = Environment::GetPathR("Flower.wmtf"); Texture2DEffect* foreEffect = new0 Texture2DEffect(Shader::SF_LINEAR); texture = Texture2D::LoadWMTF(path); mForePoly->SetEffectInstance(foreEffect->CreateInstance(texture)); // Make the foreground semitransparent. foreEffect->GetAlphaState(0, 0)->BlendEnabled = true; }
void Bullet::Move() { int bulletX = m_pLocation.getX(); int bulletY = m_pLocation.getY(); int collideX; int collideY; int bulletFlySpeed = m_iMoveSpeed+m_tOwner->MoveSpeed(); switch (m_dDirection) //ÅÚµ¯µÄ·ÉÐÐ { case RETREAT: m_pLocation.setY(bulletY+bulletFlySpeed); collideX = m_pLocation.getX(); collideY = m_pLocation.getY()+7; break; case LEFT: m_pLocation.setX(bulletX-bulletFlySpeed); collideX = m_pLocation.getX()-7; collideY = m_pLocation.getY(); break; case RIGHT: m_pLocation.setX(bulletX+bulletFlySpeed); collideX = m_pLocation.getX()+7; collideY = m_pLocation.getY(); break; case FRONT: m_pLocation.setY(bulletY-bulletFlySpeed); collideX = m_pLocation.getX(); collideY = m_pLocation.getY()-7; break; default: break; } int map_value = map[(g_roundNumber-1)%5][collideY/64][collideX/64];// »ñÈ¡µØÐÎ if (map_value==101||map_value==102||(map_value>=109&&map_value!=111&&map_value!=112&&map_value<=116)) //Óöµ½Ç½±Ú { m_bIsFly = false; } else if (bulletX<0||bulletX>g_rect.right||bulletY<0||bulletY>g_rect.bottom) //³ö½ç { m_bIsFly = false; } else if (m_tOwner->getID()==0) //²Ù¿Ø̹¿Ë ÅÚµ¯´¦Àí { if (isTouched(this,enemys[0])&&enemys[0]->getIsAlive()&&enemys[0]->getHP()>0&&!enemys[0]->getIsInvincible()) //»÷ÖÐAssassin { ShootedPlace.push_back(APoint(this->Location().getX()/64+1,this->Location().getY()/64+1)); enemys[0]->decreaseHP(); m_bIsFly = false; g_score+=30; } else { for (int i=0;i<g_enemyNumber;i++) { if (isTouched(this,newEnemy[i])&&newEnemy[i]->getIsAlive()&&newEnemy[i]->getHP()>0&&!newEnemy[i]->getIsInvincible()) //²Ù¿ØÅÚµ¯»÷Öез½Ì¹¿Ë { ShootedPlace.push_back(APoint(this->Location().getX()/64+1,this->Location().getY()/64+1)); newEnemy[i]->decreaseHP(); m_bIsFly = false; if (newEnemy[i]->getFitness()<30) { g_score+=20; //////////////////////////////////////////////////////////////////////////////////////////////////// } else if (newEnemy[i]->getFitness()<50) { g_score+=35; } else { g_score+=50; } break; } else if (newEnemy[i]->getBullet().getIsFly()&&isTouched(&(newEnemy[i]->getBullet()),this))//²Ù¿ØÅÚµ¯ÓëµÐ·½ÅÚµ¯ÏàÅö { newEnemy[i]->m_pBullet.setIsFly(false); m_bIsFly = false; break; } } } } else if (m_tOwner->getID()==2) //ÒÔºóÐ޸ģ¡£¡£¡£¡£¡£¡£¡£¡£¡£¡ { if (pLTank->getIsAlive()&&pLTank->getHP()&&isTouched(this,pLTank)) { pLTank->decreaseHP(); this->m_tOwner->increaseShoot(); this->m_tOwner->setFitness(this->m_tOwner->getFitness()+25); m_bIsFly = false; } } }
void MidiDisplay::drawData(GlInterface &gl) { //(Up here for now to minimize flickering) s_time cursor_time = (cursor ? cursor->getSampleRange().start : 0); //Get view origin/size in absolute space APoint av_pos = gl.viewToAbsolutePoint(APoint(0, 0)); AVec av_size = gl.viewToAbsoluteVec(gl.getCurrView().size); //Samples per pixel const float a_spp = samplesPerPixel, a_pps = 1.0f/a_spp, v_spp = gl.absoluteToViewVec(AVec(samplesPerPixel, 0)).x, v_pps = 1.0f/v_spp, //Chunks per pixel a_cpp = a_spp*AUDIO_CHUNK_SIZE, a_ppc = a_pps*AUDIO_CHUNK_SIZE, v_cpp = v_spp*AUDIO_CHUNK_SIZE, v_ppc = v_pps*AUDIO_CHUNK_SIZE, //Seconds per pixel a_secpp = secondsPerPixel, a_ppsec = 1.0f/a_secpp, v_secpp = gl.absoluteToViewVec(AVec(secondsPerPixel, 0)).x, v_ppsec = 1.0f/v_secpp, note_mult = 1.0f/NUM_MIDI_NOTES; //Normalizes MidiIndex between 0 and 1 //Left-most point, starting from bottom APoint origin(0, size.y); //Position adjustment values double t_offset = (double)(av_pos.x*a_secpp), t_length = (double)(av_size.x*a_secpp), end_t = t_offset + t_length; //std::cout << t_offset << "\n"; TimeRange r(t_offset, end_t); //Get intersecting notes ConstMidiData midi = midiData->getConstNotes(r); s_time sample_offset = (s_time)(av_pos.x*a_spp), num_samples = (s_time)ceil(av_size.x*a_spp), first_chunk_so = sample_offset % AUDIO_CHUNK_SIZE, last_chunk_so = (first_chunk_so + num_samples) % AUDIO_CHUNK_SIZE, total_samples = first_chunk_so + num_samples + last_chunk_so; ////DRAW//// std::vector<TVertex> points; points.reserve(2*midi.size()); Color col(0.0f, 0.0f, 0.0f, 1.0f); for(auto n : midi) { float height = origin.y - origin.y*((float)n->index*note_mult), x1 = (float)n->range.start*a_ppsec, //x2 = (float)(n->isFinished() ? n->end : (float)cursor_time/TEMP_SAMPLERATE)*a_ppsec; x2 = (float)n->range.end*a_ppsec; points.push_back(TVertex(APoint(x1, height), col)); points.push_back(TVertex(APoint(x2, height), col)); } gl.drawShape(GL_LINES, points); points.clear(); col = Color(1.0f, 1.0f, 0.0f, 1.0f); //Draw stoppers /* for(auto n : midi) { float height = origin.y - origin.y*((float)n->index*note_mult); for(auto st : n->stoppers) { float x = (float)(n->range.start + st.offset)*a_ppsec; points.push_back(TVertex(APoint(x, height), col)); } } gl.drawShape(GL_POINTS, points); */ //Draw chunk lines if(DRAW_CHUNK_LINES) { //Convert seconds to chunks c_time num_chunks = (c_time)ceil((float)total_samples/(float)AUDIO_CHUNK_SIZE); points.clear(); points.reserve(2*num_chunks); col = Color(0.4f, 0.4f, 0.9f, 0.3f); float x = av_pos.x + (AUDIO_CHUNK_SIZE - first_chunk_so)*a_pps; for(c_time c = 0; c < num_chunks; c++, x += a_ppc) { points.push_back(TVertex(APoint(x, 0.0f), col)); points.push_back(TVertex(APoint(x, size.y), col)); } gl.drawShape(GL_LINES, points); points.clear(); } //Draw cursor if(cursor) { float x = (float)cursor_time/TEMP_SAMPLERATE*a_ppsec; gl.setColor(0.8f, 0.8f, 0.1f); gl.drawLine(APoint(x, 0.0f), APoint(x, size.y)); } //TEST //gl.setColor(1.0f, 0.0f, 0.0f); //gl.drawLine(APoint(end_t*v_ppsec, 0), APoint(end_t*v_ppsec, size.y)); }
//---------------------------------------------------------------------------- void IntersectConvexPolyhedra::CreateScene () { mScene = new0 Node(); mMotionObject = mScene; VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // Attach a dummy intersection mesh. If the intersection is nonempty, // the Culling flag will be modified to CULL_DYNAMIC. The intersection // is drawn as a solid. mMeshIntersection = StandardMesh(vformat).Tetrahedron(); VertexBufferAccessor vba(mMeshIntersection); Float3 green(0.0f, 1.0f, 0.0f); int i, j; for (i = 0; i < vba.GetNumVertices(); ++i) { vba.Color<Float3>(0, i) = green; } mMeshIntersection->SetEffectInstance( VertexColor3Effect::CreateUniqueInstance()); mMeshIntersection->Culling = Spatial::CULL_ALWAYS; mScene->AttachChild(mMeshIntersection); // The first polyhedron is an ellipsoid. ConvexPolyhedronf::CreateEggShape(Vector3f::ZERO, 1.0f, 1.0f, 2.0f, 2.0f, 4.0f, 4.0f, 3, mWorldPoly0); // Build the corresponding mesh. int numVertices = mWorldPoly0.GetNumVertices(); int numTriangles = mWorldPoly0.GetNumTriangles(); int numIndices = 3*numTriangles; VertexBuffer* vbuffer = new0 VertexBuffer(numVertices, vstride); IndexBuffer* ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); Float3 red(1.0f, 0.0f, 0.0f); vba.ApplyTo(vformat, vbuffer); for (i = 0; i < numVertices; ++i) { vba.Position<Vector3f>(i) = mWorldPoly0.Point(i); vba.Color<Float3>(0,i) = red; } int* indices = (int*)ibuffer->GetData(); for (i = 0; i < numTriangles; ++i) { const MTTriangle& triangle = mWorldPoly0.GetTriangle(i); for (j = 0; j < 3; ++j) { indices[3*i + j] = mWorldPoly0.GetVLabel(triangle.GetVertex(j)); } } mMeshPoly0 = new0 TriMesh(vformat, vbuffer, ibuffer); VisualEffectInstance* instance = VertexColor3Effect::CreateUniqueInstance(); instance->GetEffect()->GetWireState(0, 0)->Enabled = true; mMeshPoly0->SetEffectInstance(instance); mMeshPoly0->LocalTransform.SetTranslate(APoint(0.0f, 2.0f, 0.0f)); mScene->AttachChild(mMeshPoly0); // The second polyhedron is egg shaped. ConvexPolyhedronf::CreateEggShape(Vector3f::ZERO, 2.0f, 2.0f, 4.0f, 4.0f, 5.0f, 3.0f, 4, mWorldPoly1); // Build the corresponding mesh. numVertices = mWorldPoly1.GetNumVertices(); numTriangles = mWorldPoly1.GetNumTriangles(); numIndices = 3*numTriangles; vbuffer = new0 VertexBuffer(numVertices, vstride); ibuffer = new0 IndexBuffer(numIndices, sizeof(int)); Float3 blue(0.0f, 0.0f, 1.0f); vba.ApplyTo(vformat, vbuffer); for (i = 0; i < numVertices; ++i) { vba.Position<Vector3f>(i) = mWorldPoly1.Point(i); vba.Color<Float3>(0, i) = blue; } indices = (int*)ibuffer->GetData(); for (i = 0; i < numTriangles; ++i) { const MTTriangle& triangle = mWorldPoly1.GetTriangle(i); for (j = 0; j < 3; ++j) { indices[3*i + j] = mWorldPoly1.GetVLabel(triangle.GetVertex(j)); } } mMeshPoly1 = new0 TriMesh(vformat, vbuffer, ibuffer); instance = VertexColor3Effect::CreateUniqueInstance(); instance->GetEffect()->GetWireState(0, 0)->Enabled = true; mMeshPoly1->SetEffectInstance(instance); mMeshPoly1->LocalTransform.SetTranslate(APoint(0.0f, -2.0f, 0.0f)); mScene->AttachChild(mMeshPoly1); ComputeIntersection(); }
//---------------------------------------------------------------------------- void MaterialTextures::CreateScene () { mScene = new0 Node(); mTrnNode = new0 Node(); mScene->AttachChild(mTrnNode); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); // Create a square object. VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0); int vstride = vformat->GetStride(); VertexBuffer* vbuffer = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer); vba.Position<Float3>(0) = Float3(-1.0f, -1.0f, 0.0f); vba.Position<Float3>(1) = Float3(-1.0f, 1.0f, 0.0f); vba.Position<Float3>(2) = Float3( 1.0f, 1.0f, 0.0f); vba.Position<Float3>(3) = Float3( 1.0f, -1.0f, 0.0f); vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f); vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f); vba.TCoord<Float2>(0, 2) = Float2(1.0f, 1.0f); vba.TCoord<Float2>(0, 3) = Float2(0.0f, 1.0f); IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 3; indices[3] = 3; indices[4] = 1; indices[5] = 2; // Create a square with a door texture. TriMesh* door = new0 TriMesh(vformat, vbuffer, ibuffer); std::string path = Environment::GetPathR("Door.wmtf"); Texture2D* texture = Texture2D::LoadWMTF(path); door->SetEffectInstance(Texture2DEffect::CreateUniqueInstance(texture, Shader::SF_LINEAR, Shader::SC_CLAMP_EDGE, Shader::SC_CLAMP_EDGE)); mTrnNode->AttachChild(door); // Material-texture effect shared by two objects. The material is // semitransparent, so alpha blending must be enabled. MaterialTextureEffect* effect = new0 MaterialTextureEffect(Shader::SF_LINEAR); effect->GetAlphaState(0, 0)->BlendEnabled = true; // Create a square with a material-texture effect. The texture is combined // with the material to produce a semitransparenteffect on the sand. You // should be able to see the door through it. TriMesh* sand = new0 TriMesh(vformat, vbuffer, ibuffer); sand->LocalTransform.SetTranslate(APoint(0.25f, 0.25f, -0.25f)); mTrnNode->AttachChild(sand); mMaterial = new0 Material(); mMaterial->Diffuse = Float4(1.0f, 0.0f, 0.0f, 0.5f); path = Environment::GetPathR("Sand.wmtf"); texture = Texture2D::LoadWMTF(path); VisualEffectInstance* instance = effect->CreateInstance(mMaterial, texture); sand->SetEffectInstance(instance); // The material alpha is adjustable during run time, so we must enable // the corresponding shader constant to automatically update. instance->GetVertexConstant(0, "MaterialDiffuse")->EnableUpdater(); // Create another square with a material-texture effect. TriMesh* water = new0 TriMesh(vformat, vbuffer, ibuffer); water->LocalTransform.SetTranslate(APoint(0.5f, 0.5f, -0.5f)); mTrnNode->AttachChild(water); Material* material = new0 Material(); material->Diffuse = Float4(0.0f, 0.0f, 1.0f, 0.5f); path = Environment::GetPathR("Water.wmtf"); texture = Texture2D::LoadWMTF(path); water->SetEffectInstance(effect->CreateInstance(material, texture)); }
//---------------------------------------------------------------------------- void PolygonOffsets::CreateScene () { mScene = new0 Node(); mWireState = new0 WireState(); mRenderer->SetOverrideWireState(mWireState); VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_COLOR, VertexFormat::AT_FLOAT3, 0); int vstride = vformat->GetStride(); // Vertices to be shared by rectangles 1 and 3. VertexBuffer* vbuffer0 = new0 VertexBuffer(4, vstride); VertexBufferAccessor vba(vformat, vbuffer0); vba.Position<Float3>(0) = Float3(-1.0f, 0.0f, -1.0f); vba.Position<Float3>(1) = Float3(-1.0f, 0.0f, +1.0f); vba.Position<Float3>(2) = Float3(+1.0f, 0.0f, +1.0f); vba.Position<Float3>(3) = Float3(+1.0f, 0.0f, -1.0f); vba.Color<Float3>(0, 0) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 1) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 2) = Float3(1.0f, 0.0f, 0.0f); vba.Color<Float3>(0, 3) = Float3(1.0f, 0.0f, 0.0f); // Vertices to be shared by rectangles 2 and 4. VertexBuffer* vbuffer1 = new0 VertexBuffer(4, vstride); vba.ApplyTo(vformat, vbuffer1); vba.Position<Float3>(0) = Float3(-1.0f, 0.0f, -1.0f); vba.Position<Float3>(1) = Float3(-1.0f, 0.0f, +1.0f); vba.Position<Float3>(2) = Float3(+1.0f, 0.0f, +1.0f); vba.Position<Float3>(3) = Float3(+1.0f, 0.0f, -1.0f); vba.Color<Float3>(0, 0) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 1) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 2) = Float3(0.0f, 1.0f, 0.0f); vba.Color<Float3>(0, 3) = Float3(0.0f, 1.0f, 0.0f); // Indices to be shared by all rectangles. IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int)); int* indices = (int*)ibuffer->GetData(); indices[0] = 0; indices[1] = 1; indices[2] = 3; indices[3] = 3; indices[4] = 1; indices[5] = 2; // Effect to be shared by the first three rectangles. VertexColor3Effect* effect = new0 VertexColor3Effect(); // rectangle 1 TriMesh* mesh = new0 TriMesh(vformat, vbuffer0, ibuffer); mesh->SetEffectInstance(effect->CreateInstance()); mesh->LocalTransform.SetTranslate(APoint(+2.0f, -4.0f, 0.0f)); mScene->AttachChild(mesh); // rectangle 2 mesh = new0 TriMesh(vformat, vbuffer1, ibuffer); mesh->SetEffectInstance(effect->CreateInstance()); mesh->LocalTransform.SetTranslate(APoint(+2.0f, -4.0f, 0.0f)); mesh->LocalTransform.SetUniformScale(0.5f); mScene->AttachChild(mesh); // rectangle 3 mesh = new0 TriMesh(vformat, vbuffer0, ibuffer); mesh->SetEffectInstance(effect->CreateInstance()); mesh->LocalTransform.SetTranslate(APoint(-2.0f, -4.0f, 0.0f)); mScene->AttachChild(mesh); // rectangle 4 mesh = new0 TriMesh(vformat, vbuffer1, ibuffer); mesh->LocalTransform.SetTranslate(APoint(-2.0f, -4.0f, 0.0f)); mesh->LocalTransform.SetUniformScale(0.5f); mScene->AttachChild(mesh); // Set up the polygon offset for rectangle 4. effect = new0 VertexColor3Effect(); OffsetState* ostate = effect->GetOffsetState(0, 0); ostate->FillEnabled = true; ostate->Scale = -1.0f; ostate->Bias = -2.0f; mesh->SetEffectInstance(effect->CreateInstance()); }
//---------------------------------------------------------------------------- Node* SimplePendulumFriction::CreatePendulum () { VertexFormat* vformat = VertexFormat::Create(2, VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0, VertexFormat::AU_NORMAL, VertexFormat::AT_FLOAT3, 0); StandardMesh sm(vformat); // Pendulum rod. TriMesh* rod = sm.Cylinder(2, 8, 0.05f, 12.0f, true); rod->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 10.0f)); // The pendulum bulb. Start with a sphere (to get the connectivity) and // then adjust the vertices to form a pair of joined cones. TriMesh* bulb = sm.Sphere(16, 32, 2.0f); VertexBufferAccessor vba(bulb); int numVertices = vba.GetNumVertices(); int i; for (i = 0; i < numVertices; ++i) { Float3& pos = vba.Position<Float3>(i); float r = Mathf::Sqrt(pos[0]*pos[0] + pos[1]*pos[1]); float z = pos[2] + 2.0f; if (z >= 2.0f) { z = 4.0f - r; } else { z = r; } pos[2] = z; } // Translate the pendulum joint to the origin for the purpose of // rotation. for (i = 0; i < numVertices; ++i) { vba.Position<Float3>(i)[2] -= 16.0f; } bulb->UpdateModelSpace(Visual::GU_NORMALS); vba.ApplyTo(rod); numVertices = vba.GetNumVertices(); for (i = 0; i < numVertices; ++i) { vba.Position<Float3>(i)[2] -= 16.0f; } rod->UpdateModelSpace(Visual::GU_NORMALS); // Group the objects into a single subtree. mPendulum = new0 Node(); mPendulum->AttachChild(rod); mPendulum->AttachChild(bulb); // Translate back to original model position. mPendulum->LocalTransform.SetTranslate(APoint(0.0f, 0.0f, 16.0f)); // Add a material for coloring. Float4 black(0.0f, 0.0f, 0.0f, 1.0f); Float4 white(1.0f, 1.0f, 1.0f, 1.0f); Material* material = new0 Material(); material->Emissive = black; material->Ambient = Float4(0.1f, 0.1f, 0.1f, 1.0f); material->Diffuse = Float4(0.99607f, 0.83920f, 0.67059f, 1.0f); material->Specular = black; // Use two lights to illuminate the pendulum. Light* light[2]; light[0] = new0 Light(Light::LT_DIRECTIONAL); light[0]->Ambient = white; light[0]->Diffuse = white; light[0]->Specular = black; light[0]->SetDirection(AVector(-1.0f, -1.0f, 0.0f)); light[1] = new0 Light(Light::LT_DIRECTIONAL); light[1]->Ambient = white; light[1]->Diffuse = white; light[1]->Specular = black; light[1]->SetDirection(AVector(+1.0f, -1.0f, 0.0f)); // TODO: The following code is used to piece together an effect with // two passes. It is better to write an effect whose vertex shader // has constants corresponding to the two lights (for a single-pass // effect). LightDirPerVerEffect* effect = new0 LightDirPerVerEffect(); VisualTechnique* technique = effect->GetTechnique(0); VisualPass* pass0 = technique->GetPass(0); VisualPass* pass1 = new0 VisualPass(); pass1->SetVertexShader(pass0->GetVertexShader()); pass1->SetPixelShader(pass0->GetPixelShader()); AlphaState* astate = new0 AlphaState(); astate->BlendEnabled = true; astate->SrcBlend = AlphaState::SBM_ONE; astate->DstBlend = AlphaState::DBM_ONE; pass1->SetAlphaState(astate); pass1->SetCullState(pass0->GetCullState()); pass1->SetDepthState(pass0->GetDepthState()); pass1->SetStencilState(pass0->GetStencilState()); pass1->SetOffsetState(pass0->GetOffsetState()); pass1->SetWireState(pass0->GetWireState()); technique->InsertPass(pass1); VisualEffectInstance* instance = new0 VisualEffectInstance(effect, 0); for (int pass = 0; pass < 2; ++pass) { instance->SetVertexConstant(pass, 0, new0 PVWMatrixConstant()); instance->SetVertexConstant(pass, 1, new0 CameraModelPositionConstant()); instance->SetVertexConstant(pass, 2, new0 MaterialEmissiveConstant(material)); instance->SetVertexConstant(pass, 3, new0 MaterialAmbientConstant(material)); instance->SetVertexConstant(pass, 4, new0 MaterialDiffuseConstant(material)); instance->SetVertexConstant(pass, 5, new0 MaterialSpecularConstant(material)); instance->SetVertexConstant(pass, 6, new0 LightModelDVectorConstant(light[pass])); instance->SetVertexConstant(pass, 7, new0 LightAmbientConstant(light[pass])); instance->SetVertexConstant(pass, 8, new0 LightDiffuseConstant(light[pass])); instance->SetVertexConstant(pass, 9, new0 LightSpecularConstant(light[pass])); instance->SetVertexConstant(pass, 10, new0 LightAttenuationConstant(light[pass])); } rod->SetEffectInstance(instance); bulb->SetEffectInstance(instance); return mPendulum; }