2010/11/15 天亮damody <t1238142000@xxxxxxxxx> > 各位同學大家好: > 助教我"黃亮軒"申請了一個maillist來跟大家討論, > 所謂的maillist就是你寄給ntustgraphics99@xxxxxxxxxxxxx的信,助教能看到,大家也能看到, > 我回的信大家也都能收到,這樣就比較不會有重複的問題一直問,別人問助教得到的結果,其它人不知道等問題, > 希望大家多多利用這個資源多多討論^^ > 最後給大家一點參考如何切點跟看正面 > Frustum.h是給大家一點參考 > 決定視野內的點最好還是用投影片上的ccw比較準。 > > 下面是簡單用視野去切點,但沒有寫怎麼找到要畫的邊切好的兩點。 > void Maze:: > Draw_View(const float focal_dist) > //====================================================================== > { > using namespace std; > frame_num++; > LineSeg line(view_cell->edges[0]); > cout << line.start[0] << " " << line.start[1] << " " << line.end[0] << > " " << line.end[1] << endl; > point clip1, clip2; > Frustum viewf(viewer_dir, viewer_fov, viewer_posn[X], viewer_posn[Y]); > clip1 = line.Cross_Param_point(viewf.edgelines[0]); //clip1 左邊切到的點 > float bill = viewf.edgelines[0].Cross_Param(line); > float bill2 = viewf.edgelines[1].Cross_Param(line); > clip2 = line.Cross_Param_point(viewf.edgelines[1]); //clip2 右邊切到的點 > if (bill>0 && bill<1 || bill2>0 && bill2<1) > cout << clip1.x << " " << clip1.y << " " << clip2.x << " " << > clip2.y << endl; > else > cout << "error : " << bill << " " << bill2 << endl; > } > > > -- > 有心情就是有壓力^^ > -- 有心情就是有壓力^^
#pragma once #include "LineSeg.h" #include <cmath> static double rad(double num) { return num / 180.0 * 3.14159; }; static double deg(double num) { return num * 180.0 / 3.14159; }; static float rad(float num) { return (float)(num / 180.0 * 3.14159); }; static float deg(float num) { return (float)(num * 180.0 / 3.14159); }; class Frustum { public: LineSeg edgelines[2]; Frustum(float viewangle, float fov, float pos_x, float pos_y) { edgelines[0] = LineSeg(pos_x, pos_y, pos_x + 1*cos( rad(viewangle - fov/2) ), pos_y + 1*sin( rad(viewangle - fov/2) )); edgelines[0].end[0] += (edgelines[0].end[0]-edgelines[0].start[0])*100; edgelines[0].end[1] += (edgelines[0].end[1]-edgelines[0].start[1])*100; edgelines[1] = LineSeg(pos_x, pos_y, pos_x + 1*cos( rad(viewangle + fov/2) ), pos_y + 1*sin( rad(viewangle + fov/2) )); edgelines[1].end[0] += (edgelines[1].end[0]-edgelines[1].start[0])*100; edgelines[1].end[1] += (edgelines[1].end[1]-edgelines[1].start[1])*100; } Frustum(float start_x, float start_y, float right_end_x, float right_end_y, float left_end_x, float left_end_y) { edgelines[0] = LineSeg( start_x,start_y,right_end_x,right_end_y); edgelines[0].end[0] += (edgelines[0].end[0]-edgelines[0].start[0])*100; edgelines[0].end[1] += (edgelines[0].end[1]-edgelines[0].start[1])*100; edgelines[1] = LineSeg( start_x,start_y,left_end_x,left_end_y); edgelines[1].end[0] += (edgelines[1].end[0]-edgelines[1].start[0])*100; edgelines[1].end[1] += (edgelines[1].end[1]-edgelines[1].start[1])*100; } };
/************************************************************************ File: LineSeg.cpp Author: Stephen Chenney, schenney@xxxxxxxxxxx Modifier Yu-Chi Lai, yu-chi@xxxxxxxxxxx Comment: (c) 2001-2002 Stephen Chenney, University of Wisconsin at Madison Class header file for LineSeg class. Platform: Visio Studio.Net 2003 (converted to 2005) *************************************************************************/ #include "LineSeg.h" //********************************************************************** // // * Constructor from an edge //====================================================================== LineSeg:: LineSeg(Edge *e) //====================================================================== { start[0] = e->endpoints[Edge::START]->posn[Vertex::X]; start[1] = e->endpoints[Edge::START]->posn[Vertex::Y]; end[0] = e->endpoints[Edge::END]->posn[Vertex::X]; end[1] = e->endpoints[Edge::END]->posn[Vertex::Y]; } //********************************************************************** // // * Constructor for specifyng start and end point //====================================================================== LineSeg:: LineSeg(float xs, float ys, float xe, float ye) //====================================================================== { start[0] = xs; start[1] = ys; end[0] = xe; end[1] = ye; } //********************************************************************** // // * Return the parameter value at which this segment crosses the given // segment. This will return parameter values outside the range 0,1 // THIS FUNCTION IS EXTREMELY USEFUL FOR CLIPPING, but it // DOES NOT tell you whether the edge is "entering" or "leaving". // But you can use tests like Edge::Point_Side() to figure that out. //====================================================================== float LineSeg:: Cross_Param(LineSeg e) //====================================================================== { float dx1, dy1, dx2, dy2; float denom, s; // This computation comes from writing each segment in parametric form, // and solving a simulataneous equation to determine the parameter // value of the intersection point on this LineSeg. dx1 = e.end[0] - e.start[0]; dy1 = e.end[1] - e.start[1]; dx2 = end[0] - start[0]; dy2 = end[1] - start[1]; if ( ( denom = dx2 * dy1 - dy2 * dx1 ) == 0.0 ) // Parallel segments. return 1.0e20f; s = ( e.start[0] - start[0] ) * dy1 - ( e.start[1] - start[1] ) * dx1; return s / denom; } point LineSeg:: Cross_Param_point(LineSeg e) //====================================================================== { float dx1, dy1, dx2, dy2; float denom, s; // This computation comes from writing each segment in parametric form, // and solving a simulataneous equation to determine the parameter // value of the intersection point on this LineSeg. dx1 = e.end[0] - e.start[0]; dy1 = e.end[1] - e.start[1]; dx2 = end[0] - start[0]; dy2 = end[1] - start[1]; if ( ( denom = dx2 * dy1 - dy2 * dx1 ) == 0.0 ) // Parallel segments. denom = 0.01; s = ( e.start[0] - start[0] ) * dy1 - ( e.start[1] - start[1] ) * dx1; float balance = s / denom; point res(start[0] + ( end[0] - start[0] ) * balance, start[1] + ( end[1] - start[1] ) * balance); return res; }
/************************************************************************ File: LineSeg.h Author: Stephen Chenney, schenney@xxxxxxxxxxx Modifier Yu-Chi Lai, yu-chi@xxxxxxxxxxx Comment: (c) 2001-2002 Stephen Chenney, University of Wisconsin at Madison Class header file for LineSeg class. Platform: Visio Studio.Net 2003 (converted to 2005) *************************************************************************/ #ifndef _LINESEG_H_ #define _LINESEG_H_ #include "Edge.h" struct point { point(){} point(float _x, float _y):x(_x),y(_y) {} float x,y; }; class LineSeg { public: // First constructor takes the endpoints. LineSeg(float xs, float ys, float xe, float ye); // Second constructor takes an edge. The LineSeg created has the same // start and end points as the edge. LineSeg(Edge*); LineSeg(){} public: // Return the parameter value at which this segment crosses the given // segment. This will return parameter values outside the range 0,1 // THIS FUNCTION IS EXTREMELY USEFUL FOR CLIPPING, but it // DOES NOT tell you whether the edge is "entering" or "leaving". // But you can use tests like Edge::Point_Side() to figure that out. float Cross_Param(LineSeg); point Cross_Param_point(LineSeg); public: float start[2]; // Starting point, x and y. float end[2]; // Ending point, x and y. }; #endif