diff options
author | Diva Canto | 2010-05-07 21:29:56 -0700 |
---|---|---|
committer | Diva Canto | 2010-05-07 21:29:56 -0700 |
commit | a58859a0d4206c194c9c56212218e2cafc2cc373 (patch) | |
tree | fed51a4e40c344b76f6b8b4d5c5b2ec0d2e142e4 /OpenSim | |
parent | improve handling of undersize sculpt textures (diff) | |
download | opensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.zip opensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.tar.gz opensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.tar.bz2 opensim-SC_OLD-a58859a0d4206c194c9c56212218e2cafc2cc373.tar.xz |
GridUserService in place. Replaces the contrived concept of storing user's home and position info in the presence service. WARNING: I violated a taboo by deleting 2 migration files and simplifying the original table creation for Presence. This should not cause any problems to anyone, though. Things will work with the new simplified table, as well as with the previous contrived one. If there are any problems, solving them is as easy as dropping the presence table and deleting its row in the migrations table. The presence info only exists during a user's session anyway.
BTW, the Meshing files want to be committed too -- EOFs.
Diffstat (limited to 'OpenSim')
36 files changed, 3700 insertions, 3655 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 5a23c90..13f9c9f 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs | |||
@@ -1611,7 +1611,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController | |||
1611 | GridRegion home = m_app.SceneManager.CurrentOrFirstScene.GridService.GetRegionByPosition(scopeID, | 1611 | GridRegion home = m_app.SceneManager.CurrentOrFirstScene.GridService.GetRegionByPosition(scopeID, |
1612 | (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); | 1612 | (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); |
1613 | if (home != null) | 1613 | if (home != null) |
1614 | m_app.SceneManager.CurrentOrFirstScene.PresenceService.SetHomeLocation(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); | 1614 | m_app.SceneManager.CurrentOrFirstScene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); |
1615 | } | 1615 | } |
1616 | else | 1616 | else |
1617 | { | 1617 | { |
diff --git a/OpenSim/Data/IGridUserData.cs b/OpenSim/Data/IGridUserData.cs index bd7a435..e15a1f8 100644 --- a/OpenSim/Data/IGridUserData.cs +++ b/OpenSim/Data/IGridUserData.cs | |||
@@ -37,6 +37,11 @@ namespace OpenSim.Data | |||
37 | { | 37 | { |
38 | public string UserID; | 38 | public string UserID; |
39 | public Dictionary<string, string> Data; | 39 | public Dictionary<string, string> Data; |
40 | |||
41 | public GridUserData() | ||
42 | { | ||
43 | Data = new Dictionary<string, string>(); | ||
44 | } | ||
40 | } | 45 | } |
41 | 46 | ||
42 | /// <summary> | 47 | /// <summary> |
@@ -44,7 +49,7 @@ namespace OpenSim.Data | |||
44 | /// </summary> | 49 | /// </summary> |
45 | public interface IGridUserData | 50 | public interface IGridUserData |
46 | { | 51 | { |
47 | GridUserData GetGridUserData(string userID); | 52 | GridUserData Get(string userID); |
48 | bool StoreGridUserData(GridUserData data); | 53 | bool Store(GridUserData data); |
49 | } | 54 | } |
50 | } \ No newline at end of file | 55 | } \ No newline at end of file |
diff --git a/OpenSim/Data/IPresenceData.cs b/OpenSim/Data/IPresenceData.cs index 71d0e31..b871f56 100644 --- a/OpenSim/Data/IPresenceData.cs +++ b/OpenSim/Data/IPresenceData.cs | |||
@@ -50,10 +50,8 @@ namespace OpenSim.Data | |||
50 | 50 | ||
51 | PresenceData Get(UUID sessionID); | 51 | PresenceData Get(UUID sessionID); |
52 | void LogoutRegionAgents(UUID regionID); | 52 | void LogoutRegionAgents(UUID regionID); |
53 | bool ReportAgent(UUID sessionID, UUID regionID, string position, string lookAt); | 53 | bool ReportAgent(UUID sessionID, UUID regionID); |
54 | bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt); | ||
55 | PresenceData[] Get(string field, string data); | 54 | PresenceData[] Get(string field, string data); |
56 | void Prune(string userID); | ||
57 | bool Delete(string field, string val); | 55 | bool Delete(string field, string val); |
58 | } | 56 | } |
59 | } | 57 | } |
diff --git a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs index 9993720..1870273 100644 --- a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs +++ b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs | |||
@@ -46,11 +46,11 @@ namespace OpenSim.Data.MSSQL | |||
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
47 | 47 | ||
48 | public MSSQLGridUserData(string connectionString, string realm) : | 48 | public MSSQLGridUserData(string connectionString, string realm) : |
49 | base(connectionString, realm, "UserGrid") | 49 | base(connectionString, realm, "GridUserStore") |
50 | { | 50 | { |
51 | } | 51 | } |
52 | 52 | ||
53 | public GridUserData GetGridUserData(string userID) | 53 | public GridUserData Get(string userID) |
54 | { | 54 | { |
55 | GridUserData[] ret = Get("UserID", userID); | 55 | GridUserData[] ret = Get("UserID", userID); |
56 | 56 | ||
@@ -60,9 +60,5 @@ namespace OpenSim.Data.MSSQL | |||
60 | return ret[0]; | 60 | return ret[0]; |
61 | } | 61 | } |
62 | 62 | ||
63 | public bool StoreGridUserData(GridUserData data) | ||
64 | { | ||
65 | return Store(data); | ||
66 | } | ||
67 | } | 63 | } |
68 | } | 64 | } |
diff --git a/OpenSim/Data/MSSQL/MSSQLPresenceData.cs b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs index 5a4ad3a..e7b3d9c 100644 --- a/OpenSim/Data/MSSQL/MSSQLPresenceData.cs +++ b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs | |||
@@ -67,7 +67,7 @@ namespace OpenSim.Data.MSSQL | |||
67 | using (SqlCommand cmd = new SqlCommand()) | 67 | using (SqlCommand cmd = new SqlCommand()) |
68 | { | 68 | { |
69 | 69 | ||
70 | cmd.CommandText = String.Format("UPDATE {0} SET Online='false' WHERE [RegionID]=@RegionID", m_Realm); | 70 | cmd.CommandText = String.Format("DELETE FROM {0} WHERE [RegionID]=@RegionID", m_Realm); |
71 | 71 | ||
72 | cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString())); | 72 | cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString())); |
73 | cmd.Connection = conn; | 73 | cmd.Connection = conn; |
@@ -76,8 +76,7 @@ namespace OpenSim.Data.MSSQL | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | public bool ReportAgent(UUID sessionID, UUID regionID, string position, | 79 | public bool ReportAgent(UUID sessionID, UUID regionID) |
80 | string lookAt) | ||
81 | { | 80 | { |
82 | PresenceData[] pd = Get("SessionID", sessionID.ToString()); | 81 | PresenceData[] pd = Get("SessionID", sessionID.ToString()); |
83 | if (pd.Length == 0) | 82 | if (pd.Length == 0) |
@@ -88,16 +87,11 @@ namespace OpenSim.Data.MSSQL | |||
88 | { | 87 | { |
89 | 88 | ||
90 | cmd.CommandText = String.Format(@"UPDATE {0} SET | 89 | cmd.CommandText = String.Format(@"UPDATE {0} SET |
91 | [RegionID] = @RegionID, | 90 | [RegionID] = @RegionID |
92 | [Position] = @Position, | ||
93 | [LookAt] = @LookAt, | ||
94 | [Online] = 'true' | ||
95 | WHERE [SessionID] = @SessionID", m_Realm); | 91 | WHERE [SessionID] = @SessionID", m_Realm); |
96 | 92 | ||
97 | cmd.Parameters.Add(m_database.CreateParameter("@SessionID", sessionID.ToString())); | 93 | cmd.Parameters.Add(m_database.CreateParameter("@SessionID", sessionID.ToString())); |
98 | cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString())); | 94 | cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString())); |
99 | cmd.Parameters.Add(m_database.CreateParameter("@Position", position.ToString())); | ||
100 | cmd.Parameters.Add(m_database.CreateParameter("@LookAt", lookAt.ToString())); | ||
101 | cmd.Connection = conn; | 95 | cmd.Connection = conn; |
102 | conn.Open(); | 96 | conn.Open(); |
103 | if (cmd.ExecuteNonQuery() == 0) | 97 | if (cmd.ExecuteNonQuery() == 0) |
@@ -106,65 +100,5 @@ namespace OpenSim.Data.MSSQL | |||
106 | return true; | 100 | return true; |
107 | } | 101 | } |
108 | 102 | ||
109 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
110 | { | ||
111 | PresenceData[] pd = Get("UserID", userID); | ||
112 | if (pd.Length == 0) | ||
113 | return false; | ||
114 | |||
115 | using (SqlConnection conn = new SqlConnection(m_ConnectionString)) | ||
116 | using (SqlCommand cmd = new SqlCommand()) | ||
117 | { | ||
118 | |||
119 | cmd.CommandText = String.Format(@"UPDATE {0} SET | ||
120 | [HomeRegionID] = @HomeRegionID, | ||
121 | [HomePosition] = @HomePosition, | ||
122 | [HomeLookAt] = @HomeLookAt | ||
123 | WHERE [UserID] = @UserID", m_Realm); | ||
124 | |||
125 | cmd.Parameters.Add(m_database.CreateParameter("@UserID", userID)); | ||
126 | cmd.Parameters.Add(m_database.CreateParameter("@HomeRegionID", regionID.ToString())); | ||
127 | cmd.Parameters.Add(m_database.CreateParameter("@HomePosition", position)); | ||
128 | cmd.Parameters.Add(m_database.CreateParameter("@HomeLookAt", lookAt)); | ||
129 | cmd.Connection = conn; | ||
130 | conn.Open(); | ||
131 | if (cmd.ExecuteNonQuery() == 0) | ||
132 | return false; | ||
133 | } | ||
134 | return true; | ||
135 | } | ||
136 | |||
137 | public void Prune(string userID) | ||
138 | { | ||
139 | using (SqlConnection conn = new SqlConnection(m_ConnectionString)) | ||
140 | using (SqlCommand cmd = new SqlCommand()) | ||
141 | { | ||
142 | cmd.CommandText = String.Format("SELECT * from {0} WHERE [UserID] = @UserID", m_Realm); | ||
143 | |||
144 | cmd.Parameters.Add(m_database.CreateParameter("@UserID", userID)); | ||
145 | cmd.Connection = conn; | ||
146 | conn.Open(); | ||
147 | |||
148 | using (SqlDataReader reader = cmd.ExecuteReader()) | ||
149 | { | ||
150 | List<UUID> deleteSessions = new List<UUID>(); | ||
151 | int online = 0; | ||
152 | |||
153 | while (reader.Read()) | ||
154 | { | ||
155 | if (bool.Parse(reader["Online"].ToString())) | ||
156 | online++; | ||
157 | else | ||
158 | deleteSessions.Add(new UUID(reader["SessionID"].ToString())); | ||
159 | } | ||
160 | |||
161 | if (online == 0 && deleteSessions.Count > 0) | ||
162 | deleteSessions.RemoveAt(0); | ||
163 | |||
164 | foreach (UUID s in deleteSessions) | ||
165 | Delete("SessionID", s.ToString()); | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | } | 103 | } |
170 | } | 104 | } |
diff --git a/OpenSim/Data/MySQL/MySQLGridUserData.cs b/OpenSim/Data/MySQL/MySQLGridUserData.cs index df29ecd..a9ce94d 100644 --- a/OpenSim/Data/MySQL/MySQLGridUserData.cs +++ b/OpenSim/Data/MySQL/MySQLGridUserData.cs | |||
@@ -44,9 +44,9 @@ namespace OpenSim.Data.MySQL | |||
44 | { | 44 | { |
45 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 46 | ||
47 | public MySQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "UserGrid") {} | 47 | public MySQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "GridUserStore") {} |
48 | 48 | ||
49 | public GridUserData GetGridUserData(string userID) | 49 | public GridUserData Get(string userID) |
50 | { | 50 | { |
51 | GridUserData[] ret = Get("UserID", userID); | 51 | GridUserData[] ret = Get("UserID", userID); |
52 | 52 | ||
@@ -56,9 +56,6 @@ namespace OpenSim.Data.MySQL | |||
56 | return ret[0]; | 56 | return ret[0]; |
57 | } | 57 | } |
58 | 58 | ||
59 | public bool StoreGridUserData(GridUserData data) | 59 | |
60 | { | ||
61 | return Store(data); | ||
62 | } | ||
63 | } | 60 | } |
64 | } \ No newline at end of file | 61 | } \ No newline at end of file |
diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs index 143dbe3..71caa1a 100644 --- a/OpenSim/Data/MySQL/MySQLPresenceData.cs +++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs | |||
@@ -65,15 +65,14 @@ namespace OpenSim.Data.MySQL | |||
65 | { | 65 | { |
66 | MySqlCommand cmd = new MySqlCommand(); | 66 | MySqlCommand cmd = new MySqlCommand(); |
67 | 67 | ||
68 | cmd.CommandText = String.Format("update {0} set Online='false' where `RegionID`=?RegionID", m_Realm); | 68 | cmd.CommandText = String.Format("delete from {0} where `RegionID`=?RegionID", m_Realm); |
69 | 69 | ||
70 | cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); | 70 | cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); |
71 | 71 | ||
72 | ExecuteNonQuery(cmd); | 72 | ExecuteNonQuery(cmd); |
73 | } | 73 | } |
74 | 74 | ||
75 | public bool ReportAgent(UUID sessionID, UUID regionID, string position, | 75 | public bool ReportAgent(UUID sessionID, UUID regionID) |
76 | string lookAt) | ||
77 | { | 76 | { |
78 | PresenceData[] pd = Get("SessionID", sessionID.ToString()); | 77 | PresenceData[] pd = Get("SessionID", sessionID.ToString()); |
79 | if (pd.Length == 0) | 78 | if (pd.Length == 0) |
@@ -81,12 +80,10 @@ namespace OpenSim.Data.MySQL | |||
81 | 80 | ||
82 | MySqlCommand cmd = new MySqlCommand(); | 81 | MySqlCommand cmd = new MySqlCommand(); |
83 | 82 | ||
84 | cmd.CommandText = String.Format("update {0} set RegionID=?RegionID, Position=?Position, LookAt=?LookAt, Online='true' where `SessionID`=?SessionID", m_Realm); | 83 | cmd.CommandText = String.Format("update {0} set RegionID=?RegionID where `SessionID`=?SessionID", m_Realm); |
85 | 84 | ||
86 | cmd.Parameters.AddWithValue("?SessionID", sessionID.ToString()); | 85 | cmd.Parameters.AddWithValue("?SessionID", sessionID.ToString()); |
87 | cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); | 86 | cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); |
88 | cmd.Parameters.AddWithValue("?Position", position.ToString()); | ||
89 | cmd.Parameters.AddWithValue("?LookAt", lookAt.ToString()); | ||
90 | 87 | ||
91 | if (ExecuteNonQuery(cmd) == 0) | 88 | if (ExecuteNonQuery(cmd) == 0) |
92 | return false; | 89 | return false; |
@@ -94,62 +91,5 @@ namespace OpenSim.Data.MySQL | |||
94 | return true; | 91 | return true; |
95 | } | 92 | } |
96 | 93 | ||
97 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
98 | { | ||
99 | PresenceData[] pd = Get("UserID", userID); | ||
100 | if (pd.Length == 0) | ||
101 | return false; | ||
102 | |||
103 | MySqlCommand cmd = new MySqlCommand(); | ||
104 | |||
105 | cmd.CommandText = String.Format("update {0} set HomeRegionID=?HomeRegionID, HomePosition=?HomePosition, HomeLookAt=?HomeLookAt where UserID=?UserID", m_Realm); | ||
106 | |||
107 | cmd.Parameters.AddWithValue("?UserID", userID); | ||
108 | cmd.Parameters.AddWithValue("?HomeRegionID", regionID.ToString()); | ||
109 | cmd.Parameters.AddWithValue("?HomePosition", position); | ||
110 | cmd.Parameters.AddWithValue("?HomeLookAt", lookAt); | ||
111 | |||
112 | if (ExecuteNonQuery(cmd) == 0) | ||
113 | return false; | ||
114 | |||
115 | return true; | ||
116 | } | ||
117 | |||
118 | public void Prune(string userID) | ||
119 | { | ||
120 | MySqlCommand cmd = new MySqlCommand(); | ||
121 | |||
122 | cmd.CommandText = String.Format("select * from {0} where UserID=?UserID", m_Realm); | ||
123 | |||
124 | cmd.Parameters.AddWithValue("?UserID", userID); | ||
125 | |||
126 | using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) | ||
127 | { | ||
128 | dbcon.Open(); | ||
129 | |||
130 | cmd.Connection = dbcon; | ||
131 | |||
132 | using (IDataReader reader = cmd.ExecuteReader()) | ||
133 | { | ||
134 | List<UUID> deleteSessions = new List<UUID>(); | ||
135 | int online = 0; | ||
136 | |||
137 | while (reader.Read()) | ||
138 | { | ||
139 | if (bool.Parse(reader["Online"].ToString())) | ||
140 | online++; | ||
141 | else | ||
142 | deleteSessions.Add(new UUID(reader["SessionID"].ToString())); | ||
143 | } | ||
144 | |||
145 | // Leave one session behind so that we can pick up details such as home location | ||
146 | if (online == 0 && deleteSessions.Count > 0) | ||
147 | deleteSessions.RemoveAt(0); | ||
148 | |||
149 | foreach (UUID s in deleteSessions) | ||
150 | Delete("SessionID", s.ToString()); | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | } | 94 | } |
155 | } | 95 | } |
diff --git a/OpenSim/Data/MySQL/Resources/001_Presence.sql b/OpenSim/Data/MySQL/Resources/001_Presence.sql index b8abaf7..84fa057 100644 --- a/OpenSim/Data/MySQL/Resources/001_Presence.sql +++ b/OpenSim/Data/MySQL/Resources/001_Presence.sql | |||
@@ -4,12 +4,10 @@ CREATE TABLE `Presence` ( | |||
4 | `UserID` VARCHAR(255) NOT NULL, | 4 | `UserID` VARCHAR(255) NOT NULL, |
5 | `RegionID` CHAR(36) NOT NULL, | 5 | `RegionID` CHAR(36) NOT NULL, |
6 | `SessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', | 6 | `SessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', |
7 | `SecureSessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', | 7 | `SecureSessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000' |
8 | `Online` CHAR(5) NOT NULL DEFAULT 'false', | ||
9 | `Login` CHAR(16) NOT NULL DEFAULT '0', | ||
10 | `Logout` CHAR(16) NOT NULL DEFAULT '0', | ||
11 | `Position` CHAR(64) NOT NULL DEFAULT '<0,0,0>', | ||
12 | `LookAt` CHAR(64) NOT NULL DEFAULT '<0,0,0>' | ||
13 | ) ENGINE=InnoDB; | 8 | ) ENGINE=InnoDB; |
14 | 9 | ||
10 | CREATE UNIQUE INDEX SessionID ON Presence(SessionID); | ||
11 | CREATE INDEX UserID ON Presence(UserID); | ||
12 | |||
15 | COMMIT; | 13 | COMMIT; |
diff --git a/OpenSim/Data/MySQL/Resources/002_Presence.sql b/OpenSim/Data/MySQL/Resources/002_Presence.sql deleted file mode 100644 index e65f105..0000000 --- a/OpenSim/Data/MySQL/Resources/002_Presence.sql +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | BEGIN; | ||
2 | |||
3 | ALTER TABLE Presence ADD COLUMN `HomeRegionID` CHAR(36) NOT NULL; | ||
4 | ALTER TABLE Presence ADD COLUMN `HomePosition` CHAR(64) NOT NULL DEFAULT '<0,0,0>'; | ||
5 | ALTER TABLE Presence ADD COLUMN `HomeLookAt` CHAR(64) NOT NULL DEFAULT '<0,0,0>'; | ||
6 | |||
7 | COMMIT; | ||
diff --git a/OpenSim/Data/MySQL/Resources/003_Presence.sql b/OpenSim/Data/MySQL/Resources/003_Presence.sql deleted file mode 100644 index 0efefa8..0000000 --- a/OpenSim/Data/MySQL/Resources/003_Presence.sql +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | BEGIN; | ||
2 | |||
3 | CREATE UNIQUE INDEX SessionID ON Presence(SessionID); | ||
4 | CREATE INDEX UserID ON Presence(UserID); | ||
5 | |||
6 | COMMIT; | ||
diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs index b98b5c9..91f1cc5 100644 --- a/OpenSim/Data/Null/NullPresenceData.cs +++ b/OpenSim/Data/Null/NullPresenceData.cs | |||
@@ -96,45 +96,20 @@ namespace OpenSim.Data.Null | |||
96 | m_presenceData.Remove(u); | 96 | m_presenceData.Remove(u); |
97 | } | 97 | } |
98 | 98 | ||
99 | public bool ReportAgent(UUID sessionID, UUID regionID, string position, string lookAt) | 99 | public bool ReportAgent(UUID sessionID, UUID regionID) |
100 | { | 100 | { |
101 | if (Instance != this) | 101 | if (Instance != this) |
102 | return Instance.ReportAgent(sessionID, regionID, position, lookAt); | 102 | return Instance.ReportAgent(sessionID, regionID); |
103 | 103 | ||
104 | if (m_presenceData.ContainsKey(sessionID)) | 104 | if (m_presenceData.ContainsKey(sessionID)) |
105 | { | 105 | { |
106 | m_presenceData[sessionID].RegionID = regionID; | 106 | m_presenceData[sessionID].RegionID = regionID; |
107 | m_presenceData[sessionID].Data["Position"] = position; | ||
108 | m_presenceData[sessionID].Data["LookAt"] = lookAt; | ||
109 | return true; | 107 | return true; |
110 | } | 108 | } |
111 | 109 | ||
112 | return false; | 110 | return false; |
113 | } | 111 | } |
114 | 112 | ||
115 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
116 | { | ||
117 | if (Instance != this) | ||
118 | return Instance.SetHomeLocation(userID, regionID, position, lookAt); | ||
119 | |||
120 | bool foundone = false; | ||
121 | foreach (PresenceData p in m_presenceData.Values) | ||
122 | { | ||
123 | if (p.UserID == userID) | ||
124 | { | ||
125 | // m_log.DebugFormat( | ||
126 | // "[NULL PRESENCE DATA]: Setting home location {0} {1} {2} for {3}", | ||
127 | // regionID, position, lookAt, p.UserID); | ||
128 | |||
129 | p.Data["HomeRegionID"] = regionID.ToString(); | ||
130 | p.Data["HomePosition"] = position.ToString(); | ||
131 | p.Data["HomeLookAt"] = lookAt.ToString(); | ||
132 | foundone = true; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | return foundone; | ||
137 | } | ||
138 | 113 | ||
139 | public PresenceData[] Get(string field, string data) | 114 | public PresenceData[] Get(string field, string data) |
140 | { | 115 | { |
@@ -193,39 +168,6 @@ namespace OpenSim.Data.Null | |||
193 | return presences.ToArray(); | 168 | return presences.ToArray(); |
194 | } | 169 | } |
195 | 170 | ||
196 | public void Prune(string userID) | ||
197 | { | ||
198 | if (Instance != this) | ||
199 | { | ||
200 | Instance.Prune(userID); | ||
201 | return; | ||
202 | } | ||
203 | |||
204 | // m_log.DebugFormat("[NULL PRESENCE DATA]: Prune called for {0}", userID); | ||
205 | |||
206 | List<UUID> deleteSessions = new List<UUID>(); | ||
207 | int online = 0; | ||
208 | |||
209 | foreach (KeyValuePair<UUID, PresenceData> kvp in m_presenceData) | ||
210 | { | ||
211 | // m_log.DebugFormat("Online: {0}", kvp.Value.Data["Online"]); | ||
212 | |||
213 | bool on = false; | ||
214 | if (bool.TryParse(kvp.Value.Data["Online"], out on) && on) | ||
215 | online++; | ||
216 | else | ||
217 | deleteSessions.Add(kvp.Key); | ||
218 | } | ||
219 | |||
220 | // m_log.DebugFormat("[NULL PRESENCE DATA]: online [{0}], deleteSession.Count [{1}]", online, deleteSessions.Count); | ||
221 | |||
222 | // Leave one session behind so that we can pick up details such as home location | ||
223 | if (online == 0 && deleteSessions.Count > 0) | ||
224 | deleteSessions.RemoveAt(0); | ||
225 | |||
226 | foreach (UUID s in deleteSessions) | ||
227 | m_presenceData.Remove(s); | ||
228 | } | ||
229 | 171 | ||
230 | public bool Delete(string field, string data) | 172 | public bool Delete(string field, string data) |
231 | { | 173 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index f2b03e4..ef37f63 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -526,11 +526,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
526 | { | 526 | { |
527 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); | 527 | m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); |
528 | 528 | ||
529 | OpenSim.Services.Interfaces.PresenceInfo pinfo = m_aScene.PresenceService.GetAgent(client.SessionId); | 529 | //OpenSim.Services.Interfaces.PresenceInfo pinfo = m_aScene.PresenceService.GetAgent(client.SessionId); |
530 | GridUserInfo uinfo = m_aScene.GridUserService.GetGridUserInfo(client.AgentId.ToString()); | ||
530 | 531 | ||
531 | if (pinfo != null) | 532 | if (uinfo != null) |
532 | { | 533 | { |
533 | GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, pinfo.HomeRegionID); | 534 | GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); |
534 | if (regionInfo == null) | 535 | if (regionInfo == null) |
535 | { | 536 | { |
536 | // can't find the Home region: Tell viewer and abort | 537 | // can't find the Home region: Tell viewer and abort |
@@ -539,7 +540,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
539 | } | 540 | } |
540 | // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point... | 541 | // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point... |
541 | ((Scene)(client.Scene)).RequestTeleportLocation( | 542 | ((Scene)(client.Scene)).RequestTeleportLocation( |
542 | client, regionInfo.RegionHandle, pinfo.HomePosition, pinfo.HomeLookAt, | 543 | client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt, |
543 | (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); | 544 | (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); |
544 | } | 545 | } |
545 | } | 546 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 28593fc..137dfec 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
154 | bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); | 154 | bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); |
155 | if (success) | 155 | if (success) |
156 | // Log them out of this grid | 156 | // Log them out of this grid |
157 | m_aScene.PresenceService.LogoutAgent(agentCircuit.SessionID, sp.AbsolutePosition, sp.Lookat); | 157 | m_aScene.PresenceService.LogoutAgent(agentCircuit.SessionID); |
158 | 158 | ||
159 | return success; | 159 | return success; |
160 | } | 160 | } |
@@ -238,6 +238,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
238 | { | 238 | { |
239 | if (obj.IsLoggingOut) | 239 | if (obj.IsLoggingOut) |
240 | { | 240 | { |
241 | object sp = null; | ||
242 | if (obj.Scene.TryGetScenePresence(obj.AgentId, out sp)) | ||
243 | { | ||
244 | if (((ScenePresence)sp).IsChildAgent) | ||
245 | return; | ||
246 | } | ||
247 | |||
241 | AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode); | 248 | AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode); |
242 | 249 | ||
243 | if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) | 250 | if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) |
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 0a5ff3f..ee07075 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml | |||
@@ -59,9 +59,11 @@ | |||
59 | <RegionModule id="RemoteUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.RemoteUserAccountServicesConnector" /> | 59 | <RegionModule id="RemoteUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.RemoteUserAccountServicesConnector" /> |
60 | 60 | ||
61 | <RegionModule id="LocalGridUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser.LocalGridUserServicesConnector" /> | 61 | <RegionModule id="LocalGridUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser.LocalGridUserServicesConnector" /> |
62 | 62 | <RegionModule id="RemoteGridUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser.RemoteGridUserServicesConnector" /> | |
63 | |||
63 | <RegionModule id="LocalSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.LocalSimulationConnectorModule" /> | 64 | <RegionModule id="LocalSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.LocalSimulationConnectorModule" /> |
64 | <RegionModule id="RemoteSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.RemoteSimulationConnectorModule" /> | 65 | <RegionModule id="RemoteSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.RemoteSimulationConnectorModule" /> |
66 | |||
65 | <!-- Service connectors IN modules --> | 67 | <!-- Service connectors IN modules --> |
66 | <RegionModule id="AssetServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset.AssetServiceInConnectorModule" /> | 68 | <RegionModule id="AssetServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset.AssetServiceInConnectorModule" /> |
67 | <RegionModule id="InventoryServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory.InventoryServiceInConnectorModule" /> | 69 | <RegionModule id="InventoryServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory.InventoryServiceInConnectorModule" /> |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs index d5fae23..d914a57 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs | |||
@@ -41,13 +41,19 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
41 | { | 41 | { |
42 | public class LocalGridUserServicesConnector : ISharedRegionModule, IGridUserService | 42 | public class LocalGridUserServicesConnector : ISharedRegionModule, IGridUserService |
43 | { | 43 | { |
44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = |
45 | LogManager.GetLogger( | ||
46 | MethodBase.GetCurrentMethod().DeclaringType); | ||
45 | 47 | ||
46 | private IGridUserService m_service; | 48 | private IGridUserService m_GridUserService; |
49 | |||
50 | private ActivityDetector m_ActivityDetector; | ||
47 | 51 | ||
48 | private bool m_Enabled = false; | 52 | private bool m_Enabled = false; |
49 | 53 | ||
50 | public Type ReplaceableInterface | 54 | #region ISharedRegionModule |
55 | |||
56 | public Type ReplaceableInterface | ||
51 | { | 57 | { |
52 | get { return null; } | 58 | get { return null; } |
53 | } | 59 | } |
@@ -68,7 +74,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
68 | IConfig userConfig = source.Configs["GridUserService"]; | 74 | IConfig userConfig = source.Configs["GridUserService"]; |
69 | if (userConfig == null) | 75 | if (userConfig == null) |
70 | { | 76 | { |
71 | m_log.Error("[LOCAL GRID USER SERVICE CONNECTOR]: GridUserService missing from ini files"); | 77 | m_log.Error("[LOCAL GRID USER SERVICE CONNECTOR]: GridUserService missing from OpenSim.ini"); |
72 | return; | 78 | return; |
73 | } | 79 | } |
74 | 80 | ||
@@ -81,15 +87,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
81 | } | 87 | } |
82 | 88 | ||
83 | Object[] args = new Object[] { source }; | 89 | Object[] args = new Object[] { source }; |
84 | m_service = ServerUtils.LoadPlugin<IGridUserService>(serviceDll, args); | 90 | m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(serviceDll, args); |
85 | 91 | ||
86 | if (m_service == null) | 92 | if (m_GridUserService == null) |
87 | { | 93 | { |
88 | m_log.Error("[LOCAL GRID USER SERVICE CONNECTOR]: Can't load GridUser service"); | 94 | m_log.ErrorFormat( |
95 | "[LOCAL GRID USER SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll); | ||
89 | return; | 96 | return; |
90 | } | 97 | } |
98 | |||
99 | m_ActivityDetector = new ActivityDetector(this); | ||
100 | |||
91 | m_Enabled = true; | 101 | m_Enabled = true; |
92 | m_log.Info("[LOCAL GRID USER SERVICE CONNECTOR]: Local GridUser connector enabled"); | 102 | |
103 | m_log.Info("[LOCAL GRID USER SERVICE CONNECTOR]: Local grid user connector enabled"); | ||
93 | } | 104 | } |
94 | } | 105 | } |
95 | } | 106 | } |
@@ -111,29 +122,57 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser | |||
111 | if (!m_Enabled) | 122 | if (!m_Enabled) |
112 | return; | 123 | return; |
113 | 124 | ||
114 | scene.RegisterModuleInterface<IGridUserService>(m_service); | 125 | scene.RegisterModuleInterface<IGridUserService>(m_GridUserService); |
126 | m_ActivityDetector.AddRegion(scene); | ||
115 | } | 127 | } |
116 | 128 | ||
117 | public void RemoveRegion(Scene scene) | 129 | public void RemoveRegion(Scene scene) |
118 | { | 130 | { |
119 | if (!m_Enabled) | 131 | if (!m_Enabled) |
120 | return; | 132 | return; |
133 | |||
134 | scene.UnregisterModuleInterface<IGridUserService>(this); | ||
135 | m_ActivityDetector.RemoveRegion(scene); | ||
121 | } | 136 | } |
122 | 137 | ||
123 | public void RegionLoaded(Scene scene) | 138 | public void RegionLoaded(Scene scene) |
124 | { | 139 | { |
125 | if (!m_Enabled) | 140 | if (!m_Enabled) |
126 | return; | 141 | return; |
142 | |||
143 | m_log.InfoFormat("[LOCAL GRID USER SERVICE CONNECTOR]: Enabled local grid user for region {0}", scene.RegionInfo.RegionName); | ||
127 | } | 144 | } |
128 | 145 | ||
129 | public GridUserInfo GetGridUserInfo(string userID) | 146 | #endregion |
147 | |||
148 | #region IGridUserService | ||
149 | |||
150 | public GridUserInfo LoggedIn(string userID) | ||
130 | { | 151 | { |
131 | return m_service.GetGridUserInfo(userID); | 152 | return m_GridUserService.LoggedIn(userID); |
132 | } | 153 | } |
133 | 154 | ||
134 | public bool StoreGridUserInfo(GridUserInfo info) | 155 | public bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) |
135 | { | 156 | { |
136 | return m_service.StoreGridUserInfo(info); | 157 | return m_GridUserService.LoggedOut(userID, regionID, lastPosition, lastLookAt); |
137 | } | 158 | } |
159 | |||
160 | public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt) | ||
161 | { | ||
162 | return m_GridUserService.SetHome(userID, homeID, homePosition, homeLookAt); | ||
163 | } | ||
164 | |||
165 | public bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) | ||
166 | { | ||
167 | return m_GridUserService.SetLastPosition(userID, regionID, lastPosition, lastLookAt); | ||
168 | } | ||
169 | |||
170 | public GridUserInfo GetGridUserInfo(string userID) | ||
171 | { | ||
172 | return m_GridUserService.GetGridUserInfo(userID); | ||
173 | } | ||
174 | |||
175 | #endregion | ||
176 | |||
138 | } | 177 | } |
139 | } \ No newline at end of file | 178 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs index c402a3f..49dd633 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs | |||
@@ -167,9 +167,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
167 | return false; | 167 | return false; |
168 | } | 168 | } |
169 | 169 | ||
170 | public bool LogoutAgent(UUID sessionID, Vector3 position, Vector3 lookat) | 170 | public bool LogoutAgent(UUID sessionID) |
171 | { | 171 | { |
172 | return m_PresenceService.LogoutAgent(sessionID, position, lookat); | 172 | return m_PresenceService.LogoutAgent(sessionID); |
173 | } | 173 | } |
174 | 174 | ||
175 | 175 | ||
@@ -178,9 +178,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
178 | return m_PresenceService.LogoutRegionAgents(regionID); | 178 | return m_PresenceService.LogoutRegionAgents(regionID); |
179 | } | 179 | } |
180 | 180 | ||
181 | public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) | 181 | public bool ReportAgent(UUID sessionID, UUID regionID) |
182 | { | 182 | { |
183 | return m_PresenceService.ReportAgent(sessionID, regionID, position, lookAt); | 183 | return m_PresenceService.ReportAgent(sessionID, regionID); |
184 | } | 184 | } |
185 | 185 | ||
186 | public PresenceInfo GetAgent(UUID sessionID) | 186 | public PresenceInfo GetAgent(UUID sessionID) |
@@ -193,11 +193,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
193 | return m_PresenceService.GetAgents(userIDs); | 193 | return m_PresenceService.GetAgents(userIDs); |
194 | } | 194 | } |
195 | 195 | ||
196 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
197 | { | ||
198 | return m_PresenceService.SetHomeLocation(userID, regionID, position, lookAt); | ||
199 | } | ||
200 | |||
201 | #endregion | 196 | #endregion |
202 | 197 | ||
203 | } | 198 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs index 7a75a89..62b8278 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs | |||
@@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
72 | public void OnMakeRootAgent(ScenePresence sp) | 72 | public void OnMakeRootAgent(ScenePresence sp) |
73 | { | 73 | { |
74 | m_log.DebugFormat("[PRESENCE DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); | 74 | m_log.DebugFormat("[PRESENCE DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); |
75 | m_PresenceService.ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); | 75 | m_PresenceService.ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID); |
76 | } | 76 | } |
77 | 77 | ||
78 | public void OnNewClient(IClientAPI client) | 78 | public void OnNewClient(IClientAPI client) |
@@ -85,19 +85,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
85 | if (client.IsLoggingOut) | 85 | if (client.IsLoggingOut) |
86 | { | 86 | { |
87 | object sp = null; | 87 | object sp = null; |
88 | Vector3 position = new Vector3(128, 128, 0); | ||
89 | Vector3 lookat = new Vector3(0, 1, 0); | ||
90 | |||
91 | if (client.Scene.TryGetScenePresence(client.AgentId, out sp)) | 88 | if (client.Scene.TryGetScenePresence(client.AgentId, out sp)) |
92 | { | 89 | { |
93 | if (sp is ScenePresence) | 90 | if (sp is ScenePresence) |
94 | { | 91 | { |
95 | position = ((ScenePresence)sp).AbsolutePosition; | 92 | if (((ScenePresence)sp).IsChildAgent) |
96 | lookat = ((ScenePresence)sp).Lookat; | 93 | return; |
97 | } | 94 | } |
98 | } | 95 | } |
99 | 96 | ||
100 | m_PresenceService.LogoutAgent(client.SessionId, position, lookat); | 97 | m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); |
98 | m_PresenceService.LogoutAgent(client.SessionId); | ||
101 | } | 99 | } |
102 | 100 | ||
103 | } | 101 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs index 5f3666e..bf4e9ab 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs | |||
@@ -127,9 +127,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
127 | return false; | 127 | return false; |
128 | } | 128 | } |
129 | 129 | ||
130 | public bool LogoutAgent(UUID sessionID, Vector3 position, Vector3 lookat) | 130 | public bool LogoutAgent(UUID sessionID) |
131 | { | 131 | { |
132 | return m_RemoteConnector.LogoutAgent(sessionID, position, lookat); | 132 | return m_RemoteConnector.LogoutAgent(sessionID); |
133 | } | 133 | } |
134 | 134 | ||
135 | 135 | ||
@@ -138,9 +138,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
138 | return m_RemoteConnector.LogoutRegionAgents(regionID); | 138 | return m_RemoteConnector.LogoutRegionAgents(regionID); |
139 | } | 139 | } |
140 | 140 | ||
141 | public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) | 141 | public bool ReportAgent(UUID sessionID, UUID regionID) |
142 | { | 142 | { |
143 | return m_RemoteConnector.ReportAgent(sessionID, regionID, position, lookAt); | 143 | return m_RemoteConnector.ReportAgent(sessionID, regionID); |
144 | } | 144 | } |
145 | 145 | ||
146 | public PresenceInfo GetAgent(UUID sessionID) | 146 | public PresenceInfo GetAgent(UUID sessionID) |
@@ -153,11 +153,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence | |||
153 | return m_RemoteConnector.GetAgents(userIDs); | 153 | return m_RemoteConnector.GetAgents(userIDs); |
154 | } | 154 | } |
155 | 155 | ||
156 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
157 | { | ||
158 | return m_RemoteConnector.SetHomeLocation(userID, regionID, position, lookAt); | ||
159 | } | ||
160 | |||
161 | #endregion | 156 | #endregion |
162 | 157 | ||
163 | } | 158 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs index 63a28fc..e5ded5b 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs | |||
@@ -93,24 +93,24 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests | |||
93 | Assert.IsTrue(result.Online, "Agent just logged in but is offline"); | 93 | Assert.IsTrue(result.Online, "Agent just logged in but is offline"); |
94 | 94 | ||
95 | UUID region1 = UUID.Random(); | 95 | UUID region1 = UUID.Random(); |
96 | bool r = m_LocalConnector.ReportAgent(session1, region1, Vector3.Zero, Vector3.Zero); | 96 | bool r = m_LocalConnector.ReportAgent(session1, region1); |
97 | Assert.IsTrue(r, "First ReportAgent returned false"); | 97 | Assert.IsTrue(r, "First ReportAgent returned false"); |
98 | result = m_LocalConnector.GetAgent(session1); | 98 | result = m_LocalConnector.GetAgent(session1); |
99 | Assert.That(result.RegionID, Is.EqualTo(region1), "Agent is not in the right region (region1)"); | 99 | Assert.That(result.RegionID, Is.EqualTo(region1), "Agent is not in the right region (region1)"); |
100 | 100 | ||
101 | UUID region2 = UUID.Random(); | 101 | UUID region2 = UUID.Random(); |
102 | r = m_LocalConnector.ReportAgent(session1, region2, Vector3.Zero, Vector3.Zero); | 102 | r = m_LocalConnector.ReportAgent(session1, region2); |
103 | Assert.IsTrue(r, "Second ReportAgent returned false"); | 103 | Assert.IsTrue(r, "Second ReportAgent returned false"); |
104 | result = m_LocalConnector.GetAgent(session1); | 104 | result = m_LocalConnector.GetAgent(session1); |
105 | Assert.That(result.RegionID, Is.EqualTo(region2), "Agent is not in the right region (region2)"); | 105 | Assert.That(result.RegionID, Is.EqualTo(region2), "Agent is not in the right region (region2)"); |
106 | 106 | ||
107 | r = m_LocalConnector.LogoutAgent(session1, Vector3.Zero, Vector3.UnitY); | 107 | r = m_LocalConnector.LogoutAgent(session1); |
108 | Assert.IsTrue(r, "LogoutAgent returned false"); | 108 | Assert.IsTrue(r, "LogoutAgent returned false"); |
109 | result = m_LocalConnector.GetAgent(session1); | 109 | result = m_LocalConnector.GetAgent(session1); |
110 | Assert.IsNotNull(result, "Agent session disappeared from storage after logout"); | 110 | Assert.IsNotNull(result, "Agent session disappeared from storage after logout"); |
111 | Assert.IsFalse(result.Online, "Agent is reported to be Online after logout"); | 111 | Assert.IsFalse(result.Online, "Agent is reported to be Online after logout"); |
112 | 112 | ||
113 | r = m_LocalConnector.ReportAgent(session1, region1, Vector3.Zero, Vector3.Zero); | 113 | r = m_LocalConnector.ReportAgent(session1, region1); |
114 | Assert.IsFalse(r, "ReportAgent of non-logged in user returned true"); | 114 | Assert.IsFalse(r, "ReportAgent of non-logged in user returned true"); |
115 | } | 115 | } |
116 | } | 116 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1a46837..c0fa7b4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -304,7 +304,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
304 | return m_AvatarService; | 304 | return m_AvatarService; |
305 | } | 305 | } |
306 | } | 306 | } |
307 | 307 | ||
308 | protected IGridUserService m_GridUserService; | ||
309 | public IGridUserService GridUserService | ||
310 | { | ||
311 | get | ||
312 | { | ||
313 | if (m_GridUserService == null) | ||
314 | m_GridUserService = RequestModuleInterface<IGridUserService>(); | ||
315 | return m_GridUserService; | ||
316 | } | ||
317 | } | ||
318 | |||
308 | protected IXMLRPC m_xmlrpcModule; | 319 | protected IXMLRPC m_xmlrpcModule; |
309 | protected IWorldComm m_worldCommModule; | 320 | protected IWorldComm m_worldCommModule; |
310 | public IAttachmentsModule AttachmentsModule { get; set; } | 321 | public IAttachmentsModule AttachmentsModule { get; set; } |
@@ -1306,8 +1317,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1306 | if (defaultRegions != null && defaultRegions.Count >= 1) | 1317 | if (defaultRegions != null && defaultRegions.Count >= 1) |
1307 | home = defaultRegions[0]; | 1318 | home = defaultRegions[0]; |
1308 | 1319 | ||
1309 | if (PresenceService != null && home != null) | 1320 | if (GridUserService != null && home != null) |
1310 | PresenceService.SetHomeLocation(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); | 1321 | GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); |
1311 | else | 1322 | else |
1312 | m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.", | 1323 | m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.", |
1313 | first, last); | 1324 | first, last); |
@@ -3095,7 +3106,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3095 | /// <param name="flags"></param> | 3106 | /// <param name="flags"></param> |
3096 | public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) | 3107 | public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) |
3097 | { | 3108 | { |
3098 | if (PresenceService.SetHomeLocation(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) | 3109 | if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) |
3099 | // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. | 3110 | // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. |
3100 | m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); | 3111 | m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); |
3101 | else | 3112 | else |
@@ -3543,7 +3554,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3543 | 3554 | ||
3544 | OpenSim.Services.Interfaces.PresenceInfo pinfo = presence.GetAgent(agent.SessionID); | 3555 | OpenSim.Services.Interfaces.PresenceInfo pinfo = presence.GetAgent(agent.SessionID); |
3545 | 3556 | ||
3546 | if (pinfo == null || (pinfo != null && pinfo.Online == false)) | 3557 | if (pinfo == null) |
3547 | { | 3558 | { |
3548 | reason = String.Format("Failed to verify user {0} {1}, access denied to region {2}.", agent.firstname, agent.lastname, RegionInfo.RegionName); | 3559 | reason = String.Format("Failed to verify user {0} {1}, access denied to region {2}.", agent.firstname, agent.lastname, RegionInfo.RegionName); |
3549 | return false; | 3560 | return false; |
diff --git a/OpenSim/Region/Physics/Meshing/PrimMesher.cs b/OpenSim/Region/Physics/Meshing/PrimMesher.cs index b4e101a..53022ad 100644 --- a/OpenSim/Region/Physics/Meshing/PrimMesher.cs +++ b/OpenSim/Region/Physics/Meshing/PrimMesher.cs | |||
@@ -1,2284 +1,2284 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors | 2 | * Copyright (c) Contributors |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Text; | 30 | using System.Text; |
31 | using System.IO; | 31 | using System.IO; |
32 | 32 | ||
33 | namespace PrimMesher | 33 | namespace PrimMesher |
34 | { | 34 | { |
35 | public struct Quat | 35 | public struct Quat |
36 | { | 36 | { |
37 | /// <summary>X value</summary> | 37 | /// <summary>X value</summary> |
38 | public float X; | 38 | public float X; |
39 | /// <summary>Y value</summary> | 39 | /// <summary>Y value</summary> |
40 | public float Y; | 40 | public float Y; |
41 | /// <summary>Z value</summary> | 41 | /// <summary>Z value</summary> |
42 | public float Z; | 42 | public float Z; |
43 | /// <summary>W value</summary> | 43 | /// <summary>W value</summary> |
44 | public float W; | 44 | public float W; |
45 | 45 | ||
46 | public Quat(float x, float y, float z, float w) | 46 | public Quat(float x, float y, float z, float w) |
47 | { | 47 | { |
48 | X = x; | 48 | X = x; |
49 | Y = y; | 49 | Y = y; |
50 | Z = z; | 50 | Z = z; |
51 | W = w; | 51 | W = w; |
52 | } | 52 | } |
53 | 53 | ||
54 | public Quat(Coord axis, float angle) | 54 | public Quat(Coord axis, float angle) |
55 | { | 55 | { |
56 | axis = axis.Normalize(); | 56 | axis = axis.Normalize(); |
57 | 57 | ||
58 | angle *= 0.5f; | 58 | angle *= 0.5f; |
59 | float c = (float)Math.Cos(angle); | 59 | float c = (float)Math.Cos(angle); |
60 | float s = (float)Math.Sin(angle); | 60 | float s = (float)Math.Sin(angle); |
61 | 61 | ||
62 | X = axis.X * s; | 62 | X = axis.X * s; |
63 | Y = axis.Y * s; | 63 | Y = axis.Y * s; |
64 | Z = axis.Z * s; | 64 | Z = axis.Z * s; |
65 | W = c; | 65 | W = c; |
66 | 66 | ||
67 | Normalize(); | 67 | Normalize(); |
68 | } | 68 | } |
69 | 69 | ||
70 | public float Length() | 70 | public float Length() |
71 | { | 71 | { |
72 | return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); | 72 | return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W); |
73 | } | 73 | } |
74 | 74 | ||
75 | public Quat Normalize() | 75 | public Quat Normalize() |
76 | { | 76 | { |
77 | const float MAG_THRESHOLD = 0.0000001f; | 77 | const float MAG_THRESHOLD = 0.0000001f; |
78 | float mag = Length(); | 78 | float mag = Length(); |
79 | 79 | ||
80 | // Catch very small rounding errors when normalizing | 80 | // Catch very small rounding errors when normalizing |
81 | if (mag > MAG_THRESHOLD) | 81 | if (mag > MAG_THRESHOLD) |
82 | { | 82 | { |
83 | float oomag = 1f / mag; | 83 | float oomag = 1f / mag; |
84 | X *= oomag; | 84 | X *= oomag; |
85 | Y *= oomag; | 85 | Y *= oomag; |
86 | Z *= oomag; | 86 | Z *= oomag; |
87 | W *= oomag; | 87 | W *= oomag; |
88 | } | 88 | } |
89 | else | 89 | else |
90 | { | 90 | { |
91 | X = 0f; | 91 | X = 0f; |
92 | Y = 0f; | 92 | Y = 0f; |
93 | Z = 0f; | 93 | Z = 0f; |
94 | W = 1f; | 94 | W = 1f; |
95 | } | 95 | } |
96 | 96 | ||
97 | return this; | 97 | return this; |
98 | } | 98 | } |
99 | 99 | ||
100 | public static Quat operator *(Quat q1, Quat q2) | 100 | public static Quat operator *(Quat q1, Quat q2) |
101 | { | 101 | { |
102 | float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y; | 102 | float x = q1.W * q2.X + q1.X * q2.W + q1.Y * q2.Z - q1.Z * q2.Y; |
103 | float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X; | 103 | float y = q1.W * q2.Y - q1.X * q2.Z + q1.Y * q2.W + q1.Z * q2.X; |
104 | float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W; | 104 | float z = q1.W * q2.Z + q1.X * q2.Y - q1.Y * q2.X + q1.Z * q2.W; |
105 | float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z; | 105 | float w = q1.W * q2.W - q1.X * q2.X - q1.Y * q2.Y - q1.Z * q2.Z; |
106 | return new Quat(x, y, z, w); | 106 | return new Quat(x, y, z, w); |
107 | } | 107 | } |
108 | 108 | ||
109 | public override string ToString() | 109 | public override string ToString() |
110 | { | 110 | { |
111 | return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">"; | 111 | return "< X: " + this.X.ToString() + ", Y: " + this.Y.ToString() + ", Z: " + this.Z.ToString() + ", W: " + this.W.ToString() + ">"; |
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | public struct Coord | 115 | public struct Coord |
116 | { | 116 | { |
117 | public float X; | 117 | public float X; |
118 | public float Y; | 118 | public float Y; |
119 | public float Z; | 119 | public float Z; |
120 | 120 | ||
121 | public Coord(float x, float y, float z) | 121 | public Coord(float x, float y, float z) |
122 | { | 122 | { |
123 | this.X = x; | 123 | this.X = x; |
124 | this.Y = y; | 124 | this.Y = y; |
125 | this.Z = z; | 125 | this.Z = z; |
126 | } | 126 | } |
127 | 127 | ||
128 | public float Length() | 128 | public float Length() |
129 | { | 129 | { |
130 | return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z); | 130 | return (float)Math.Sqrt(this.X * this.X + this.Y * this.Y + this.Z * this.Z); |
131 | } | 131 | } |
132 | 132 | ||
133 | public Coord Invert() | 133 | public Coord Invert() |
134 | { | 134 | { |
135 | this.X = -this.X; | 135 | this.X = -this.X; |
136 | this.Y = -this.Y; | 136 | this.Y = -this.Y; |
137 | this.Z = -this.Z; | 137 | this.Z = -this.Z; |
138 | 138 | ||
139 | return this; | 139 | return this; |
140 | } | 140 | } |
141 | 141 | ||
142 | public Coord Normalize() | 142 | public Coord Normalize() |
143 | { | 143 | { |
144 | const float MAG_THRESHOLD = 0.0000001f; | 144 | const float MAG_THRESHOLD = 0.0000001f; |
145 | float mag = Length(); | 145 | float mag = Length(); |
146 | 146 | ||
147 | // Catch very small rounding errors when normalizing | 147 | // Catch very small rounding errors when normalizing |
148 | if (mag > MAG_THRESHOLD) | 148 | if (mag > MAG_THRESHOLD) |
149 | { | 149 | { |
150 | float oomag = 1.0f / mag; | 150 | float oomag = 1.0f / mag; |
151 | this.X *= oomag; | 151 | this.X *= oomag; |
152 | this.Y *= oomag; | 152 | this.Y *= oomag; |
153 | this.Z *= oomag; | 153 | this.Z *= oomag; |
154 | } | 154 | } |
155 | else | 155 | else |
156 | { | 156 | { |
157 | this.X = 0.0f; | 157 | this.X = 0.0f; |
158 | this.Y = 0.0f; | 158 | this.Y = 0.0f; |
159 | this.Z = 0.0f; | 159 | this.Z = 0.0f; |
160 | } | 160 | } |
161 | 161 | ||
162 | return this; | 162 | return this; |
163 | } | 163 | } |
164 | 164 | ||
165 | public override string ToString() | 165 | public override string ToString() |
166 | { | 166 | { |
167 | return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString(); | 167 | return this.X.ToString() + " " + this.Y.ToString() + " " + this.Z.ToString(); |
168 | } | 168 | } |
169 | 169 | ||
170 | public static Coord Cross(Coord c1, Coord c2) | 170 | public static Coord Cross(Coord c1, Coord c2) |
171 | { | 171 | { |
172 | return new Coord( | 172 | return new Coord( |
173 | c1.Y * c2.Z - c2.Y * c1.Z, | 173 | c1.Y * c2.Z - c2.Y * c1.Z, |
174 | c1.Z * c2.X - c2.Z * c1.X, | 174 | c1.Z * c2.X - c2.Z * c1.X, |
175 | c1.X * c2.Y - c2.X * c1.Y | 175 | c1.X * c2.Y - c2.X * c1.Y |
176 | ); | 176 | ); |
177 | } | 177 | } |
178 | 178 | ||
179 | public static Coord operator +(Coord v, Coord a) | 179 | public static Coord operator +(Coord v, Coord a) |
180 | { | 180 | { |
181 | return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z); | 181 | return new Coord(v.X + a.X, v.Y + a.Y, v.Z + a.Z); |
182 | } | 182 | } |
183 | 183 | ||
184 | public static Coord operator *(Coord v, Coord m) | 184 | public static Coord operator *(Coord v, Coord m) |
185 | { | 185 | { |
186 | return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z); | 186 | return new Coord(v.X * m.X, v.Y * m.Y, v.Z * m.Z); |
187 | } | 187 | } |
188 | 188 | ||
189 | public static Coord operator *(Coord v, Quat q) | 189 | public static Coord operator *(Coord v, Quat q) |
190 | { | 190 | { |
191 | // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ | 191 | // From http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/ |
192 | 192 | ||
193 | Coord c2 = new Coord(0.0f, 0.0f, 0.0f); | 193 | Coord c2 = new Coord(0.0f, 0.0f, 0.0f); |
194 | 194 | ||
195 | c2.X = q.W * q.W * v.X + | 195 | c2.X = q.W * q.W * v.X + |
196 | 2f * q.Y * q.W * v.Z - | 196 | 2f * q.Y * q.W * v.Z - |
197 | 2f * q.Z * q.W * v.Y + | 197 | 2f * q.Z * q.W * v.Y + |
198 | q.X * q.X * v.X + | 198 | q.X * q.X * v.X + |
199 | 2f * q.Y * q.X * v.Y + | 199 | 2f * q.Y * q.X * v.Y + |
200 | 2f * q.Z * q.X * v.Z - | 200 | 2f * q.Z * q.X * v.Z - |
201 | q.Z * q.Z * v.X - | 201 | q.Z * q.Z * v.X - |
202 | q.Y * q.Y * v.X; | 202 | q.Y * q.Y * v.X; |
203 | 203 | ||
204 | c2.Y = | 204 | c2.Y = |
205 | 2f * q.X * q.Y * v.X + | 205 | 2f * q.X * q.Y * v.X + |
206 | q.Y * q.Y * v.Y + | 206 | q.Y * q.Y * v.Y + |
207 | 2f * q.Z * q.Y * v.Z + | 207 | 2f * q.Z * q.Y * v.Z + |
208 | 2f * q.W * q.Z * v.X - | 208 | 2f * q.W * q.Z * v.X - |
209 | q.Z * q.Z * v.Y + | 209 | q.Z * q.Z * v.Y + |
210 | q.W * q.W * v.Y - | 210 | q.W * q.W * v.Y - |
211 | 2f * q.X * q.W * v.Z - | 211 | 2f * q.X * q.W * v.Z - |
212 | q.X * q.X * v.Y; | 212 | q.X * q.X * v.Y; |
213 | 213 | ||
214 | c2.Z = | 214 | c2.Z = |
215 | 2f * q.X * q.Z * v.X + | 215 | 2f * q.X * q.Z * v.X + |
216 | 2f * q.Y * q.Z * v.Y + | 216 | 2f * q.Y * q.Z * v.Y + |
217 | q.Z * q.Z * v.Z - | 217 | q.Z * q.Z * v.Z - |
218 | 2f * q.W * q.Y * v.X - | 218 | 2f * q.W * q.Y * v.X - |
219 | q.Y * q.Y * v.Z + | 219 | q.Y * q.Y * v.Z + |
220 | 2f * q.W * q.X * v.Y - | 220 | 2f * q.W * q.X * v.Y - |
221 | q.X * q.X * v.Z + | 221 | q.X * q.X * v.Z + |
222 | q.W * q.W * v.Z; | 222 | q.W * q.W * v.Z; |
223 | 223 | ||
224 | return c2; | 224 | return c2; |
225 | } | 225 | } |
226 | } | 226 | } |
227 | 227 | ||
228 | public struct UVCoord | 228 | public struct UVCoord |
229 | { | 229 | { |
230 | public float U; | 230 | public float U; |
231 | public float V; | 231 | public float V; |
232 | 232 | ||
233 | 233 | ||
234 | public UVCoord(float u, float v) | 234 | public UVCoord(float u, float v) |
235 | { | 235 | { |
236 | this.U = u; | 236 | this.U = u; |
237 | this.V = v; | 237 | this.V = v; |
238 | } | 238 | } |
239 | } | 239 | } |
240 | 240 | ||
241 | public struct Face | 241 | public struct Face |
242 | { | 242 | { |
243 | public int primFace; | 243 | public int primFace; |
244 | 244 | ||
245 | // vertices | 245 | // vertices |
246 | public int v1; | 246 | public int v1; |
247 | public int v2; | 247 | public int v2; |
248 | public int v3; | 248 | public int v3; |
249 | 249 | ||
250 | //normals | 250 | //normals |
251 | public int n1; | 251 | public int n1; |
252 | public int n2; | 252 | public int n2; |
253 | public int n3; | 253 | public int n3; |
254 | 254 | ||
255 | // uvs | 255 | // uvs |
256 | public int uv1; | 256 | public int uv1; |
257 | public int uv2; | 257 | public int uv2; |
258 | public int uv3; | 258 | public int uv3; |
259 | 259 | ||
260 | public Face(int v1, int v2, int v3) | 260 | public Face(int v1, int v2, int v3) |
261 | { | 261 | { |
262 | primFace = 0; | 262 | primFace = 0; |
263 | 263 | ||
264 | this.v1 = v1; | 264 | this.v1 = v1; |
265 | this.v2 = v2; | 265 | this.v2 = v2; |
266 | this.v3 = v3; | 266 | this.v3 = v3; |
267 | 267 | ||
268 | this.n1 = 0; | 268 | this.n1 = 0; |
269 | this.n2 = 0; | 269 | this.n2 = 0; |
270 | this.n3 = 0; | 270 | this.n3 = 0; |
271 | 271 | ||
272 | this.uv1 = 0; | 272 | this.uv1 = 0; |
273 | this.uv2 = 0; | 273 | this.uv2 = 0; |
274 | this.uv3 = 0; | 274 | this.uv3 = 0; |
275 | 275 | ||
276 | } | 276 | } |
277 | 277 | ||
278 | public Face(int v1, int v2, int v3, int n1, int n2, int n3) | 278 | public Face(int v1, int v2, int v3, int n1, int n2, int n3) |
279 | { | 279 | { |
280 | primFace = 0; | 280 | primFace = 0; |
281 | 281 | ||
282 | this.v1 = v1; | 282 | this.v1 = v1; |
283 | this.v2 = v2; | 283 | this.v2 = v2; |
284 | this.v3 = v3; | 284 | this.v3 = v3; |
285 | 285 | ||
286 | this.n1 = n1; | 286 | this.n1 = n1; |
287 | this.n2 = n2; | 287 | this.n2 = n2; |
288 | this.n3 = n3; | 288 | this.n3 = n3; |
289 | 289 | ||
290 | this.uv1 = 0; | 290 | this.uv1 = 0; |
291 | this.uv2 = 0; | 291 | this.uv2 = 0; |
292 | this.uv3 = 0; | 292 | this.uv3 = 0; |
293 | } | 293 | } |
294 | 294 | ||
295 | public Coord SurfaceNormal(List<Coord> coordList) | 295 | public Coord SurfaceNormal(List<Coord> coordList) |
296 | { | 296 | { |
297 | Coord c1 = coordList[this.v1]; | 297 | Coord c1 = coordList[this.v1]; |
298 | Coord c2 = coordList[this.v2]; | 298 | Coord c2 = coordList[this.v2]; |
299 | Coord c3 = coordList[this.v3]; | 299 | Coord c3 = coordList[this.v3]; |
300 | 300 | ||
301 | Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); | 301 | Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); |
302 | Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); | 302 | Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); |
303 | 303 | ||
304 | return Coord.Cross(edge1, edge2).Normalize(); | 304 | return Coord.Cross(edge1, edge2).Normalize(); |
305 | } | 305 | } |
306 | } | 306 | } |
307 | 307 | ||
308 | public struct ViewerFace | 308 | public struct ViewerFace |
309 | { | 309 | { |
310 | public int primFaceNumber; | 310 | public int primFaceNumber; |
311 | 311 | ||
312 | public Coord v1; | 312 | public Coord v1; |
313 | public Coord v2; | 313 | public Coord v2; |
314 | public Coord v3; | 314 | public Coord v3; |
315 | 315 | ||
316 | public int coordIndex1; | 316 | public int coordIndex1; |
317 | public int coordIndex2; | 317 | public int coordIndex2; |
318 | public int coordIndex3; | 318 | public int coordIndex3; |
319 | 319 | ||
320 | public Coord n1; | 320 | public Coord n1; |
321 | public Coord n2; | 321 | public Coord n2; |
322 | public Coord n3; | 322 | public Coord n3; |
323 | 323 | ||
324 | public UVCoord uv1; | 324 | public UVCoord uv1; |
325 | public UVCoord uv2; | 325 | public UVCoord uv2; |
326 | public UVCoord uv3; | 326 | public UVCoord uv3; |
327 | 327 | ||
328 | public ViewerFace(int primFaceNumber) | 328 | public ViewerFace(int primFaceNumber) |
329 | { | 329 | { |
330 | this.primFaceNumber = primFaceNumber; | 330 | this.primFaceNumber = primFaceNumber; |
331 | 331 | ||
332 | this.v1 = new Coord(); | 332 | this.v1 = new Coord(); |
333 | this.v2 = new Coord(); | 333 | this.v2 = new Coord(); |
334 | this.v3 = new Coord(); | 334 | this.v3 = new Coord(); |
335 | 335 | ||
336 | this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet | 336 | this.coordIndex1 = this.coordIndex2 = this.coordIndex3 = -1; // -1 means not assigned yet |
337 | 337 | ||
338 | this.n1 = new Coord(); | 338 | this.n1 = new Coord(); |
339 | this.n2 = new Coord(); | 339 | this.n2 = new Coord(); |
340 | this.n3 = new Coord(); | 340 | this.n3 = new Coord(); |
341 | 341 | ||
342 | this.uv1 = new UVCoord(); | 342 | this.uv1 = new UVCoord(); |
343 | this.uv2 = new UVCoord(); | 343 | this.uv2 = new UVCoord(); |
344 | this.uv3 = new UVCoord(); | 344 | this.uv3 = new UVCoord(); |
345 | } | 345 | } |
346 | 346 | ||
347 | public void Scale(float x, float y, float z) | 347 | public void Scale(float x, float y, float z) |
348 | { | 348 | { |
349 | this.v1.X *= x; | 349 | this.v1.X *= x; |
350 | this.v1.Y *= y; | 350 | this.v1.Y *= y; |
351 | this.v1.Z *= z; | 351 | this.v1.Z *= z; |
352 | 352 | ||
353 | this.v2.X *= x; | 353 | this.v2.X *= x; |
354 | this.v2.Y *= y; | 354 | this.v2.Y *= y; |
355 | this.v2.Z *= z; | 355 | this.v2.Z *= z; |
356 | 356 | ||
357 | this.v3.X *= x; | 357 | this.v3.X *= x; |
358 | this.v3.Y *= y; | 358 | this.v3.Y *= y; |
359 | this.v3.Z *= z; | 359 | this.v3.Z *= z; |
360 | } | 360 | } |
361 | 361 | ||
362 | public void AddPos(float x, float y, float z) | 362 | public void AddPos(float x, float y, float z) |
363 | { | 363 | { |
364 | this.v1.X += x; | 364 | this.v1.X += x; |
365 | this.v2.X += x; | 365 | this.v2.X += x; |
366 | this.v3.X += x; | 366 | this.v3.X += x; |
367 | 367 | ||
368 | this.v1.Y += y; | 368 | this.v1.Y += y; |
369 | this.v2.Y += y; | 369 | this.v2.Y += y; |
370 | this.v3.Y += y; | 370 | this.v3.Y += y; |
371 | 371 | ||
372 | this.v1.Z += z; | 372 | this.v1.Z += z; |
373 | this.v2.Z += z; | 373 | this.v2.Z += z; |
374 | this.v3.Z += z; | 374 | this.v3.Z += z; |
375 | } | 375 | } |
376 | 376 | ||
377 | public void AddRot(Quat q) | 377 | public void AddRot(Quat q) |
378 | { | 378 | { |
379 | this.v1 *= q; | 379 | this.v1 *= q; |
380 | this.v2 *= q; | 380 | this.v2 *= q; |
381 | this.v3 *= q; | 381 | this.v3 *= q; |
382 | 382 | ||
383 | this.n1 *= q; | 383 | this.n1 *= q; |
384 | this.n2 *= q; | 384 | this.n2 *= q; |
385 | this.n3 *= q; | 385 | this.n3 *= q; |
386 | } | 386 | } |
387 | 387 | ||
388 | public void CalcSurfaceNormal() | 388 | public void CalcSurfaceNormal() |
389 | { | 389 | { |
390 | 390 | ||
391 | Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z); | 391 | Coord edge1 = new Coord(this.v2.X - this.v1.X, this.v2.Y - this.v1.Y, this.v2.Z - this.v1.Z); |
392 | Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z); | 392 | Coord edge2 = new Coord(this.v3.X - this.v1.X, this.v3.Y - this.v1.Y, this.v3.Z - this.v1.Z); |
393 | 393 | ||
394 | this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize(); | 394 | this.n1 = this.n2 = this.n3 = Coord.Cross(edge1, edge2).Normalize(); |
395 | } | 395 | } |
396 | } | 396 | } |
397 | 397 | ||
398 | internal struct Angle | 398 | internal struct Angle |
399 | { | 399 | { |
400 | internal float angle; | 400 | internal float angle; |
401 | internal float X; | 401 | internal float X; |
402 | internal float Y; | 402 | internal float Y; |
403 | 403 | ||
404 | internal Angle(float angle, float x, float y) | 404 | internal Angle(float angle, float x, float y) |
405 | { | 405 | { |
406 | this.angle = angle; | 406 | this.angle = angle; |
407 | this.X = x; | 407 | this.X = x; |
408 | this.Y = y; | 408 | this.Y = y; |
409 | } | 409 | } |
410 | } | 410 | } |
411 | 411 | ||
412 | internal class AngleList | 412 | internal class AngleList |
413 | { | 413 | { |
414 | private float iX, iY; // intersection point | 414 | private float iX, iY; // intersection point |
415 | 415 | ||
416 | private static Angle[] angles3 = | 416 | private static Angle[] angles3 = |
417 | { | 417 | { |
418 | new Angle(0.0f, 1.0f, 0.0f), | 418 | new Angle(0.0f, 1.0f, 0.0f), |
419 | new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), | 419 | new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), |
420 | new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), | 420 | new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), |
421 | new Angle(1.0f, 1.0f, 0.0f) | 421 | new Angle(1.0f, 1.0f, 0.0f) |
422 | }; | 422 | }; |
423 | 423 | ||
424 | private static Coord[] normals3 = | 424 | private static Coord[] normals3 = |
425 | { | 425 | { |
426 | new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(), | 426 | new Coord(0.25f, 0.4330127019f, 0.0f).Normalize(), |
427 | new Coord(-0.5f, 0.0f, 0.0f).Normalize(), | 427 | new Coord(-0.5f, 0.0f, 0.0f).Normalize(), |
428 | new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(), | 428 | new Coord(0.25f, -0.4330127019f, 0.0f).Normalize(), |
429 | new Coord(0.25f, 0.4330127019f, 0.0f).Normalize() | 429 | new Coord(0.25f, 0.4330127019f, 0.0f).Normalize() |
430 | }; | 430 | }; |
431 | 431 | ||
432 | private static Angle[] angles4 = | 432 | private static Angle[] angles4 = |
433 | { | 433 | { |
434 | new Angle(0.0f, 1.0f, 0.0f), | 434 | new Angle(0.0f, 1.0f, 0.0f), |
435 | new Angle(0.25f, 0.0f, 1.0f), | 435 | new Angle(0.25f, 0.0f, 1.0f), |
436 | new Angle(0.5f, -1.0f, 0.0f), | 436 | new Angle(0.5f, -1.0f, 0.0f), |
437 | new Angle(0.75f, 0.0f, -1.0f), | 437 | new Angle(0.75f, 0.0f, -1.0f), |
438 | new Angle(1.0f, 1.0f, 0.0f) | 438 | new Angle(1.0f, 1.0f, 0.0f) |
439 | }; | 439 | }; |
440 | 440 | ||
441 | private static Coord[] normals4 = | 441 | private static Coord[] normals4 = |
442 | { | 442 | { |
443 | new Coord(0.5f, 0.5f, 0.0f).Normalize(), | 443 | new Coord(0.5f, 0.5f, 0.0f).Normalize(), |
444 | new Coord(-0.5f, 0.5f, 0.0f).Normalize(), | 444 | new Coord(-0.5f, 0.5f, 0.0f).Normalize(), |
445 | new Coord(-0.5f, -0.5f, 0.0f).Normalize(), | 445 | new Coord(-0.5f, -0.5f, 0.0f).Normalize(), |
446 | new Coord(0.5f, -0.5f, 0.0f).Normalize(), | 446 | new Coord(0.5f, -0.5f, 0.0f).Normalize(), |
447 | new Coord(0.5f, 0.5f, 0.0f).Normalize() | 447 | new Coord(0.5f, 0.5f, 0.0f).Normalize() |
448 | }; | 448 | }; |
449 | 449 | ||
450 | private static Angle[] angles24 = | 450 | private static Angle[] angles24 = |
451 | { | 451 | { |
452 | new Angle(0.0f, 1.0f, 0.0f), | 452 | new Angle(0.0f, 1.0f, 0.0f), |
453 | new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f), | 453 | new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f), |
454 | new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f), | 454 | new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f), |
455 | new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f), | 455 | new Angle(0.125f, 0.70710678118654757f, 0.70710678118654746f), |
456 | new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), | 456 | new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f), |
457 | new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f), | 457 | new Angle(0.20833333333333331f, 0.25881904510252096f, 0.9659258262890682f), |
458 | new Angle(0.25f, 0.0f, 1.0f), | 458 | new Angle(0.25f, 0.0f, 1.0f), |
459 | new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f), | 459 | new Angle(0.29166666666666663f, -0.25881904510252063f, 0.96592582628906831f), |
460 | new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), | 460 | new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f), |
461 | new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f), | 461 | new Angle(0.375f, -0.70710678118654746f, 0.70710678118654757f), |
462 | new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f), | 462 | new Angle(0.41666666666666663f, -0.86602540378443849f, 0.5f), |
463 | new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f), | 463 | new Angle(0.45833333333333331f, -0.9659258262890682f, 0.25881904510252102f), |
464 | new Angle(0.5f, -1.0f, 0.0f), | 464 | new Angle(0.5f, -1.0f, 0.0f), |
465 | new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f), | 465 | new Angle(0.54166666666666663f, -0.96592582628906842f, -0.25881904510252035f), |
466 | new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f), | 466 | new Angle(0.58333333333333326f, -0.86602540378443882f, -0.5f), |
467 | new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f), | 467 | new Angle(0.62499999999999989f, -0.70710678118654791f, -0.70710678118654713f), |
468 | new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), | 468 | new Angle(0.66666666666666667f, -0.5f, -0.86602540378443837f), |
469 | new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f), | 469 | new Angle(0.70833333333333326f, -0.25881904510252152f, -0.96592582628906809f), |
470 | new Angle(0.75f, 0.0f, -1.0f), | 470 | new Angle(0.75f, 0.0f, -1.0f), |
471 | new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f), | 471 | new Angle(0.79166666666666663f, 0.2588190451025203f, -0.96592582628906842f), |
472 | new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), | 472 | new Angle(0.83333333333333326f, 0.5f, -0.86602540378443904f), |
473 | new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f), | 473 | new Angle(0.875f, 0.70710678118654735f, -0.70710678118654768f), |
474 | new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f), | 474 | new Angle(0.91666666666666663f, 0.86602540378443837f, -0.5f), |
475 | new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f), | 475 | new Angle(0.95833333333333326f, 0.96592582628906809f, -0.25881904510252157f), |
476 | new Angle(1.0f, 1.0f, 0.0f) | 476 | new Angle(1.0f, 1.0f, 0.0f) |
477 | }; | 477 | }; |
478 | 478 | ||
479 | private Angle interpolatePoints(float newPoint, Angle p1, Angle p2) | 479 | private Angle interpolatePoints(float newPoint, Angle p1, Angle p2) |
480 | { | 480 | { |
481 | float m = (newPoint - p1.angle) / (p2.angle - p1.angle); | 481 | float m = (newPoint - p1.angle) / (p2.angle - p1.angle); |
482 | return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y)); | 482 | return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y)); |
483 | } | 483 | } |
484 | 484 | ||
485 | private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) | 485 | private void intersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) |
486 | { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ | 486 | { // ref: http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ |
487 | double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); | 487 | double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); |
488 | double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); | 488 | double uaNumerator = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3); |
489 | 489 | ||
490 | if (denom != 0.0) | 490 | if (denom != 0.0) |
491 | { | 491 | { |
492 | double ua = uaNumerator / denom; | 492 | double ua = uaNumerator / denom; |
493 | iX = (float)(x1 + ua * (x2 - x1)); | 493 | iX = (float)(x1 + ua * (x2 - x1)); |
494 | iY = (float)(y1 + ua * (y2 - y1)); | 494 | iY = (float)(y1 + ua * (y2 - y1)); |
495 | } | 495 | } |
496 | } | 496 | } |
497 | 497 | ||
498 | internal List<Angle> angles; | 498 | internal List<Angle> angles; |
499 | internal List<Coord> normals; | 499 | internal List<Coord> normals; |
500 | 500 | ||
501 | internal void makeAngles(int sides, float startAngle, float stopAngle) | 501 | internal void makeAngles(int sides, float startAngle, float stopAngle) |
502 | { | 502 | { |
503 | angles = new List<Angle>(); | 503 | angles = new List<Angle>(); |
504 | normals = new List<Coord>(); | 504 | normals = new List<Coord>(); |
505 | 505 | ||
506 | double twoPi = System.Math.PI * 2.0; | 506 | double twoPi = System.Math.PI * 2.0; |
507 | float twoPiInv = 1.0f / (float)twoPi; | 507 | float twoPiInv = 1.0f / (float)twoPi; |
508 | 508 | ||
509 | if (sides < 1) | 509 | if (sides < 1) |
510 | throw new Exception("number of sides not greater than zero"); | 510 | throw new Exception("number of sides not greater than zero"); |
511 | if (stopAngle <= startAngle) | 511 | if (stopAngle <= startAngle) |
512 | throw new Exception("stopAngle not greater than startAngle"); | 512 | throw new Exception("stopAngle not greater than startAngle"); |
513 | 513 | ||
514 | if ((sides == 3 || sides == 4 || sides == 24)) | 514 | if ((sides == 3 || sides == 4 || sides == 24)) |
515 | { | 515 | { |
516 | startAngle *= twoPiInv; | 516 | startAngle *= twoPiInv; |
517 | stopAngle *= twoPiInv; | 517 | stopAngle *= twoPiInv; |
518 | 518 | ||
519 | Angle[] sourceAngles; | 519 | Angle[] sourceAngles; |
520 | if (sides == 3) | 520 | if (sides == 3) |
521 | sourceAngles = angles3; | 521 | sourceAngles = angles3; |
522 | else if (sides == 4) | 522 | else if (sides == 4) |
523 | sourceAngles = angles4; | 523 | sourceAngles = angles4; |
524 | else sourceAngles = angles24; | 524 | else sourceAngles = angles24; |
525 | 525 | ||
526 | int startAngleIndex = (int)(startAngle * sides); | 526 | int startAngleIndex = (int)(startAngle * sides); |
527 | int endAngleIndex = sourceAngles.Length - 1; | 527 | int endAngleIndex = sourceAngles.Length - 1; |
528 | if (stopAngle < 1.0f) | 528 | if (stopAngle < 1.0f) |
529 | endAngleIndex = (int)(stopAngle * sides) + 1; | 529 | endAngleIndex = (int)(stopAngle * sides) + 1; |
530 | if (endAngleIndex == startAngleIndex) | 530 | if (endAngleIndex == startAngleIndex) |
531 | endAngleIndex++; | 531 | endAngleIndex++; |
532 | 532 | ||
533 | for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++) | 533 | for (int angleIndex = startAngleIndex; angleIndex < endAngleIndex + 1; angleIndex++) |
534 | { | 534 | { |
535 | angles.Add(sourceAngles[angleIndex]); | 535 | angles.Add(sourceAngles[angleIndex]); |
536 | if (sides == 3) | 536 | if (sides == 3) |
537 | normals.Add(normals3[angleIndex]); | 537 | normals.Add(normals3[angleIndex]); |
538 | else if (sides == 4) | 538 | else if (sides == 4) |
539 | normals.Add(normals4[angleIndex]); | 539 | normals.Add(normals4[angleIndex]); |
540 | } | 540 | } |
541 | 541 | ||
542 | if (startAngle > 0.0f) | 542 | if (startAngle > 0.0f) |
543 | angles[0] = interpolatePoints(startAngle, angles[0], angles[1]); | 543 | angles[0] = interpolatePoints(startAngle, angles[0], angles[1]); |
544 | 544 | ||
545 | if (stopAngle < 1.0f) | 545 | if (stopAngle < 1.0f) |
546 | { | 546 | { |
547 | int lastAngleIndex = angles.Count - 1; | 547 | int lastAngleIndex = angles.Count - 1; |
548 | angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]); | 548 | angles[lastAngleIndex] = interpolatePoints(stopAngle, angles[lastAngleIndex - 1], angles[lastAngleIndex]); |
549 | } | 549 | } |
550 | } | 550 | } |
551 | else | 551 | else |
552 | { | 552 | { |
553 | double stepSize = twoPi / sides; | 553 | double stepSize = twoPi / sides; |
554 | 554 | ||
555 | int startStep = (int)(startAngle / stepSize); | 555 | int startStep = (int)(startAngle / stepSize); |
556 | double angle = stepSize * startStep; | 556 | double angle = stepSize * startStep; |
557 | int step = startStep; | 557 | int step = startStep; |
558 | double stopAngleTest = stopAngle; | 558 | double stopAngleTest = stopAngle; |
559 | if (stopAngle < twoPi) | 559 | if (stopAngle < twoPi) |
560 | { | 560 | { |
561 | stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1); | 561 | stopAngleTest = stepSize * ((int)(stopAngle / stepSize) + 1); |
562 | if (stopAngleTest < stopAngle) | 562 | if (stopAngleTest < stopAngle) |
563 | stopAngleTest += stepSize; | 563 | stopAngleTest += stepSize; |
564 | if (stopAngleTest > twoPi) | 564 | if (stopAngleTest > twoPi) |
565 | stopAngleTest = twoPi; | 565 | stopAngleTest = twoPi; |
566 | } | 566 | } |
567 | 567 | ||
568 | while (angle <= stopAngleTest) | 568 | while (angle <= stopAngleTest) |
569 | { | 569 | { |
570 | Angle newAngle; | 570 | Angle newAngle; |
571 | newAngle.angle = (float)angle; | 571 | newAngle.angle = (float)angle; |
572 | newAngle.X = (float)System.Math.Cos(angle); | 572 | newAngle.X = (float)System.Math.Cos(angle); |
573 | newAngle.Y = (float)System.Math.Sin(angle); | 573 | newAngle.Y = (float)System.Math.Sin(angle); |
574 | angles.Add(newAngle); | 574 | angles.Add(newAngle); |
575 | step += 1; | 575 | step += 1; |
576 | angle = stepSize * step; | 576 | angle = stepSize * step; |
577 | } | 577 | } |
578 | 578 | ||
579 | if (startAngle > angles[0].angle) | 579 | if (startAngle > angles[0].angle) |
580 | { | 580 | { |
581 | Angle newAngle; | 581 | Angle newAngle; |
582 | intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle)); | 582 | intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle)); |
583 | newAngle.angle = startAngle; | 583 | newAngle.angle = startAngle; |
584 | newAngle.X = iX; | 584 | newAngle.X = iX; |
585 | newAngle.Y = iY; | 585 | newAngle.Y = iY; |
586 | angles[0] = newAngle; | 586 | angles[0] = newAngle; |
587 | } | 587 | } |
588 | 588 | ||
589 | int index = angles.Count - 1; | 589 | int index = angles.Count - 1; |
590 | if (stopAngle < angles[index].angle) | 590 | if (stopAngle < angles[index].angle) |
591 | { | 591 | { |
592 | Angle newAngle; | 592 | Angle newAngle; |
593 | intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle)); | 593 | intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle)); |
594 | newAngle.angle = stopAngle; | 594 | newAngle.angle = stopAngle; |
595 | newAngle.X = iX; | 595 | newAngle.X = iX; |
596 | newAngle.Y = iY; | 596 | newAngle.Y = iY; |
597 | angles[index] = newAngle; | 597 | angles[index] = newAngle; |
598 | } | 598 | } |
599 | } | 599 | } |
600 | } | 600 | } |
601 | } | 601 | } |
602 | 602 | ||
603 | /// <summary> | 603 | /// <summary> |
604 | /// generates a profile for extrusion | 604 | /// generates a profile for extrusion |
605 | /// </summary> | 605 | /// </summary> |
606 | internal class Profile | 606 | internal class Profile |
607 | { | 607 | { |
608 | private const float twoPi = 2.0f * (float)Math.PI; | 608 | private const float twoPi = 2.0f * (float)Math.PI; |
609 | 609 | ||
610 | internal string errorMessage = null; | 610 | internal string errorMessage = null; |
611 | 611 | ||
612 | internal List<Coord> coords; | 612 | internal List<Coord> coords; |
613 | internal List<Face> faces; | 613 | internal List<Face> faces; |
614 | internal List<Coord> vertexNormals; | 614 | internal List<Coord> vertexNormals; |
615 | internal List<float> us; | 615 | internal List<float> us; |
616 | internal List<UVCoord> faceUVs; | 616 | internal List<UVCoord> faceUVs; |
617 | internal List<int> faceNumbers; | 617 | internal List<int> faceNumbers; |
618 | 618 | ||
619 | // use these for making individual meshes for each prim face | 619 | // use these for making individual meshes for each prim face |
620 | internal List<int> outerCoordIndices = null; | 620 | internal List<int> outerCoordIndices = null; |
621 | internal List<int> hollowCoordIndices = null; | 621 | internal List<int> hollowCoordIndices = null; |
622 | internal List<int> cut1CoordIndices = null; | 622 | internal List<int> cut1CoordIndices = null; |
623 | internal List<int> cut2CoordIndices = null; | 623 | internal List<int> cut2CoordIndices = null; |
624 | 624 | ||
625 | internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); | 625 | internal Coord faceNormal = new Coord(0.0f, 0.0f, 1.0f); |
626 | internal Coord cutNormal1 = new Coord(); | 626 | internal Coord cutNormal1 = new Coord(); |
627 | internal Coord cutNormal2 = new Coord(); | 627 | internal Coord cutNormal2 = new Coord(); |
628 | 628 | ||
629 | internal int numOuterVerts = 0; | 629 | internal int numOuterVerts = 0; |
630 | internal int numHollowVerts = 0; | 630 | internal int numHollowVerts = 0; |
631 | 631 | ||
632 | internal int outerFaceNumber = -1; | 632 | internal int outerFaceNumber = -1; |
633 | internal int hollowFaceNumber = -1; | 633 | internal int hollowFaceNumber = -1; |
634 | 634 | ||
635 | internal bool calcVertexNormals = false; | 635 | internal bool calcVertexNormals = false; |
636 | internal int bottomFaceNumber = 0; | 636 | internal int bottomFaceNumber = 0; |
637 | internal int numPrimFaces = 0; | 637 | internal int numPrimFaces = 0; |
638 | 638 | ||
639 | internal Profile() | 639 | internal Profile() |
640 | { | 640 | { |
641 | this.coords = new List<Coord>(); | 641 | this.coords = new List<Coord>(); |
642 | this.faces = new List<Face>(); | 642 | this.faces = new List<Face>(); |
643 | this.vertexNormals = new List<Coord>(); | 643 | this.vertexNormals = new List<Coord>(); |
644 | this.us = new List<float>(); | 644 | this.us = new List<float>(); |
645 | this.faceUVs = new List<UVCoord>(); | 645 | this.faceUVs = new List<UVCoord>(); |
646 | this.faceNumbers = new List<int>(); | 646 | this.faceNumbers = new List<int>(); |
647 | } | 647 | } |
648 | 648 | ||
649 | internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) | 649 | internal Profile(int sides, float profileStart, float profileEnd, float hollow, int hollowSides, bool createFaces, bool calcVertexNormals) |
650 | { | 650 | { |
651 | this.calcVertexNormals = calcVertexNormals; | 651 | this.calcVertexNormals = calcVertexNormals; |
652 | this.coords = new List<Coord>(); | 652 | this.coords = new List<Coord>(); |
653 | this.faces = new List<Face>(); | 653 | this.faces = new List<Face>(); |
654 | this.vertexNormals = new List<Coord>(); | 654 | this.vertexNormals = new List<Coord>(); |
655 | this.us = new List<float>(); | 655 | this.us = new List<float>(); |
656 | this.faceUVs = new List<UVCoord>(); | 656 | this.faceUVs = new List<UVCoord>(); |
657 | this.faceNumbers = new List<int>(); | 657 | this.faceNumbers = new List<int>(); |
658 | 658 | ||
659 | Coord center = new Coord(0.0f, 0.0f, 0.0f); | 659 | Coord center = new Coord(0.0f, 0.0f, 0.0f); |
660 | //bool hasCenter = false; | 660 | //bool hasCenter = false; |
661 | 661 | ||
662 | List<Coord> hollowCoords = new List<Coord>(); | 662 | List<Coord> hollowCoords = new List<Coord>(); |
663 | List<Coord> hollowNormals = new List<Coord>(); | 663 | List<Coord> hollowNormals = new List<Coord>(); |
664 | List<float> hollowUs = new List<float>(); | 664 | List<float> hollowUs = new List<float>(); |
665 | 665 | ||
666 | if (calcVertexNormals) | 666 | if (calcVertexNormals) |
667 | { | 667 | { |
668 | this.outerCoordIndices = new List<int>(); | 668 | this.outerCoordIndices = new List<int>(); |
669 | this.hollowCoordIndices = new List<int>(); | 669 | this.hollowCoordIndices = new List<int>(); |
670 | this.cut1CoordIndices = new List<int>(); | 670 | this.cut1CoordIndices = new List<int>(); |
671 | this.cut2CoordIndices = new List<int>(); | 671 | this.cut2CoordIndices = new List<int>(); |
672 | } | 672 | } |
673 | 673 | ||
674 | bool hasHollow = (hollow > 0.0f); | 674 | bool hasHollow = (hollow > 0.0f); |
675 | 675 | ||
676 | bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f); | 676 | bool hasProfileCut = (profileStart > 0.0f || profileEnd < 1.0f); |
677 | 677 | ||
678 | AngleList angles = new AngleList(); | 678 | AngleList angles = new AngleList(); |
679 | AngleList hollowAngles = new AngleList(); | 679 | AngleList hollowAngles = new AngleList(); |
680 | 680 | ||
681 | float xScale = 0.5f; | 681 | float xScale = 0.5f; |
682 | float yScale = 0.5f; | 682 | float yScale = 0.5f; |
683 | if (sides == 4) // corners of a square are sqrt(2) from center | 683 | if (sides == 4) // corners of a square are sqrt(2) from center |
684 | { | 684 | { |
685 | xScale = 0.707f; | 685 | xScale = 0.707f; |
686 | yScale = 0.707f; | 686 | yScale = 0.707f; |
687 | } | 687 | } |
688 | 688 | ||
689 | float startAngle = profileStart * twoPi; | 689 | float startAngle = profileStart * twoPi; |
690 | float stopAngle = profileEnd * twoPi; | 690 | float stopAngle = profileEnd * twoPi; |
691 | 691 | ||
692 | try { angles.makeAngles(sides, startAngle, stopAngle); } | 692 | try { angles.makeAngles(sides, startAngle, stopAngle); } |
693 | catch (Exception ex) | 693 | catch (Exception ex) |
694 | { | 694 | { |
695 | 695 | ||
696 | errorMessage = "makeAngles failed: Exception: " + ex.ToString() | 696 | errorMessage = "makeAngles failed: Exception: " + ex.ToString() |
697 | + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); | 697 | + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); |
698 | 698 | ||
699 | return; | 699 | return; |
700 | } | 700 | } |
701 | 701 | ||
702 | this.numOuterVerts = angles.angles.Count; | 702 | this.numOuterVerts = angles.angles.Count; |
703 | 703 | ||
704 | // flag to create as few triangles as possible for 3 or 4 side profile | 704 | // flag to create as few triangles as possible for 3 or 4 side profile |
705 | bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); | 705 | bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut); |
706 | 706 | ||
707 | if (hasHollow) | 707 | if (hasHollow) |
708 | { | 708 | { |
709 | if (sides == hollowSides) | 709 | if (sides == hollowSides) |
710 | hollowAngles = angles; | 710 | hollowAngles = angles; |
711 | else | 711 | else |
712 | { | 712 | { |
713 | try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); } | 713 | try { hollowAngles.makeAngles(hollowSides, startAngle, stopAngle); } |
714 | catch (Exception ex) | 714 | catch (Exception ex) |
715 | { | 715 | { |
716 | errorMessage = "makeAngles failed: Exception: " + ex.ToString() | 716 | errorMessage = "makeAngles failed: Exception: " + ex.ToString() |
717 | + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); | 717 | + "\nsides: " + sides.ToString() + " startAngle: " + startAngle.ToString() + " stopAngle: " + stopAngle.ToString(); |
718 | 718 | ||
719 | return; | 719 | return; |
720 | } | 720 | } |
721 | } | 721 | } |
722 | this.numHollowVerts = hollowAngles.angles.Count; | 722 | this.numHollowVerts = hollowAngles.angles.Count; |
723 | } | 723 | } |
724 | else if (!simpleFace) | 724 | else if (!simpleFace) |
725 | { | 725 | { |
726 | this.coords.Add(center); | 726 | this.coords.Add(center); |
727 | //hasCenter = true; | 727 | //hasCenter = true; |
728 | if (this.calcVertexNormals) | 728 | if (this.calcVertexNormals) |
729 | this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); | 729 | this.vertexNormals.Add(new Coord(0.0f, 0.0f, 1.0f)); |
730 | this.us.Add(0.0f); | 730 | this.us.Add(0.0f); |
731 | } | 731 | } |
732 | 732 | ||
733 | float z = 0.0f; | 733 | float z = 0.0f; |
734 | 734 | ||
735 | Angle angle; | 735 | Angle angle; |
736 | Coord newVert = new Coord(); | 736 | Coord newVert = new Coord(); |
737 | if (hasHollow && hollowSides != sides) | 737 | if (hasHollow && hollowSides != sides) |
738 | { | 738 | { |
739 | int numHollowAngles = hollowAngles.angles.Count; | 739 | int numHollowAngles = hollowAngles.angles.Count; |
740 | for (int i = 0; i < numHollowAngles; i++) | 740 | for (int i = 0; i < numHollowAngles; i++) |
741 | { | 741 | { |
742 | angle = hollowAngles.angles[i]; | 742 | angle = hollowAngles.angles[i]; |
743 | newVert.X = hollow * xScale * angle.X; | 743 | newVert.X = hollow * xScale * angle.X; |
744 | newVert.Y = hollow * yScale * angle.Y; | 744 | newVert.Y = hollow * yScale * angle.Y; |
745 | newVert.Z = z; | 745 | newVert.Z = z; |
746 | 746 | ||
747 | hollowCoords.Add(newVert); | 747 | hollowCoords.Add(newVert); |
748 | if (this.calcVertexNormals) | 748 | if (this.calcVertexNormals) |
749 | { | 749 | { |
750 | if (hollowSides < 5) | 750 | if (hollowSides < 5) |
751 | hollowNormals.Add(hollowAngles.normals[i].Invert()); | 751 | hollowNormals.Add(hollowAngles.normals[i].Invert()); |
752 | else | 752 | else |
753 | hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); | 753 | hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); |
754 | 754 | ||
755 | hollowUs.Add(angle.angle * hollow); | 755 | hollowUs.Add(angle.angle * hollow); |
756 | } | 756 | } |
757 | } | 757 | } |
758 | } | 758 | } |
759 | 759 | ||
760 | int index = 0; | 760 | int index = 0; |
761 | int numAngles = angles.angles.Count; | 761 | int numAngles = angles.angles.Count; |
762 | 762 | ||
763 | for (int i = 0; i < numAngles; i++) | 763 | for (int i = 0; i < numAngles; i++) |
764 | { | 764 | { |
765 | angle = angles.angles[i]; | 765 | angle = angles.angles[i]; |
766 | newVert.X = angle.X * xScale; | 766 | newVert.X = angle.X * xScale; |
767 | newVert.Y = angle.Y * yScale; | 767 | newVert.Y = angle.Y * yScale; |
768 | newVert.Z = z; | 768 | newVert.Z = z; |
769 | this.coords.Add(newVert); | 769 | this.coords.Add(newVert); |
770 | if (this.calcVertexNormals) | 770 | if (this.calcVertexNormals) |
771 | { | 771 | { |
772 | this.outerCoordIndices.Add(this.coords.Count - 1); | 772 | this.outerCoordIndices.Add(this.coords.Count - 1); |
773 | 773 | ||
774 | if (sides < 5) | 774 | if (sides < 5) |
775 | { | 775 | { |
776 | this.vertexNormals.Add(angles.normals[i]); | 776 | this.vertexNormals.Add(angles.normals[i]); |
777 | float u = angle.angle; | 777 | float u = angle.angle; |
778 | this.us.Add(u); | 778 | this.us.Add(u); |
779 | } | 779 | } |
780 | else | 780 | else |
781 | { | 781 | { |
782 | this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f)); | 782 | this.vertexNormals.Add(new Coord(angle.X, angle.Y, 0.0f)); |
783 | this.us.Add(angle.angle); | 783 | this.us.Add(angle.angle); |
784 | } | 784 | } |
785 | } | 785 | } |
786 | 786 | ||
787 | if (hasHollow) | 787 | if (hasHollow) |
788 | { | 788 | { |
789 | if (hollowSides == sides) | 789 | if (hollowSides == sides) |
790 | { | 790 | { |
791 | newVert.X *= hollow; | 791 | newVert.X *= hollow; |
792 | newVert.Y *= hollow; | 792 | newVert.Y *= hollow; |
793 | newVert.Z = z; | 793 | newVert.Z = z; |
794 | hollowCoords.Add(newVert); | 794 | hollowCoords.Add(newVert); |
795 | if (this.calcVertexNormals) | 795 | if (this.calcVertexNormals) |
796 | { | 796 | { |
797 | if (sides < 5) | 797 | if (sides < 5) |
798 | { | 798 | { |
799 | hollowNormals.Add(angles.normals[i].Invert()); | 799 | hollowNormals.Add(angles.normals[i].Invert()); |
800 | } | 800 | } |
801 | 801 | ||
802 | else | 802 | else |
803 | hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); | 803 | hollowNormals.Add(new Coord(-angle.X, -angle.Y, 0.0f)); |
804 | 804 | ||
805 | hollowUs.Add(angle.angle * hollow); | 805 | hollowUs.Add(angle.angle * hollow); |
806 | } | 806 | } |
807 | } | 807 | } |
808 | } | 808 | } |
809 | else if (!simpleFace && createFaces && angle.angle > 0.0001f) | 809 | else if (!simpleFace && createFaces && angle.angle > 0.0001f) |
810 | { | 810 | { |
811 | Face newFace = new Face(); | 811 | Face newFace = new Face(); |
812 | newFace.v1 = 0; | 812 | newFace.v1 = 0; |
813 | newFace.v2 = index; | 813 | newFace.v2 = index; |
814 | newFace.v3 = index + 1; | 814 | newFace.v3 = index + 1; |
815 | 815 | ||
816 | this.faces.Add(newFace); | 816 | this.faces.Add(newFace); |
817 | } | 817 | } |
818 | index += 1; | 818 | index += 1; |
819 | } | 819 | } |
820 | 820 | ||
821 | if (hasHollow) | 821 | if (hasHollow) |
822 | { | 822 | { |
823 | hollowCoords.Reverse(); | 823 | hollowCoords.Reverse(); |
824 | if (this.calcVertexNormals) | 824 | if (this.calcVertexNormals) |
825 | { | 825 | { |
826 | hollowNormals.Reverse(); | 826 | hollowNormals.Reverse(); |
827 | hollowUs.Reverse(); | 827 | hollowUs.Reverse(); |
828 | } | 828 | } |
829 | 829 | ||
830 | if (createFaces) | 830 | if (createFaces) |
831 | { | 831 | { |
832 | //int numOuterVerts = this.coords.Count; | 832 | //int numOuterVerts = this.coords.Count; |
833 | //numOuterVerts = this.coords.Count; | 833 | //numOuterVerts = this.coords.Count; |
834 | //int numHollowVerts = hollowCoords.Count; | 834 | //int numHollowVerts = hollowCoords.Count; |
835 | int numTotalVerts = this.numOuterVerts + this.numHollowVerts; | 835 | int numTotalVerts = this.numOuterVerts + this.numHollowVerts; |
836 | 836 | ||
837 | if (this.numOuterVerts == this.numHollowVerts) | 837 | if (this.numOuterVerts == this.numHollowVerts) |
838 | { | 838 | { |
839 | Face newFace = new Face(); | 839 | Face newFace = new Face(); |
840 | 840 | ||
841 | for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++) | 841 | for (int coordIndex = 0; coordIndex < this.numOuterVerts - 1; coordIndex++) |
842 | { | 842 | { |
843 | newFace.v1 = coordIndex; | 843 | newFace.v1 = coordIndex; |
844 | newFace.v2 = coordIndex + 1; | 844 | newFace.v2 = coordIndex + 1; |
845 | newFace.v3 = numTotalVerts - coordIndex - 1; | 845 | newFace.v3 = numTotalVerts - coordIndex - 1; |
846 | this.faces.Add(newFace); | 846 | this.faces.Add(newFace); |
847 | 847 | ||
848 | newFace.v1 = coordIndex + 1; | 848 | newFace.v1 = coordIndex + 1; |
849 | newFace.v2 = numTotalVerts - coordIndex - 2; | 849 | newFace.v2 = numTotalVerts - coordIndex - 2; |
850 | newFace.v3 = numTotalVerts - coordIndex - 1; | 850 | newFace.v3 = numTotalVerts - coordIndex - 1; |
851 | this.faces.Add(newFace); | 851 | this.faces.Add(newFace); |
852 | } | 852 | } |
853 | } | 853 | } |
854 | else | 854 | else |
855 | { | 855 | { |
856 | if (this.numOuterVerts < this.numHollowVerts) | 856 | if (this.numOuterVerts < this.numHollowVerts) |
857 | { | 857 | { |
858 | Face newFace = new Face(); | 858 | Face newFace = new Face(); |
859 | int j = 0; // j is the index for outer vertices | 859 | int j = 0; // j is the index for outer vertices |
860 | int maxJ = this.numOuterVerts - 1; | 860 | int maxJ = this.numOuterVerts - 1; |
861 | for (int i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices | 861 | for (int i = 0; i < this.numHollowVerts; i++) // i is the index for inner vertices |
862 | { | 862 | { |
863 | if (j < maxJ) | 863 | if (j < maxJ) |
864 | if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f) | 864 | if (angles.angles[j + 1].angle - hollowAngles.angles[i].angle < hollowAngles.angles[i].angle - angles.angles[j].angle + 0.000001f) |
865 | { | 865 | { |
866 | newFace.v1 = numTotalVerts - i - 1; | 866 | newFace.v1 = numTotalVerts - i - 1; |
867 | newFace.v2 = j; | 867 | newFace.v2 = j; |
868 | newFace.v3 = j + 1; | 868 | newFace.v3 = j + 1; |
869 | 869 | ||
870 | this.faces.Add(newFace); | 870 | this.faces.Add(newFace); |
871 | j += 1; | 871 | j += 1; |
872 | } | 872 | } |
873 | 873 | ||
874 | newFace.v1 = j; | 874 | newFace.v1 = j; |
875 | newFace.v2 = numTotalVerts - i - 2; | 875 | newFace.v2 = numTotalVerts - i - 2; |
876 | newFace.v3 = numTotalVerts - i - 1; | 876 | newFace.v3 = numTotalVerts - i - 1; |
877 | 877 | ||
878 | this.faces.Add(newFace); | 878 | this.faces.Add(newFace); |
879 | } | 879 | } |
880 | } | 880 | } |
881 | else // numHollowVerts < numOuterVerts | 881 | else // numHollowVerts < numOuterVerts |
882 | { | 882 | { |
883 | Face newFace = new Face(); | 883 | Face newFace = new Face(); |
884 | int j = 0; // j is the index for inner vertices | 884 | int j = 0; // j is the index for inner vertices |
885 | int maxJ = this.numHollowVerts - 1; | 885 | int maxJ = this.numHollowVerts - 1; |
886 | for (int i = 0; i < this.numOuterVerts; i++) | 886 | for (int i = 0; i < this.numOuterVerts; i++) |
887 | { | 887 | { |
888 | if (j < maxJ) | 888 | if (j < maxJ) |
889 | if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f) | 889 | if (hollowAngles.angles[j + 1].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[j].angle + 0.000001f) |
890 | { | 890 | { |
891 | newFace.v1 = i; | 891 | newFace.v1 = i; |
892 | newFace.v2 = numTotalVerts - j - 2; | 892 | newFace.v2 = numTotalVerts - j - 2; |
893 | newFace.v3 = numTotalVerts - j - 1; | 893 | newFace.v3 = numTotalVerts - j - 1; |
894 | 894 | ||
895 | this.faces.Add(newFace); | 895 | this.faces.Add(newFace); |
896 | j += 1; | 896 | j += 1; |
897 | } | 897 | } |
898 | 898 | ||
899 | newFace.v1 = numTotalVerts - j - 1; | 899 | newFace.v1 = numTotalVerts - j - 1; |
900 | newFace.v2 = i; | 900 | newFace.v2 = i; |
901 | newFace.v3 = i + 1; | 901 | newFace.v3 = i + 1; |
902 | 902 | ||
903 | this.faces.Add(newFace); | 903 | this.faces.Add(newFace); |
904 | } | 904 | } |
905 | } | 905 | } |
906 | } | 906 | } |
907 | } | 907 | } |
908 | 908 | ||
909 | if (calcVertexNormals) | 909 | if (calcVertexNormals) |
910 | { | 910 | { |
911 | foreach (Coord hc in hollowCoords) | 911 | foreach (Coord hc in hollowCoords) |
912 | { | 912 | { |
913 | this.coords.Add(hc); | 913 | this.coords.Add(hc); |
914 | hollowCoordIndices.Add(this.coords.Count - 1); | 914 | hollowCoordIndices.Add(this.coords.Count - 1); |
915 | } | 915 | } |
916 | } | 916 | } |
917 | else | 917 | else |
918 | this.coords.AddRange(hollowCoords); | 918 | this.coords.AddRange(hollowCoords); |
919 | 919 | ||
920 | if (this.calcVertexNormals) | 920 | if (this.calcVertexNormals) |
921 | { | 921 | { |
922 | this.vertexNormals.AddRange(hollowNormals); | 922 | this.vertexNormals.AddRange(hollowNormals); |
923 | this.us.AddRange(hollowUs); | 923 | this.us.AddRange(hollowUs); |
924 | 924 | ||
925 | } | 925 | } |
926 | } | 926 | } |
927 | 927 | ||
928 | if (simpleFace && createFaces) | 928 | if (simpleFace && createFaces) |
929 | { | 929 | { |
930 | if (sides == 3) | 930 | if (sides == 3) |
931 | this.faces.Add(new Face(0, 1, 2)); | 931 | this.faces.Add(new Face(0, 1, 2)); |
932 | else if (sides == 4) | 932 | else if (sides == 4) |
933 | { | 933 | { |
934 | this.faces.Add(new Face(0, 1, 2)); | 934 | this.faces.Add(new Face(0, 1, 2)); |
935 | this.faces.Add(new Face(0, 2, 3)); | 935 | this.faces.Add(new Face(0, 2, 3)); |
936 | } | 936 | } |
937 | } | 937 | } |
938 | 938 | ||
939 | if (calcVertexNormals && hasProfileCut) | 939 | if (calcVertexNormals && hasProfileCut) |
940 | { | 940 | { |
941 | int lastOuterVertIndex = this.numOuterVerts - 1; | 941 | int lastOuterVertIndex = this.numOuterVerts - 1; |
942 | 942 | ||
943 | if (hasHollow) | 943 | if (hasHollow) |
944 | { | 944 | { |
945 | this.cut1CoordIndices.Add(0); | 945 | this.cut1CoordIndices.Add(0); |
946 | this.cut1CoordIndices.Add(this.coords.Count - 1); | 946 | this.cut1CoordIndices.Add(this.coords.Count - 1); |
947 | 947 | ||
948 | this.cut2CoordIndices.Add(lastOuterVertIndex + 1); | 948 | this.cut2CoordIndices.Add(lastOuterVertIndex + 1); |
949 | this.cut2CoordIndices.Add(lastOuterVertIndex); | 949 | this.cut2CoordIndices.Add(lastOuterVertIndex); |
950 | 950 | ||
951 | this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y; | 951 | this.cutNormal1.X = this.coords[0].Y - this.coords[this.coords.Count - 1].Y; |
952 | this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X); | 952 | this.cutNormal1.Y = -(this.coords[0].X - this.coords[this.coords.Count - 1].X); |
953 | 953 | ||
954 | this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y; | 954 | this.cutNormal2.X = this.coords[lastOuterVertIndex + 1].Y - this.coords[lastOuterVertIndex].Y; |
955 | this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X); | 955 | this.cutNormal2.Y = -(this.coords[lastOuterVertIndex + 1].X - this.coords[lastOuterVertIndex].X); |
956 | } | 956 | } |
957 | 957 | ||
958 | else | 958 | else |
959 | { | 959 | { |
960 | this.cut1CoordIndices.Add(0); | 960 | this.cut1CoordIndices.Add(0); |
961 | this.cut1CoordIndices.Add(1); | 961 | this.cut1CoordIndices.Add(1); |
962 | 962 | ||
963 | this.cut2CoordIndices.Add(lastOuterVertIndex); | 963 | this.cut2CoordIndices.Add(lastOuterVertIndex); |
964 | this.cut2CoordIndices.Add(0); | 964 | this.cut2CoordIndices.Add(0); |
965 | 965 | ||
966 | this.cutNormal1.X = this.vertexNormals[1].Y; | 966 | this.cutNormal1.X = this.vertexNormals[1].Y; |
967 | this.cutNormal1.Y = -this.vertexNormals[1].X; | 967 | this.cutNormal1.Y = -this.vertexNormals[1].X; |
968 | 968 | ||
969 | this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y; | 969 | this.cutNormal2.X = -this.vertexNormals[this.vertexNormals.Count - 2].Y; |
970 | this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X; | 970 | this.cutNormal2.Y = this.vertexNormals[this.vertexNormals.Count - 2].X; |
971 | 971 | ||
972 | } | 972 | } |
973 | this.cutNormal1.Normalize(); | 973 | this.cutNormal1.Normalize(); |
974 | this.cutNormal2.Normalize(); | 974 | this.cutNormal2.Normalize(); |
975 | } | 975 | } |
976 | 976 | ||
977 | this.MakeFaceUVs(); | 977 | this.MakeFaceUVs(); |
978 | 978 | ||
979 | hollowCoords = null; | 979 | hollowCoords = null; |
980 | hollowNormals = null; | 980 | hollowNormals = null; |
981 | hollowUs = null; | 981 | hollowUs = null; |
982 | 982 | ||
983 | if (calcVertexNormals) | 983 | if (calcVertexNormals) |
984 | { // calculate prim face numbers | 984 | { // calculate prim face numbers |
985 | 985 | ||
986 | // face number order is top, outer, hollow, bottom, start cut, end cut | 986 | // face number order is top, outer, hollow, bottom, start cut, end cut |
987 | // I know it's ugly but so is the whole concept of prim face numbers | 987 | // I know it's ugly but so is the whole concept of prim face numbers |
988 | 988 | ||
989 | int faceNum = 1; // start with outer faces | 989 | int faceNum = 1; // start with outer faces |
990 | this.outerFaceNumber = faceNum; | 990 | this.outerFaceNumber = faceNum; |
991 | 991 | ||
992 | int startVert = hasProfileCut && !hasHollow ? 1 : 0; | 992 | int startVert = hasProfileCut && !hasHollow ? 1 : 0; |
993 | if (startVert > 0) | 993 | if (startVert > 0) |
994 | this.faceNumbers.Add(-1); | 994 | this.faceNumbers.Add(-1); |
995 | for (int i = 0; i < this.numOuterVerts - 1; i++) | 995 | for (int i = 0; i < this.numOuterVerts - 1; i++) |
996 | //this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); | 996 | //this.faceNumbers.Add(sides < 5 ? faceNum++ : faceNum); |
997 | this.faceNumbers.Add(sides < 5 && i < sides ? faceNum++ : faceNum); | 997 | this.faceNumbers.Add(sides < 5 && i < sides ? faceNum++ : faceNum); |
998 | 998 | ||
999 | //if (!hasHollow && !hasProfileCut) | 999 | //if (!hasHollow && !hasProfileCut) |
1000 | // this.bottomFaceNumber = faceNum++; | 1000 | // this.bottomFaceNumber = faceNum++; |
1001 | 1001 | ||
1002 | this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); | 1002 | this.faceNumbers.Add(hasProfileCut ? -1 : faceNum++); |
1003 | 1003 | ||
1004 | if (sides > 4 && (hasHollow || hasProfileCut)) | 1004 | if (sides > 4 && (hasHollow || hasProfileCut)) |
1005 | faceNum++; | 1005 | faceNum++; |
1006 | 1006 | ||
1007 | if (sides < 5 && (hasHollow || hasProfileCut) && this.numOuterVerts < sides) | 1007 | if (sides < 5 && (hasHollow || hasProfileCut) && this.numOuterVerts < sides) |
1008 | faceNum++; | 1008 | faceNum++; |
1009 | 1009 | ||
1010 | if (hasHollow) | 1010 | if (hasHollow) |
1011 | { | 1011 | { |
1012 | for (int i = 0; i < this.numHollowVerts; i++) | 1012 | for (int i = 0; i < this.numHollowVerts; i++) |
1013 | this.faceNumbers.Add(faceNum); | 1013 | this.faceNumbers.Add(faceNum); |
1014 | 1014 | ||
1015 | this.hollowFaceNumber = faceNum++; | 1015 | this.hollowFaceNumber = faceNum++; |
1016 | } | 1016 | } |
1017 | //if (hasProfileCut || hasHollow) | 1017 | //if (hasProfileCut || hasHollow) |
1018 | // this.bottomFaceNumber = faceNum++; | 1018 | // this.bottomFaceNumber = faceNum++; |
1019 | this.bottomFaceNumber = faceNum++; | 1019 | this.bottomFaceNumber = faceNum++; |
1020 | 1020 | ||
1021 | if (hasHollow && hasProfileCut) | 1021 | if (hasHollow && hasProfileCut) |
1022 | this.faceNumbers.Add(faceNum++); | 1022 | this.faceNumbers.Add(faceNum++); |
1023 | 1023 | ||
1024 | for (int i = 0; i < this.faceNumbers.Count; i++) | 1024 | for (int i = 0; i < this.faceNumbers.Count; i++) |
1025 | if (this.faceNumbers[i] == -1) | 1025 | if (this.faceNumbers[i] == -1) |
1026 | this.faceNumbers[i] = faceNum++; | 1026 | this.faceNumbers[i] = faceNum++; |
1027 | 1027 | ||
1028 | this.numPrimFaces = faceNum; | 1028 | this.numPrimFaces = faceNum; |
1029 | } | 1029 | } |
1030 | 1030 | ||
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | internal void MakeFaceUVs() | 1033 | internal void MakeFaceUVs() |
1034 | { | 1034 | { |
1035 | this.faceUVs = new List<UVCoord>(); | 1035 | this.faceUVs = new List<UVCoord>(); |
1036 | foreach (Coord c in this.coords) | 1036 | foreach (Coord c in this.coords) |
1037 | this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y)); | 1037 | this.faceUVs.Add(new UVCoord(0.5f + c.X, 0.5f - c.Y)); |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | internal Profile Copy() | 1040 | internal Profile Copy() |
1041 | { | 1041 | { |
1042 | return this.Copy(true); | 1042 | return this.Copy(true); |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | internal Profile Copy(bool needFaces) | 1045 | internal Profile Copy(bool needFaces) |
1046 | { | 1046 | { |
1047 | Profile copy = new Profile(); | 1047 | Profile copy = new Profile(); |
1048 | 1048 | ||
1049 | copy.coords.AddRange(this.coords); | 1049 | copy.coords.AddRange(this.coords); |
1050 | copy.faceUVs.AddRange(this.faceUVs); | 1050 | copy.faceUVs.AddRange(this.faceUVs); |
1051 | 1051 | ||
1052 | if (needFaces) | 1052 | if (needFaces) |
1053 | copy.faces.AddRange(this.faces); | 1053 | copy.faces.AddRange(this.faces); |
1054 | if ((copy.calcVertexNormals = this.calcVertexNormals) == true) | 1054 | if ((copy.calcVertexNormals = this.calcVertexNormals) == true) |
1055 | { | 1055 | { |
1056 | copy.vertexNormals.AddRange(this.vertexNormals); | 1056 | copy.vertexNormals.AddRange(this.vertexNormals); |
1057 | copy.faceNormal = this.faceNormal; | 1057 | copy.faceNormal = this.faceNormal; |
1058 | copy.cutNormal1 = this.cutNormal1; | 1058 | copy.cutNormal1 = this.cutNormal1; |
1059 | copy.cutNormal2 = this.cutNormal2; | 1059 | copy.cutNormal2 = this.cutNormal2; |
1060 | copy.us.AddRange(this.us); | 1060 | copy.us.AddRange(this.us); |
1061 | copy.faceNumbers.AddRange(this.faceNumbers); | 1061 | copy.faceNumbers.AddRange(this.faceNumbers); |
1062 | 1062 | ||
1063 | copy.cut1CoordIndices = new List<int>(this.cut1CoordIndices); | 1063 | copy.cut1CoordIndices = new List<int>(this.cut1CoordIndices); |
1064 | copy.cut2CoordIndices = new List<int>(this.cut2CoordIndices); | 1064 | copy.cut2CoordIndices = new List<int>(this.cut2CoordIndices); |
1065 | copy.hollowCoordIndices = new List<int>(this.hollowCoordIndices); | 1065 | copy.hollowCoordIndices = new List<int>(this.hollowCoordIndices); |
1066 | copy.outerCoordIndices = new List<int>(this.outerCoordIndices); | 1066 | copy.outerCoordIndices = new List<int>(this.outerCoordIndices); |
1067 | } | 1067 | } |
1068 | copy.numOuterVerts = this.numOuterVerts; | 1068 | copy.numOuterVerts = this.numOuterVerts; |
1069 | copy.numHollowVerts = this.numHollowVerts; | 1069 | copy.numHollowVerts = this.numHollowVerts; |
1070 | 1070 | ||
1071 | return copy; | 1071 | return copy; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | internal void AddPos(Coord v) | 1074 | internal void AddPos(Coord v) |
1075 | { | 1075 | { |
1076 | this.AddPos(v.X, v.Y, v.Z); | 1076 | this.AddPos(v.X, v.Y, v.Z); |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | internal void AddPos(float x, float y, float z) | 1079 | internal void AddPos(float x, float y, float z) |
1080 | { | 1080 | { |
1081 | int i; | 1081 | int i; |
1082 | int numVerts = this.coords.Count; | 1082 | int numVerts = this.coords.Count; |
1083 | Coord vert; | 1083 | Coord vert; |
1084 | 1084 | ||
1085 | for (i = 0; i < numVerts; i++) | 1085 | for (i = 0; i < numVerts; i++) |
1086 | { | 1086 | { |
1087 | vert = this.coords[i]; | 1087 | vert = this.coords[i]; |
1088 | vert.X += x; | 1088 | vert.X += x; |
1089 | vert.Y += y; | 1089 | vert.Y += y; |
1090 | vert.Z += z; | 1090 | vert.Z += z; |
1091 | this.coords[i] = vert; | 1091 | this.coords[i] = vert; |
1092 | } | 1092 | } |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | internal void AddRot(Quat q) | 1095 | internal void AddRot(Quat q) |
1096 | { | 1096 | { |
1097 | int i; | 1097 | int i; |
1098 | int numVerts = this.coords.Count; | 1098 | int numVerts = this.coords.Count; |
1099 | 1099 | ||
1100 | for (i = 0; i < numVerts; i++) | 1100 | for (i = 0; i < numVerts; i++) |
1101 | this.coords[i] *= q; | 1101 | this.coords[i] *= q; |
1102 | 1102 | ||
1103 | if (this.calcVertexNormals) | 1103 | if (this.calcVertexNormals) |
1104 | { | 1104 | { |
1105 | int numNormals = this.vertexNormals.Count; | 1105 | int numNormals = this.vertexNormals.Count; |
1106 | for (i = 0; i < numNormals; i++) | 1106 | for (i = 0; i < numNormals; i++) |
1107 | this.vertexNormals[i] *= q; | 1107 | this.vertexNormals[i] *= q; |
1108 | 1108 | ||
1109 | this.faceNormal *= q; | 1109 | this.faceNormal *= q; |
1110 | this.cutNormal1 *= q; | 1110 | this.cutNormal1 *= q; |
1111 | this.cutNormal2 *= q; | 1111 | this.cutNormal2 *= q; |
1112 | 1112 | ||
1113 | } | 1113 | } |
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | internal void Scale(float x, float y) | 1116 | internal void Scale(float x, float y) |
1117 | { | 1117 | { |
1118 | int i; | 1118 | int i; |
1119 | int numVerts = this.coords.Count; | 1119 | int numVerts = this.coords.Count; |
1120 | Coord vert; | 1120 | Coord vert; |
1121 | 1121 | ||
1122 | for (i = 0; i < numVerts; i++) | 1122 | for (i = 0; i < numVerts; i++) |
1123 | { | 1123 | { |
1124 | vert = this.coords[i]; | 1124 | vert = this.coords[i]; |
1125 | vert.X *= x; | 1125 | vert.X *= x; |
1126 | vert.Y *= y; | 1126 | vert.Y *= y; |
1127 | this.coords[i] = vert; | 1127 | this.coords[i] = vert; |
1128 | } | 1128 | } |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | /// <summary> | 1131 | /// <summary> |
1132 | /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices | 1132 | /// Changes order of the vertex indices and negates the center vertex normal. Does not alter vertex normals of radial vertices |
1133 | /// </summary> | 1133 | /// </summary> |
1134 | internal void FlipNormals() | 1134 | internal void FlipNormals() |
1135 | { | 1135 | { |
1136 | int i; | 1136 | int i; |
1137 | int numFaces = this.faces.Count; | 1137 | int numFaces = this.faces.Count; |
1138 | Face tmpFace; | 1138 | Face tmpFace; |
1139 | int tmp; | 1139 | int tmp; |
1140 | 1140 | ||
1141 | for (i = 0; i < numFaces; i++) | 1141 | for (i = 0; i < numFaces; i++) |
1142 | { | 1142 | { |
1143 | tmpFace = this.faces[i]; | 1143 | tmpFace = this.faces[i]; |
1144 | tmp = tmpFace.v3; | 1144 | tmp = tmpFace.v3; |
1145 | tmpFace.v3 = tmpFace.v1; | 1145 | tmpFace.v3 = tmpFace.v1; |
1146 | tmpFace.v1 = tmp; | 1146 | tmpFace.v1 = tmp; |
1147 | this.faces[i] = tmpFace; | 1147 | this.faces[i] = tmpFace; |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | if (this.calcVertexNormals) | 1150 | if (this.calcVertexNormals) |
1151 | { | 1151 | { |
1152 | int normalCount = this.vertexNormals.Count; | 1152 | int normalCount = this.vertexNormals.Count; |
1153 | if (normalCount > 0) | 1153 | if (normalCount > 0) |
1154 | { | 1154 | { |
1155 | Coord n = this.vertexNormals[normalCount - 1]; | 1155 | Coord n = this.vertexNormals[normalCount - 1]; |
1156 | n.Z = -n.Z; | 1156 | n.Z = -n.Z; |
1157 | this.vertexNormals[normalCount - 1] = n; | 1157 | this.vertexNormals[normalCount - 1] = n; |
1158 | } | 1158 | } |
1159 | } | 1159 | } |
1160 | 1160 | ||
1161 | this.faceNormal.X = -this.faceNormal.X; | 1161 | this.faceNormal.X = -this.faceNormal.X; |
1162 | this.faceNormal.Y = -this.faceNormal.Y; | 1162 | this.faceNormal.Y = -this.faceNormal.Y; |
1163 | this.faceNormal.Z = -this.faceNormal.Z; | 1163 | this.faceNormal.Z = -this.faceNormal.Z; |
1164 | 1164 | ||
1165 | int numfaceUVs = this.faceUVs.Count; | 1165 | int numfaceUVs = this.faceUVs.Count; |
1166 | for (i = 0; i < numfaceUVs; i++) | 1166 | for (i = 0; i < numfaceUVs; i++) |
1167 | { | 1167 | { |
1168 | UVCoord uv = this.faceUVs[i]; | 1168 | UVCoord uv = this.faceUVs[i]; |
1169 | uv.V = 1.0f - uv.V; | 1169 | uv.V = 1.0f - uv.V; |
1170 | this.faceUVs[i] = uv; | 1170 | this.faceUVs[i] = uv; |
1171 | } | 1171 | } |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | internal void AddValue2FaceVertexIndices(int num) | 1174 | internal void AddValue2FaceVertexIndices(int num) |
1175 | { | 1175 | { |
1176 | int numFaces = this.faces.Count; | 1176 | int numFaces = this.faces.Count; |
1177 | Face tmpFace; | 1177 | Face tmpFace; |
1178 | for (int i = 0; i < numFaces; i++) | 1178 | for (int i = 0; i < numFaces; i++) |
1179 | { | 1179 | { |
1180 | tmpFace = this.faces[i]; | 1180 | tmpFace = this.faces[i]; |
1181 | tmpFace.v1 += num; | 1181 | tmpFace.v1 += num; |
1182 | tmpFace.v2 += num; | 1182 | tmpFace.v2 += num; |
1183 | tmpFace.v3 += num; | 1183 | tmpFace.v3 += num; |
1184 | 1184 | ||
1185 | this.faces[i] = tmpFace; | 1185 | this.faces[i] = tmpFace; |
1186 | } | 1186 | } |
1187 | } | 1187 | } |
1188 | 1188 | ||
1189 | internal void AddValue2FaceNormalIndices(int num) | 1189 | internal void AddValue2FaceNormalIndices(int num) |
1190 | { | 1190 | { |
1191 | if (this.calcVertexNormals) | 1191 | if (this.calcVertexNormals) |
1192 | { | 1192 | { |
1193 | int numFaces = this.faces.Count; | 1193 | int numFaces = this.faces.Count; |
1194 | Face tmpFace; | 1194 | Face tmpFace; |
1195 | for (int i = 0; i < numFaces; i++) | 1195 | for (int i = 0; i < numFaces; i++) |
1196 | { | 1196 | { |
1197 | tmpFace = this.faces[i]; | 1197 | tmpFace = this.faces[i]; |
1198 | tmpFace.n1 += num; | 1198 | tmpFace.n1 += num; |
1199 | tmpFace.n2 += num; | 1199 | tmpFace.n2 += num; |
1200 | tmpFace.n3 += num; | 1200 | tmpFace.n3 += num; |
1201 | 1201 | ||
1202 | this.faces[i] = tmpFace; | 1202 | this.faces[i] = tmpFace; |
1203 | } | 1203 | } |
1204 | } | 1204 | } |
1205 | } | 1205 | } |
1206 | 1206 | ||
1207 | internal void DumpRaw(String path, String name, String title) | 1207 | internal void DumpRaw(String path, String name, String title) |
1208 | { | 1208 | { |
1209 | if (path == null) | 1209 | if (path == null) |
1210 | return; | 1210 | return; |
1211 | String fileName = name + "_" + title + ".raw"; | 1211 | String fileName = name + "_" + title + ".raw"; |
1212 | String completePath = System.IO.Path.Combine(path, fileName); | 1212 | String completePath = System.IO.Path.Combine(path, fileName); |
1213 | StreamWriter sw = new StreamWriter(completePath); | 1213 | StreamWriter sw = new StreamWriter(completePath); |
1214 | 1214 | ||
1215 | for (int i = 0; i < this.faces.Count; i++) | 1215 | for (int i = 0; i < this.faces.Count; i++) |
1216 | { | 1216 | { |
1217 | string s = this.coords[this.faces[i].v1].ToString(); | 1217 | string s = this.coords[this.faces[i].v1].ToString(); |
1218 | s += " " + this.coords[this.faces[i].v2].ToString(); | 1218 | s += " " + this.coords[this.faces[i].v2].ToString(); |
1219 | s += " " + this.coords[this.faces[i].v3].ToString(); | 1219 | s += " " + this.coords[this.faces[i].v3].ToString(); |
1220 | 1220 | ||
1221 | sw.WriteLine(s); | 1221 | sw.WriteLine(s); |
1222 | } | 1222 | } |
1223 | 1223 | ||
1224 | sw.Close(); | 1224 | sw.Close(); |
1225 | } | 1225 | } |
1226 | } | 1226 | } |
1227 | 1227 | ||
1228 | public struct PathNode | 1228 | public struct PathNode |
1229 | { | 1229 | { |
1230 | public Coord position; | 1230 | public Coord position; |
1231 | public Quat rotation; | 1231 | public Quat rotation; |
1232 | public float xScale; | 1232 | public float xScale; |
1233 | public float yScale; | 1233 | public float yScale; |
1234 | public float percentOfPath; | 1234 | public float percentOfPath; |
1235 | } | 1235 | } |
1236 | 1236 | ||
1237 | public enum PathType { Linear = 0, Circular = 1, Flexible = 2 } | 1237 | public enum PathType { Linear = 0, Circular = 1, Flexible = 2 } |
1238 | 1238 | ||
1239 | public class Path | 1239 | public class Path |
1240 | { | 1240 | { |
1241 | public List<PathNode> pathNodes = new List<PathNode>(); | 1241 | public List<PathNode> pathNodes = new List<PathNode>(); |
1242 | 1242 | ||
1243 | public float twistBegin = 0.0f; | 1243 | public float twistBegin = 0.0f; |
1244 | public float twistEnd = 0.0f; | 1244 | public float twistEnd = 0.0f; |
1245 | public float topShearX = 0.0f; | 1245 | public float topShearX = 0.0f; |
1246 | public float topShearY = 0.0f; | 1246 | public float topShearY = 0.0f; |
1247 | public float pathCutBegin = 0.0f; | 1247 | public float pathCutBegin = 0.0f; |
1248 | public float pathCutEnd = 1.0f; | 1248 | public float pathCutEnd = 1.0f; |
1249 | public float dimpleBegin = 0.0f; | 1249 | public float dimpleBegin = 0.0f; |
1250 | public float dimpleEnd = 1.0f; | 1250 | public float dimpleEnd = 1.0f; |
1251 | public float skew = 0.0f; | 1251 | public float skew = 0.0f; |
1252 | public float holeSizeX = 1.0f; // called pathScaleX in pbs | 1252 | public float holeSizeX = 1.0f; // called pathScaleX in pbs |
1253 | public float holeSizeY = 0.25f; | 1253 | public float holeSizeY = 0.25f; |
1254 | public float taperX = 0.0f; | 1254 | public float taperX = 0.0f; |
1255 | public float taperY = 0.0f; | 1255 | public float taperY = 0.0f; |
1256 | public float radius = 0.0f; | 1256 | public float radius = 0.0f; |
1257 | public float revolutions = 1.0f; | 1257 | public float revolutions = 1.0f; |
1258 | public int stepsPerRevolution = 24; | 1258 | public int stepsPerRevolution = 24; |
1259 | 1259 | ||
1260 | private const float twoPi = 2.0f * (float)Math.PI; | 1260 | private const float twoPi = 2.0f * (float)Math.PI; |
1261 | 1261 | ||
1262 | public void Create(PathType pathType, int steps) | 1262 | public void Create(PathType pathType, int steps) |
1263 | { | 1263 | { |
1264 | if (pathType == PathType.Linear || pathType == PathType.Flexible) | 1264 | if (pathType == PathType.Linear || pathType == PathType.Flexible) |
1265 | { | 1265 | { |
1266 | int step = 0; | 1266 | int step = 0; |
1267 | 1267 | ||
1268 | float length = this.pathCutEnd - this.pathCutBegin; | 1268 | float length = this.pathCutEnd - this.pathCutBegin; |
1269 | float twistTotal = twistEnd - twistBegin; | 1269 | float twistTotal = twistEnd - twistBegin; |
1270 | float twistTotalAbs = Math.Abs(twistTotal); | 1270 | float twistTotalAbs = Math.Abs(twistTotal); |
1271 | if (twistTotalAbs > 0.01f) | 1271 | if (twistTotalAbs > 0.01f) |
1272 | steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number | 1272 | steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number |
1273 | 1273 | ||
1274 | float start = -0.5f; | 1274 | float start = -0.5f; |
1275 | float stepSize = length / (float)steps; | 1275 | float stepSize = length / (float)steps; |
1276 | float percentOfPathMultiplier = stepSize; | 1276 | float percentOfPathMultiplier = stepSize; |
1277 | float xOffset = 0.0f; | 1277 | float xOffset = 0.0f; |
1278 | float yOffset = 0.0f; | 1278 | float yOffset = 0.0f; |
1279 | float zOffset = start; | 1279 | float zOffset = start; |
1280 | float xOffsetStepIncrement = this.topShearX / steps; | 1280 | float xOffsetStepIncrement = this.topShearX / steps; |
1281 | float yOffsetStepIncrement = this.topShearY / steps; | 1281 | float yOffsetStepIncrement = this.topShearY / steps; |
1282 | 1282 | ||
1283 | float percentOfPath = this.pathCutBegin; | 1283 | float percentOfPath = this.pathCutBegin; |
1284 | zOffset += percentOfPath; | 1284 | zOffset += percentOfPath; |
1285 | 1285 | ||
1286 | // sanity checks | 1286 | // sanity checks |
1287 | 1287 | ||
1288 | bool done = false; | 1288 | bool done = false; |
1289 | 1289 | ||
1290 | while (!done) | 1290 | while (!done) |
1291 | { | 1291 | { |
1292 | PathNode newNode = new PathNode(); | 1292 | PathNode newNode = new PathNode(); |
1293 | 1293 | ||
1294 | newNode.xScale = 1.0f; | 1294 | newNode.xScale = 1.0f; |
1295 | if (this.taperX == 0.0f) | 1295 | if (this.taperX == 0.0f) |
1296 | newNode.xScale = 1.0f; | 1296 | newNode.xScale = 1.0f; |
1297 | else if (this.taperX > 0.0f) | 1297 | else if (this.taperX > 0.0f) |
1298 | newNode.xScale = 1.0f - percentOfPath * this.taperX; | 1298 | newNode.xScale = 1.0f - percentOfPath * this.taperX; |
1299 | else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX; | 1299 | else newNode.xScale = 1.0f + (1.0f - percentOfPath) * this.taperX; |
1300 | 1300 | ||
1301 | newNode.yScale = 1.0f; | 1301 | newNode.yScale = 1.0f; |
1302 | if (this.taperY == 0.0f) | 1302 | if (this.taperY == 0.0f) |
1303 | newNode.yScale = 1.0f; | 1303 | newNode.yScale = 1.0f; |
1304 | else if (this.taperY > 0.0f) | 1304 | else if (this.taperY > 0.0f) |
1305 | newNode.yScale = 1.0f - percentOfPath * this.taperY; | 1305 | newNode.yScale = 1.0f - percentOfPath * this.taperY; |
1306 | else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY; | 1306 | else newNode.yScale = 1.0f + (1.0f - percentOfPath) * this.taperY; |
1307 | 1307 | ||
1308 | float twist = twistBegin + twistTotal * percentOfPath; | 1308 | float twist = twistBegin + twistTotal * percentOfPath; |
1309 | 1309 | ||
1310 | newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); | 1310 | newNode.rotation = new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); |
1311 | newNode.position = new Coord(xOffset, yOffset, zOffset); | 1311 | newNode.position = new Coord(xOffset, yOffset, zOffset); |
1312 | newNode.percentOfPath = percentOfPath; | 1312 | newNode.percentOfPath = percentOfPath; |
1313 | 1313 | ||
1314 | pathNodes.Add(newNode); | 1314 | pathNodes.Add(newNode); |
1315 | 1315 | ||
1316 | if (step < steps) | 1316 | if (step < steps) |
1317 | { | 1317 | { |
1318 | step += 1; | 1318 | step += 1; |
1319 | percentOfPath += percentOfPathMultiplier; | 1319 | percentOfPath += percentOfPathMultiplier; |
1320 | xOffset += xOffsetStepIncrement; | 1320 | xOffset += xOffsetStepIncrement; |
1321 | yOffset += yOffsetStepIncrement; | 1321 | yOffset += yOffsetStepIncrement; |
1322 | zOffset += stepSize; | 1322 | zOffset += stepSize; |
1323 | if (percentOfPath > this.pathCutEnd) | 1323 | if (percentOfPath > this.pathCutEnd) |
1324 | done = true; | 1324 | done = true; |
1325 | } | 1325 | } |
1326 | else done = true; | 1326 | else done = true; |
1327 | } | 1327 | } |
1328 | } // end of linear path code | 1328 | } // end of linear path code |
1329 | 1329 | ||
1330 | else // pathType == Circular | 1330 | else // pathType == Circular |
1331 | { | 1331 | { |
1332 | float twistTotal = twistEnd - twistBegin; | 1332 | float twistTotal = twistEnd - twistBegin; |
1333 | 1333 | ||
1334 | // if the profile has a lot of twist, add more layers otherwise the layers may overlap | 1334 | // if the profile has a lot of twist, add more layers otherwise the layers may overlap |
1335 | // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't | 1335 | // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't |
1336 | // accurately match the viewer | 1336 | // accurately match the viewer |
1337 | float twistTotalAbs = Math.Abs(twistTotal); | 1337 | float twistTotalAbs = Math.Abs(twistTotal); |
1338 | if (twistTotalAbs > 0.01f) | 1338 | if (twistTotalAbs > 0.01f) |
1339 | { | 1339 | { |
1340 | if (twistTotalAbs > Math.PI * 1.5f) | 1340 | if (twistTotalAbs > Math.PI * 1.5f) |
1341 | steps *= 2; | 1341 | steps *= 2; |
1342 | if (twistTotalAbs > Math.PI * 3.0f) | 1342 | if (twistTotalAbs > Math.PI * 3.0f) |
1343 | steps *= 2; | 1343 | steps *= 2; |
1344 | } | 1344 | } |
1345 | 1345 | ||
1346 | float yPathScale = this.holeSizeY * 0.5f; | 1346 | float yPathScale = this.holeSizeY * 0.5f; |
1347 | float pathLength = this.pathCutEnd - this.pathCutBegin; | 1347 | float pathLength = this.pathCutEnd - this.pathCutBegin; |
1348 | float totalSkew = this.skew * 2.0f * pathLength; | 1348 | float totalSkew = this.skew * 2.0f * pathLength; |
1349 | float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew; | 1349 | float skewStart = this.pathCutBegin * 2.0f * this.skew - this.skew; |
1350 | float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY)); | 1350 | float xOffsetTopShearXFactor = this.topShearX * (0.25f + 0.5f * (0.5f - this.holeSizeY)); |
1351 | float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f; | 1351 | float yShearCompensation = 1.0f + Math.Abs(this.topShearY) * 0.25f; |
1352 | 1352 | ||
1353 | // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end | 1353 | // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end |
1354 | // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used | 1354 | // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used |
1355 | // to calculate the sine for generating the path radius appears to approximate it's effects there | 1355 | // to calculate the sine for generating the path radius appears to approximate it's effects there |
1356 | // too, but there are some subtle differences in the radius which are noticeable as the prim size | 1356 | // too, but there are some subtle differences in the radius which are noticeable as the prim size |
1357 | // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on | 1357 | // increases and it may affect megaprims quite a bit. The effect of the Y top shear parameter on |
1358 | // the meshes generated with this technique appear nearly identical in shape to the same prims when | 1358 | // the meshes generated with this technique appear nearly identical in shape to the same prims when |
1359 | // displayed by the viewer. | 1359 | // displayed by the viewer. |
1360 | 1360 | ||
1361 | float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f; | 1361 | float startAngle = (twoPi * this.pathCutBegin * this.revolutions) - this.topShearY * 0.9f; |
1362 | float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f; | 1362 | float endAngle = (twoPi * this.pathCutEnd * this.revolutions) - this.topShearY * 0.9f; |
1363 | float stepSize = twoPi / this.stepsPerRevolution; | 1363 | float stepSize = twoPi / this.stepsPerRevolution; |
1364 | 1364 | ||
1365 | int step = (int)(startAngle / stepSize); | 1365 | int step = (int)(startAngle / stepSize); |
1366 | float angle = startAngle; | 1366 | float angle = startAngle; |
1367 | 1367 | ||
1368 | bool done = false; | 1368 | bool done = false; |
1369 | while (!done) // loop through the length of the path and add the layers | 1369 | while (!done) // loop through the length of the path and add the layers |
1370 | { | 1370 | { |
1371 | PathNode newNode = new PathNode(); | 1371 | PathNode newNode = new PathNode(); |
1372 | 1372 | ||
1373 | float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; | 1373 | float xProfileScale = (1.0f - Math.Abs(this.skew)) * this.holeSizeX; |
1374 | float yProfileScale = this.holeSizeY; | 1374 | float yProfileScale = this.holeSizeY; |
1375 | 1375 | ||
1376 | float percentOfPath = angle / (twoPi * this.revolutions); | 1376 | float percentOfPath = angle / (twoPi * this.revolutions); |
1377 | float percentOfAngles = (angle - startAngle) / (endAngle - startAngle); | 1377 | float percentOfAngles = (angle - startAngle) / (endAngle - startAngle); |
1378 | 1378 | ||
1379 | if (this.taperX > 0.01f) | 1379 | if (this.taperX > 0.01f) |
1380 | xProfileScale *= 1.0f - percentOfPath * this.taperX; | 1380 | xProfileScale *= 1.0f - percentOfPath * this.taperX; |
1381 | else if (this.taperX < -0.01f) | 1381 | else if (this.taperX < -0.01f) |
1382 | xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX; | 1382 | xProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperX; |
1383 | 1383 | ||
1384 | if (this.taperY > 0.01f) | 1384 | if (this.taperY > 0.01f) |
1385 | yProfileScale *= 1.0f - percentOfPath * this.taperY; | 1385 | yProfileScale *= 1.0f - percentOfPath * this.taperY; |
1386 | else if (this.taperY < -0.01f) | 1386 | else if (this.taperY < -0.01f) |
1387 | yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY; | 1387 | yProfileScale *= 1.0f + (1.0f - percentOfPath) * this.taperY; |
1388 | 1388 | ||
1389 | newNode.xScale = xProfileScale; | 1389 | newNode.xScale = xProfileScale; |
1390 | newNode.yScale = yProfileScale; | 1390 | newNode.yScale = yProfileScale; |
1391 | 1391 | ||
1392 | float radiusScale = 1.0f; | 1392 | float radiusScale = 1.0f; |
1393 | if (this.radius > 0.001f) | 1393 | if (this.radius > 0.001f) |
1394 | radiusScale = 1.0f - this.radius * percentOfPath; | 1394 | radiusScale = 1.0f - this.radius * percentOfPath; |
1395 | else if (this.radius < 0.001f) | 1395 | else if (this.radius < 0.001f) |
1396 | radiusScale = 1.0f + this.radius * (1.0f - percentOfPath); | 1396 | radiusScale = 1.0f + this.radius * (1.0f - percentOfPath); |
1397 | 1397 | ||
1398 | float twist = twistBegin + twistTotal * percentOfPath; | 1398 | float twist = twistBegin + twistTotal * percentOfPath; |
1399 | 1399 | ||
1400 | float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles); | 1400 | float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles); |
1401 | xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor; | 1401 | xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor; |
1402 | 1402 | ||
1403 | float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale; | 1403 | float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale; |
1404 | 1404 | ||
1405 | float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale; | 1405 | float zOffset = (float)Math.Sin(angle + this.topShearY) * (0.5f - yPathScale) * radiusScale; |
1406 | 1406 | ||
1407 | newNode.position = new Coord(xOffset, yOffset, zOffset); | 1407 | newNode.position = new Coord(xOffset, yOffset, zOffset); |
1408 | 1408 | ||
1409 | // now orient the rotation of the profile layer relative to it's position on the path | 1409 | // now orient the rotation of the profile layer relative to it's position on the path |
1410 | // adding taperY to the angle used to generate the quat appears to approximate the viewer | 1410 | // adding taperY to the angle used to generate the quat appears to approximate the viewer |
1411 | 1411 | ||
1412 | newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY); | 1412 | newNode.rotation = new Quat(new Coord(1.0f, 0.0f, 0.0f), angle + this.topShearY); |
1413 | 1413 | ||
1414 | // next apply twist rotation to the profile layer | 1414 | // next apply twist rotation to the profile layer |
1415 | if (twistTotal != 0.0f || twistBegin != 0.0f) | 1415 | if (twistTotal != 0.0f || twistBegin != 0.0f) |
1416 | newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); | 1416 | newNode.rotation *= new Quat(new Coord(0.0f, 0.0f, 1.0f), twist); |
1417 | 1417 | ||
1418 | newNode.percentOfPath = percentOfPath; | 1418 | newNode.percentOfPath = percentOfPath; |
1419 | 1419 | ||
1420 | pathNodes.Add(newNode); | 1420 | pathNodes.Add(newNode); |
1421 | 1421 | ||
1422 | // calculate terms for next iteration | 1422 | // calculate terms for next iteration |
1423 | // calculate the angle for the next iteration of the loop | 1423 | // calculate the angle for the next iteration of the loop |
1424 | 1424 | ||
1425 | if (angle >= endAngle - 0.01) | 1425 | if (angle >= endAngle - 0.01) |
1426 | done = true; | 1426 | done = true; |
1427 | else | 1427 | else |
1428 | { | 1428 | { |
1429 | step += 1; | 1429 | step += 1; |
1430 | angle = stepSize * step; | 1430 | angle = stepSize * step; |
1431 | if (angle > endAngle) | 1431 | if (angle > endAngle) |
1432 | angle = endAngle; | 1432 | angle = endAngle; |
1433 | } | 1433 | } |
1434 | } | 1434 | } |
1435 | } | 1435 | } |
1436 | } | 1436 | } |
1437 | } | 1437 | } |
1438 | 1438 | ||
1439 | public class PrimMesh | 1439 | public class PrimMesh |
1440 | { | 1440 | { |
1441 | public string errorMessage = ""; | 1441 | public string errorMessage = ""; |
1442 | private const float twoPi = 2.0f * (float)Math.PI; | 1442 | private const float twoPi = 2.0f * (float)Math.PI; |
1443 | 1443 | ||
1444 | public List<Coord> coords; | 1444 | public List<Coord> coords; |
1445 | public List<Coord> normals; | 1445 | public List<Coord> normals; |
1446 | public List<Face> faces; | 1446 | public List<Face> faces; |
1447 | 1447 | ||
1448 | public List<ViewerFace> viewerFaces; | 1448 | public List<ViewerFace> viewerFaces; |
1449 | 1449 | ||
1450 | private int sides = 4; | 1450 | private int sides = 4; |
1451 | private int hollowSides = 4; | 1451 | private int hollowSides = 4; |
1452 | private float profileStart = 0.0f; | 1452 | private float profileStart = 0.0f; |
1453 | private float profileEnd = 1.0f; | 1453 | private float profileEnd = 1.0f; |
1454 | private float hollow = 0.0f; | 1454 | private float hollow = 0.0f; |
1455 | public int twistBegin = 0; | 1455 | public int twistBegin = 0; |
1456 | public int twistEnd = 0; | 1456 | public int twistEnd = 0; |
1457 | public float topShearX = 0.0f; | 1457 | public float topShearX = 0.0f; |
1458 | public float topShearY = 0.0f; | 1458 | public float topShearY = 0.0f; |
1459 | public float pathCutBegin = 0.0f; | 1459 | public float pathCutBegin = 0.0f; |
1460 | public float pathCutEnd = 1.0f; | 1460 | public float pathCutEnd = 1.0f; |
1461 | public float dimpleBegin = 0.0f; | 1461 | public float dimpleBegin = 0.0f; |
1462 | public float dimpleEnd = 1.0f; | 1462 | public float dimpleEnd = 1.0f; |
1463 | public float skew = 0.0f; | 1463 | public float skew = 0.0f; |
1464 | public float holeSizeX = 1.0f; // called pathScaleX in pbs | 1464 | public float holeSizeX = 1.0f; // called pathScaleX in pbs |
1465 | public float holeSizeY = 0.25f; | 1465 | public float holeSizeY = 0.25f; |
1466 | public float taperX = 0.0f; | 1466 | public float taperX = 0.0f; |
1467 | public float taperY = 0.0f; | 1467 | public float taperY = 0.0f; |
1468 | public float radius = 0.0f; | 1468 | public float radius = 0.0f; |
1469 | public float revolutions = 1.0f; | 1469 | public float revolutions = 1.0f; |
1470 | public int stepsPerRevolution = 24; | 1470 | public int stepsPerRevolution = 24; |
1471 | 1471 | ||
1472 | private int profileOuterFaceNumber = -1; | 1472 | private int profileOuterFaceNumber = -1; |
1473 | private int profileHollowFaceNumber = -1; | 1473 | private int profileHollowFaceNumber = -1; |
1474 | 1474 | ||
1475 | private bool hasProfileCut = false; | 1475 | private bool hasProfileCut = false; |
1476 | private bool hasHollow = false; | 1476 | private bool hasHollow = false; |
1477 | public bool calcVertexNormals = false; | 1477 | public bool calcVertexNormals = false; |
1478 | private bool normalsProcessed = false; | 1478 | private bool normalsProcessed = false; |
1479 | public bool viewerMode = false; | 1479 | public bool viewerMode = false; |
1480 | public bool sphereMode = false; | 1480 | public bool sphereMode = false; |
1481 | 1481 | ||
1482 | public int numPrimFaces = 0; | 1482 | public int numPrimFaces = 0; |
1483 | 1483 | ||
1484 | /// <summary> | 1484 | /// <summary> |
1485 | /// Human readable string representation of the parameters used to create a mesh. | 1485 | /// Human readable string representation of the parameters used to create a mesh. |
1486 | /// </summary> | 1486 | /// </summary> |
1487 | /// <returns></returns> | 1487 | /// <returns></returns> |
1488 | public string ParamsToDisplayString() | 1488 | public string ParamsToDisplayString() |
1489 | { | 1489 | { |
1490 | string s = ""; | 1490 | string s = ""; |
1491 | s += "sides..................: " + this.sides.ToString(); | 1491 | s += "sides..................: " + this.sides.ToString(); |
1492 | s += "\nhollowSides..........: " + this.hollowSides.ToString(); | 1492 | s += "\nhollowSides..........: " + this.hollowSides.ToString(); |
1493 | s += "\nprofileStart.........: " + this.profileStart.ToString(); | 1493 | s += "\nprofileStart.........: " + this.profileStart.ToString(); |
1494 | s += "\nprofileEnd...........: " + this.profileEnd.ToString(); | 1494 | s += "\nprofileEnd...........: " + this.profileEnd.ToString(); |
1495 | s += "\nhollow...............: " + this.hollow.ToString(); | 1495 | s += "\nhollow...............: " + this.hollow.ToString(); |
1496 | s += "\ntwistBegin...........: " + this.twistBegin.ToString(); | 1496 | s += "\ntwistBegin...........: " + this.twistBegin.ToString(); |
1497 | s += "\ntwistEnd.............: " + this.twistEnd.ToString(); | 1497 | s += "\ntwistEnd.............: " + this.twistEnd.ToString(); |
1498 | s += "\ntopShearX............: " + this.topShearX.ToString(); | 1498 | s += "\ntopShearX............: " + this.topShearX.ToString(); |
1499 | s += "\ntopShearY............: " + this.topShearY.ToString(); | 1499 | s += "\ntopShearY............: " + this.topShearY.ToString(); |
1500 | s += "\npathCutBegin.........: " + this.pathCutBegin.ToString(); | 1500 | s += "\npathCutBegin.........: " + this.pathCutBegin.ToString(); |
1501 | s += "\npathCutEnd...........: " + this.pathCutEnd.ToString(); | 1501 | s += "\npathCutEnd...........: " + this.pathCutEnd.ToString(); |
1502 | s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString(); | 1502 | s += "\ndimpleBegin..........: " + this.dimpleBegin.ToString(); |
1503 | s += "\ndimpleEnd............: " + this.dimpleEnd.ToString(); | 1503 | s += "\ndimpleEnd............: " + this.dimpleEnd.ToString(); |
1504 | s += "\nskew.................: " + this.skew.ToString(); | 1504 | s += "\nskew.................: " + this.skew.ToString(); |
1505 | s += "\nholeSizeX............: " + this.holeSizeX.ToString(); | 1505 | s += "\nholeSizeX............: " + this.holeSizeX.ToString(); |
1506 | s += "\nholeSizeY............: " + this.holeSizeY.ToString(); | 1506 | s += "\nholeSizeY............: " + this.holeSizeY.ToString(); |
1507 | s += "\ntaperX...............: " + this.taperX.ToString(); | 1507 | s += "\ntaperX...............: " + this.taperX.ToString(); |
1508 | s += "\ntaperY...............: " + this.taperY.ToString(); | 1508 | s += "\ntaperY...............: " + this.taperY.ToString(); |
1509 | s += "\nradius...............: " + this.radius.ToString(); | 1509 | s += "\nradius...............: " + this.radius.ToString(); |
1510 | s += "\nrevolutions..........: " + this.revolutions.ToString(); | 1510 | s += "\nrevolutions..........: " + this.revolutions.ToString(); |
1511 | s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); | 1511 | s += "\nstepsPerRevolution...: " + this.stepsPerRevolution.ToString(); |
1512 | s += "\nsphereMode...........: " + this.sphereMode.ToString(); | 1512 | s += "\nsphereMode...........: " + this.sphereMode.ToString(); |
1513 | s += "\nhasProfileCut........: " + this.hasProfileCut.ToString(); | 1513 | s += "\nhasProfileCut........: " + this.hasProfileCut.ToString(); |
1514 | s += "\nhasHollow............: " + this.hasHollow.ToString(); | 1514 | s += "\nhasHollow............: " + this.hasHollow.ToString(); |
1515 | s += "\nviewerMode...........: " + this.viewerMode.ToString(); | 1515 | s += "\nviewerMode...........: " + this.viewerMode.ToString(); |
1516 | 1516 | ||
1517 | return s; | 1517 | return s; |
1518 | } | 1518 | } |
1519 | 1519 | ||
1520 | public int ProfileOuterFaceNumber | 1520 | public int ProfileOuterFaceNumber |
1521 | { | 1521 | { |
1522 | get { return profileOuterFaceNumber; } | 1522 | get { return profileOuterFaceNumber; } |
1523 | } | 1523 | } |
1524 | 1524 | ||
1525 | public int ProfileHollowFaceNumber | 1525 | public int ProfileHollowFaceNumber |
1526 | { | 1526 | { |
1527 | get { return profileHollowFaceNumber; } | 1527 | get { return profileHollowFaceNumber; } |
1528 | } | 1528 | } |
1529 | 1529 | ||
1530 | public bool HasProfileCut | 1530 | public bool HasProfileCut |
1531 | { | 1531 | { |
1532 | get { return hasProfileCut; } | 1532 | get { return hasProfileCut; } |
1533 | } | 1533 | } |
1534 | 1534 | ||
1535 | public bool HasHollow | 1535 | public bool HasHollow |
1536 | { | 1536 | { |
1537 | get { return hasHollow; } | 1537 | get { return hasHollow; } |
1538 | } | 1538 | } |
1539 | 1539 | ||
1540 | 1540 | ||
1541 | /// <summary> | 1541 | /// <summary> |
1542 | /// Constructs a PrimMesh object and creates the profile for extrusion. | 1542 | /// Constructs a PrimMesh object and creates the profile for extrusion. |
1543 | /// </summary> | 1543 | /// </summary> |
1544 | /// <param name="sides"></param> | 1544 | /// <param name="sides"></param> |
1545 | /// <param name="profileStart"></param> | 1545 | /// <param name="profileStart"></param> |
1546 | /// <param name="profileEnd"></param> | 1546 | /// <param name="profileEnd"></param> |
1547 | /// <param name="hollow"></param> | 1547 | /// <param name="hollow"></param> |
1548 | /// <param name="hollowSides"></param> | 1548 | /// <param name="hollowSides"></param> |
1549 | public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides) | 1549 | public PrimMesh(int sides, float profileStart, float profileEnd, float hollow, int hollowSides) |
1550 | { | 1550 | { |
1551 | this.coords = new List<Coord>(); | 1551 | this.coords = new List<Coord>(); |
1552 | this.faces = new List<Face>(); | 1552 | this.faces = new List<Face>(); |
1553 | 1553 | ||
1554 | this.sides = sides; | 1554 | this.sides = sides; |
1555 | this.profileStart = profileStart; | 1555 | this.profileStart = profileStart; |
1556 | this.profileEnd = profileEnd; | 1556 | this.profileEnd = profileEnd; |
1557 | this.hollow = hollow; | 1557 | this.hollow = hollow; |
1558 | this.hollowSides = hollowSides; | 1558 | this.hollowSides = hollowSides; |
1559 | 1559 | ||
1560 | if (sides < 3) | 1560 | if (sides < 3) |
1561 | this.sides = 3; | 1561 | this.sides = 3; |
1562 | if (hollowSides < 3) | 1562 | if (hollowSides < 3) |
1563 | this.hollowSides = 3; | 1563 | this.hollowSides = 3; |
1564 | if (profileStart < 0.0f) | 1564 | if (profileStart < 0.0f) |
1565 | this.profileStart = 0.0f; | 1565 | this.profileStart = 0.0f; |
1566 | if (profileEnd > 1.0f) | 1566 | if (profileEnd > 1.0f) |
1567 | this.profileEnd = 1.0f; | 1567 | this.profileEnd = 1.0f; |
1568 | if (profileEnd < 0.02f) | 1568 | if (profileEnd < 0.02f) |
1569 | this.profileEnd = 0.02f; | 1569 | this.profileEnd = 0.02f; |
1570 | if (profileStart >= profileEnd) | 1570 | if (profileStart >= profileEnd) |
1571 | this.profileStart = profileEnd - 0.02f; | 1571 | this.profileStart = profileEnd - 0.02f; |
1572 | if (hollow > 0.99f) | 1572 | if (hollow > 0.99f) |
1573 | this.hollow = 0.99f; | 1573 | this.hollow = 0.99f; |
1574 | if (hollow < 0.0f) | 1574 | if (hollow < 0.0f) |
1575 | this.hollow = 0.0f; | 1575 | this.hollow = 0.0f; |
1576 | 1576 | ||
1577 | //if (sphereMode) | 1577 | //if (sphereMode) |
1578 | // this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f; | 1578 | // this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f; |
1579 | //else | 1579 | //else |
1580 | // //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f); | 1580 | // //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f); |
1581 | // this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; | 1581 | // this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; |
1582 | //this.hasHollow = (this.hollow > 0.001f); | 1582 | //this.hasHollow = (this.hollow > 0.001f); |
1583 | } | 1583 | } |
1584 | 1584 | ||
1585 | /// <summary> | 1585 | /// <summary> |
1586 | /// Extrudes a profile along a path. | 1586 | /// Extrudes a profile along a path. |
1587 | /// </summary> | 1587 | /// </summary> |
1588 | public void Extrude(PathType pathType) | 1588 | public void Extrude(PathType pathType) |
1589 | { | 1589 | { |
1590 | bool needEndFaces = false; | 1590 | bool needEndFaces = false; |
1591 | 1591 | ||
1592 | this.coords = new List<Coord>(); | 1592 | this.coords = new List<Coord>(); |
1593 | this.faces = new List<Face>(); | 1593 | this.faces = new List<Face>(); |
1594 | 1594 | ||
1595 | if (this.viewerMode) | 1595 | if (this.viewerMode) |
1596 | { | 1596 | { |
1597 | this.viewerFaces = new List<ViewerFace>(); | 1597 | this.viewerFaces = new List<ViewerFace>(); |
1598 | this.calcVertexNormals = true; | 1598 | this.calcVertexNormals = true; |
1599 | } | 1599 | } |
1600 | 1600 | ||
1601 | if (this.calcVertexNormals) | 1601 | if (this.calcVertexNormals) |
1602 | this.normals = new List<Coord>(); | 1602 | this.normals = new List<Coord>(); |
1603 | 1603 | ||
1604 | int steps = 1; | 1604 | int steps = 1; |
1605 | 1605 | ||
1606 | float length = this.pathCutEnd - this.pathCutBegin; | 1606 | float length = this.pathCutEnd - this.pathCutBegin; |
1607 | normalsProcessed = false; | 1607 | normalsProcessed = false; |
1608 | 1608 | ||
1609 | if (this.viewerMode && this.sides == 3) | 1609 | if (this.viewerMode && this.sides == 3) |
1610 | { | 1610 | { |
1611 | // prisms don't taper well so add some vertical resolution | 1611 | // prisms don't taper well so add some vertical resolution |
1612 | // other prims may benefit from this but just do prisms for now | 1612 | // other prims may benefit from this but just do prisms for now |
1613 | if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01) | 1613 | if (Math.Abs(this.taperX) > 0.01 || Math.Abs(this.taperY) > 0.01) |
1614 | steps = (int)(steps * 4.5 * length); | 1614 | steps = (int)(steps * 4.5 * length); |
1615 | } | 1615 | } |
1616 | 1616 | ||
1617 | if (sphereMode) | 1617 | if (sphereMode) |
1618 | this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f; | 1618 | this.hasProfileCut = this.profileEnd - this.profileStart < 0.4999f; |
1619 | else | 1619 | else |
1620 | //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f); | 1620 | //this.hasProfileCut = (this.profileStart > 0.0f || this.profileEnd < 1.0f); |
1621 | this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; | 1621 | this.hasProfileCut = this.profileEnd - this.profileStart < 0.9999f; |
1622 | this.hasHollow = (this.hollow > 0.001f); | 1622 | this.hasHollow = (this.hollow > 0.001f); |
1623 | 1623 | ||
1624 | float twistBegin = this.twistBegin / 360.0f * twoPi; | 1624 | float twistBegin = this.twistBegin / 360.0f * twoPi; |
1625 | float twistEnd = this.twistEnd / 360.0f * twoPi; | 1625 | float twistEnd = this.twistEnd / 360.0f * twoPi; |
1626 | float twistTotal = twistEnd - twistBegin; | 1626 | float twistTotal = twistEnd - twistBegin; |
1627 | float twistTotalAbs = Math.Abs(twistTotal); | 1627 | float twistTotalAbs = Math.Abs(twistTotal); |
1628 | if (twistTotalAbs > 0.01f) | 1628 | if (twistTotalAbs > 0.01f) |
1629 | steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number | 1629 | steps += (int)(twistTotalAbs * 3.66); // dahlia's magic number |
1630 | 1630 | ||
1631 | float hollow = this.hollow; | 1631 | float hollow = this.hollow; |
1632 | 1632 | ||
1633 | // sanity checks | 1633 | // sanity checks |
1634 | float initialProfileRot = 0.0f; | 1634 | float initialProfileRot = 0.0f; |
1635 | if (pathType == PathType.Circular) | 1635 | if (pathType == PathType.Circular) |
1636 | { | 1636 | { |
1637 | if (this.sides == 3) | 1637 | if (this.sides == 3) |
1638 | { | 1638 | { |
1639 | initialProfileRot = (float)Math.PI; | 1639 | initialProfileRot = (float)Math.PI; |
1640 | if (this.hollowSides == 4) | 1640 | if (this.hollowSides == 4) |
1641 | { | 1641 | { |
1642 | if (hollow > 0.7f) | 1642 | if (hollow > 0.7f) |
1643 | hollow = 0.7f; | 1643 | hollow = 0.7f; |
1644 | hollow *= 0.707f; | 1644 | hollow *= 0.707f; |
1645 | } | 1645 | } |
1646 | else hollow *= 0.5f; | 1646 | else hollow *= 0.5f; |
1647 | } | 1647 | } |
1648 | else if (this.sides == 4) | 1648 | else if (this.sides == 4) |
1649 | { | 1649 | { |
1650 | initialProfileRot = 0.25f * (float)Math.PI; | 1650 | initialProfileRot = 0.25f * (float)Math.PI; |
1651 | if (this.hollowSides != 4) | 1651 | if (this.hollowSides != 4) |
1652 | hollow *= 0.707f; | 1652 | hollow *= 0.707f; |
1653 | } | 1653 | } |
1654 | else if (this.sides > 4) | 1654 | else if (this.sides > 4) |
1655 | { | 1655 | { |
1656 | initialProfileRot = (float)Math.PI; | 1656 | initialProfileRot = (float)Math.PI; |
1657 | if (this.hollowSides == 4) | 1657 | if (this.hollowSides == 4) |
1658 | { | 1658 | { |
1659 | if (hollow > 0.7f) | 1659 | if (hollow > 0.7f) |
1660 | hollow = 0.7f; | 1660 | hollow = 0.7f; |
1661 | hollow /= 0.7f; | 1661 | hollow /= 0.7f; |
1662 | } | 1662 | } |
1663 | } | 1663 | } |
1664 | } | 1664 | } |
1665 | else | 1665 | else |
1666 | { | 1666 | { |
1667 | if (this.sides == 3) | 1667 | if (this.sides == 3) |
1668 | { | 1668 | { |
1669 | if (this.hollowSides == 4) | 1669 | if (this.hollowSides == 4) |
1670 | { | 1670 | { |
1671 | if (hollow > 0.7f) | 1671 | if (hollow > 0.7f) |
1672 | hollow = 0.7f; | 1672 | hollow = 0.7f; |
1673 | hollow *= 0.707f; | 1673 | hollow *= 0.707f; |
1674 | } | 1674 | } |
1675 | else hollow *= 0.5f; | 1675 | else hollow *= 0.5f; |
1676 | } | 1676 | } |
1677 | else if (this.sides == 4) | 1677 | else if (this.sides == 4) |
1678 | { | 1678 | { |
1679 | initialProfileRot = 1.25f * (float)Math.PI; | 1679 | initialProfileRot = 1.25f * (float)Math.PI; |
1680 | if (this.hollowSides != 4) | 1680 | if (this.hollowSides != 4) |
1681 | hollow *= 0.707f; | 1681 | hollow *= 0.707f; |
1682 | } | 1682 | } |
1683 | else if (this.sides == 24 && this.hollowSides == 4) | 1683 | else if (this.sides == 24 && this.hollowSides == 4) |
1684 | hollow *= 1.414f; | 1684 | hollow *= 1.414f; |
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals); | 1687 | Profile profile = new Profile(this.sides, this.profileStart, this.profileEnd, hollow, this.hollowSides, true, calcVertexNormals); |
1688 | this.errorMessage = profile.errorMessage; | 1688 | this.errorMessage = profile.errorMessage; |
1689 | 1689 | ||
1690 | this.numPrimFaces = profile.numPrimFaces; | 1690 | this.numPrimFaces = profile.numPrimFaces; |
1691 | 1691 | ||
1692 | //profileOuterFaceNumber = profile.faceNumbers[0]; | 1692 | //profileOuterFaceNumber = profile.faceNumbers[0]; |
1693 | //if (!needEndFaces) | 1693 | //if (!needEndFaces) |
1694 | // profileOuterFaceNumber--; | 1694 | // profileOuterFaceNumber--; |
1695 | //profileOuterFaceNumber = needEndFaces ? 1 : 0; | 1695 | //profileOuterFaceNumber = needEndFaces ? 1 : 0; |
1696 | 1696 | ||
1697 | 1697 | ||
1698 | //if (hasHollow) | 1698 | //if (hasHollow) |
1699 | //{ | 1699 | //{ |
1700 | // if (needEndFaces) | 1700 | // if (needEndFaces) |
1701 | // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts + 1]; | 1701 | // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts + 1]; |
1702 | // else | 1702 | // else |
1703 | // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts] - 1; | 1703 | // profileHollowFaceNumber = profile.faceNumbers[profile.numOuterVerts] - 1; |
1704 | //} | 1704 | //} |
1705 | 1705 | ||
1706 | 1706 | ||
1707 | profileOuterFaceNumber = profile.outerFaceNumber; | 1707 | profileOuterFaceNumber = profile.outerFaceNumber; |
1708 | if (!needEndFaces) | 1708 | if (!needEndFaces) |
1709 | profileOuterFaceNumber--; | 1709 | profileOuterFaceNumber--; |
1710 | 1710 | ||
1711 | if (hasHollow) | 1711 | if (hasHollow) |
1712 | { | 1712 | { |
1713 | profileHollowFaceNumber = profile.hollowFaceNumber; | 1713 | profileHollowFaceNumber = profile.hollowFaceNumber; |
1714 | if (!needEndFaces) | 1714 | if (!needEndFaces) |
1715 | profileHollowFaceNumber--; | 1715 | profileHollowFaceNumber--; |
1716 | } | 1716 | } |
1717 | 1717 | ||
1718 | int cut1Vert = -1; | 1718 | int cut1Vert = -1; |
1719 | int cut2Vert = -1; | 1719 | int cut2Vert = -1; |
1720 | if (hasProfileCut) | 1720 | if (hasProfileCut) |
1721 | { | 1721 | { |
1722 | cut1Vert = hasHollow ? profile.coords.Count - 1 : 0; | 1722 | cut1Vert = hasHollow ? profile.coords.Count - 1 : 0; |
1723 | cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts; | 1723 | cut2Vert = hasHollow ? profile.numOuterVerts - 1 : profile.numOuterVerts; |
1724 | } | 1724 | } |
1725 | 1725 | ||
1726 | if (initialProfileRot != 0.0f) | 1726 | if (initialProfileRot != 0.0f) |
1727 | { | 1727 | { |
1728 | profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); | 1728 | profile.AddRot(new Quat(new Coord(0.0f, 0.0f, 1.0f), initialProfileRot)); |
1729 | if (viewerMode) | 1729 | if (viewerMode) |
1730 | profile.MakeFaceUVs(); | 1730 | profile.MakeFaceUVs(); |
1731 | } | 1731 | } |
1732 | 1732 | ||
1733 | Coord lastCutNormal1 = new Coord(); | 1733 | Coord lastCutNormal1 = new Coord(); |
1734 | Coord lastCutNormal2 = new Coord(); | 1734 | Coord lastCutNormal2 = new Coord(); |
1735 | float lastV = 1.0f; | 1735 | float lastV = 1.0f; |
1736 | 1736 | ||
1737 | Path path = new Path(); | 1737 | Path path = new Path(); |
1738 | path.twistBegin = twistBegin; | 1738 | path.twistBegin = twistBegin; |
1739 | path.twistEnd = twistEnd; | 1739 | path.twistEnd = twistEnd; |
1740 | path.topShearX = topShearX; | 1740 | path.topShearX = topShearX; |
1741 | path.topShearY = topShearY; | 1741 | path.topShearY = topShearY; |
1742 | path.pathCutBegin = pathCutBegin; | 1742 | path.pathCutBegin = pathCutBegin; |
1743 | path.pathCutEnd = pathCutEnd; | 1743 | path.pathCutEnd = pathCutEnd; |
1744 | path.dimpleBegin = dimpleBegin; | 1744 | path.dimpleBegin = dimpleBegin; |
1745 | path.dimpleEnd = dimpleEnd; | 1745 | path.dimpleEnd = dimpleEnd; |
1746 | path.skew = skew; | 1746 | path.skew = skew; |
1747 | path.holeSizeX = holeSizeX; | 1747 | path.holeSizeX = holeSizeX; |
1748 | path.holeSizeY = holeSizeY; | 1748 | path.holeSizeY = holeSizeY; |
1749 | path.taperX = taperX; | 1749 | path.taperX = taperX; |
1750 | path.taperY = taperY; | 1750 | path.taperY = taperY; |
1751 | path.radius = radius; | 1751 | path.radius = radius; |
1752 | path.revolutions = revolutions; | 1752 | path.revolutions = revolutions; |
1753 | path.stepsPerRevolution = stepsPerRevolution; | 1753 | path.stepsPerRevolution = stepsPerRevolution; |
1754 | 1754 | ||
1755 | path.Create(pathType, steps); | 1755 | path.Create(pathType, steps); |
1756 | 1756 | ||
1757 | 1757 | ||
1758 | if (pathType == PathType.Circular) | 1758 | if (pathType == PathType.Circular) |
1759 | { | 1759 | { |
1760 | needEndFaces = false; | 1760 | needEndFaces = false; |
1761 | if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f) | 1761 | if (this.pathCutBegin != 0.0f || this.pathCutEnd != 1.0f) |
1762 | needEndFaces = true; | 1762 | needEndFaces = true; |
1763 | else if (this.taperX != 0.0f || this.taperY != 0.0f) | 1763 | else if (this.taperX != 0.0f || this.taperY != 0.0f) |
1764 | needEndFaces = true; | 1764 | needEndFaces = true; |
1765 | else if (this.skew != 0.0f) | 1765 | else if (this.skew != 0.0f) |
1766 | needEndFaces = true; | 1766 | needEndFaces = true; |
1767 | else if (twistTotal != 0.0f) | 1767 | else if (twistTotal != 0.0f) |
1768 | needEndFaces = true; | 1768 | needEndFaces = true; |
1769 | else if (this.radius != 0.0f) | 1769 | else if (this.radius != 0.0f) |
1770 | needEndFaces = true; | 1770 | needEndFaces = true; |
1771 | } | 1771 | } |
1772 | else needEndFaces = true; | 1772 | else needEndFaces = true; |
1773 | 1773 | ||
1774 | for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) | 1774 | for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) |
1775 | { | 1775 | { |
1776 | PathNode node = path.pathNodes[nodeIndex]; | 1776 | PathNode node = path.pathNodes[nodeIndex]; |
1777 | Profile newLayer = profile.Copy(); | 1777 | Profile newLayer = profile.Copy(); |
1778 | newLayer.Scale(node.xScale, node.yScale); | 1778 | newLayer.Scale(node.xScale, node.yScale); |
1779 | 1779 | ||
1780 | newLayer.AddRot(node.rotation); | 1780 | newLayer.AddRot(node.rotation); |
1781 | newLayer.AddPos(node.position); | 1781 | newLayer.AddPos(node.position); |
1782 | 1782 | ||
1783 | if (needEndFaces && nodeIndex == 0) | 1783 | if (needEndFaces && nodeIndex == 0) |
1784 | { | 1784 | { |
1785 | newLayer.FlipNormals(); | 1785 | newLayer.FlipNormals(); |
1786 | 1786 | ||
1787 | // add the top faces to the viewerFaces list here | 1787 | // add the top faces to the viewerFaces list here |
1788 | if (this.viewerMode) | 1788 | if (this.viewerMode) |
1789 | { | 1789 | { |
1790 | Coord faceNormal = newLayer.faceNormal; | 1790 | Coord faceNormal = newLayer.faceNormal; |
1791 | ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber); | 1791 | ViewerFace newViewerFace = new ViewerFace(profile.bottomFaceNumber); |
1792 | int numFaces = newLayer.faces.Count; | 1792 | int numFaces = newLayer.faces.Count; |
1793 | List<Face> faces = newLayer.faces; | 1793 | List<Face> faces = newLayer.faces; |
1794 | 1794 | ||
1795 | for (int i = 0; i < numFaces; i++) | 1795 | for (int i = 0; i < numFaces; i++) |
1796 | { | 1796 | { |
1797 | Face face = faces[i]; | 1797 | Face face = faces[i]; |
1798 | newViewerFace.v1 = newLayer.coords[face.v1]; | 1798 | newViewerFace.v1 = newLayer.coords[face.v1]; |
1799 | newViewerFace.v2 = newLayer.coords[face.v2]; | 1799 | newViewerFace.v2 = newLayer.coords[face.v2]; |
1800 | newViewerFace.v3 = newLayer.coords[face.v3]; | 1800 | newViewerFace.v3 = newLayer.coords[face.v3]; |
1801 | 1801 | ||
1802 | newViewerFace.coordIndex1 = face.v1; | 1802 | newViewerFace.coordIndex1 = face.v1; |
1803 | newViewerFace.coordIndex2 = face.v2; | 1803 | newViewerFace.coordIndex2 = face.v2; |
1804 | newViewerFace.coordIndex3 = face.v3; | 1804 | newViewerFace.coordIndex3 = face.v3; |
1805 | 1805 | ||
1806 | newViewerFace.n1 = faceNormal; | 1806 | newViewerFace.n1 = faceNormal; |
1807 | newViewerFace.n2 = faceNormal; | 1807 | newViewerFace.n2 = faceNormal; |
1808 | newViewerFace.n3 = faceNormal; | 1808 | newViewerFace.n3 = faceNormal; |
1809 | 1809 | ||
1810 | newViewerFace.uv1 = newLayer.faceUVs[face.v1]; | 1810 | newViewerFace.uv1 = newLayer.faceUVs[face.v1]; |
1811 | newViewerFace.uv2 = newLayer.faceUVs[face.v2]; | 1811 | newViewerFace.uv2 = newLayer.faceUVs[face.v2]; |
1812 | newViewerFace.uv3 = newLayer.faceUVs[face.v3]; | 1812 | newViewerFace.uv3 = newLayer.faceUVs[face.v3]; |
1813 | 1813 | ||
1814 | this.viewerFaces.Add(newViewerFace); | 1814 | this.viewerFaces.Add(newViewerFace); |
1815 | } | 1815 | } |
1816 | } | 1816 | } |
1817 | } // if (nodeIndex == 0) | 1817 | } // if (nodeIndex == 0) |
1818 | 1818 | ||
1819 | // append this layer | 1819 | // append this layer |
1820 | 1820 | ||
1821 | int coordsLen = this.coords.Count; | 1821 | int coordsLen = this.coords.Count; |
1822 | newLayer.AddValue2FaceVertexIndices(coordsLen); | 1822 | newLayer.AddValue2FaceVertexIndices(coordsLen); |
1823 | 1823 | ||
1824 | this.coords.AddRange(newLayer.coords); | 1824 | this.coords.AddRange(newLayer.coords); |
1825 | 1825 | ||
1826 | if (this.calcVertexNormals) | 1826 | if (this.calcVertexNormals) |
1827 | { | 1827 | { |
1828 | newLayer.AddValue2FaceNormalIndices(this.normals.Count); | 1828 | newLayer.AddValue2FaceNormalIndices(this.normals.Count); |
1829 | this.normals.AddRange(newLayer.vertexNormals); | 1829 | this.normals.AddRange(newLayer.vertexNormals); |
1830 | } | 1830 | } |
1831 | 1831 | ||
1832 | if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f) | 1832 | if (node.percentOfPath < this.pathCutBegin + 0.01f || node.percentOfPath > this.pathCutEnd - 0.01f) |
1833 | this.faces.AddRange(newLayer.faces); | 1833 | this.faces.AddRange(newLayer.faces); |
1834 | 1834 | ||
1835 | // fill faces between layers | 1835 | // fill faces between layers |
1836 | 1836 | ||
1837 | int numVerts = newLayer.coords.Count; | 1837 | int numVerts = newLayer.coords.Count; |
1838 | Face newFace = new Face(); | 1838 | Face newFace = new Face(); |
1839 | 1839 | ||
1840 | if (nodeIndex > 0) | 1840 | if (nodeIndex > 0) |
1841 | { | 1841 | { |
1842 | int startVert = coordsLen + 1; | 1842 | int startVert = coordsLen + 1; |
1843 | int endVert = this.coords.Count; | 1843 | int endVert = this.coords.Count; |
1844 | 1844 | ||
1845 | if (sides < 5 || this.hasProfileCut || this.hasHollow) | 1845 | if (sides < 5 || this.hasProfileCut || this.hasHollow) |
1846 | startVert--; | 1846 | startVert--; |
1847 | 1847 | ||
1848 | for (int i = startVert; i < endVert; i++) | 1848 | for (int i = startVert; i < endVert; i++) |
1849 | { | 1849 | { |
1850 | int iNext = i + 1; | 1850 | int iNext = i + 1; |
1851 | if (i == endVert - 1) | 1851 | if (i == endVert - 1) |
1852 | iNext = startVert; | 1852 | iNext = startVert; |
1853 | 1853 | ||
1854 | int whichVert = i - startVert; | 1854 | int whichVert = i - startVert; |
1855 | 1855 | ||
1856 | newFace.v1 = i; | 1856 | newFace.v1 = i; |
1857 | newFace.v2 = i - numVerts; | 1857 | newFace.v2 = i - numVerts; |
1858 | newFace.v3 = iNext - numVerts; | 1858 | newFace.v3 = iNext - numVerts; |
1859 | this.faces.Add(newFace); | 1859 | this.faces.Add(newFace); |
1860 | 1860 | ||
1861 | newFace.v2 = iNext - numVerts; | 1861 | newFace.v2 = iNext - numVerts; |
1862 | newFace.v3 = iNext; | 1862 | newFace.v3 = iNext; |
1863 | this.faces.Add(newFace); | 1863 | this.faces.Add(newFace); |
1864 | 1864 | ||
1865 | if (this.viewerMode) | 1865 | if (this.viewerMode) |
1866 | { | 1866 | { |
1867 | // add the side faces to the list of viewerFaces here | 1867 | // add the side faces to the list of viewerFaces here |
1868 | 1868 | ||
1869 | int primFaceNum = profile.faceNumbers[whichVert]; | 1869 | int primFaceNum = profile.faceNumbers[whichVert]; |
1870 | if (!needEndFaces) | 1870 | if (!needEndFaces) |
1871 | primFaceNum -= 1; | 1871 | primFaceNum -= 1; |
1872 | 1872 | ||
1873 | ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); | 1873 | ViewerFace newViewerFace1 = new ViewerFace(primFaceNum); |
1874 | ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); | 1874 | ViewerFace newViewerFace2 = new ViewerFace(primFaceNum); |
1875 | 1875 | ||
1876 | float u1 = newLayer.us[whichVert]; | 1876 | float u1 = newLayer.us[whichVert]; |
1877 | float u2 = 1.0f; | 1877 | float u2 = 1.0f; |
1878 | if (whichVert < newLayer.us.Count - 1) | 1878 | if (whichVert < newLayer.us.Count - 1) |
1879 | u2 = newLayer.us[whichVert + 1]; | 1879 | u2 = newLayer.us[whichVert + 1]; |
1880 | 1880 | ||
1881 | if (whichVert == cut1Vert || whichVert == cut2Vert) | 1881 | if (whichVert == cut1Vert || whichVert == cut2Vert) |
1882 | { | 1882 | { |
1883 | u1 = 0.0f; | 1883 | u1 = 0.0f; |
1884 | u2 = 1.0f; | 1884 | u2 = 1.0f; |
1885 | } | 1885 | } |
1886 | else if (sides < 5) | 1886 | else if (sides < 5) |
1887 | { | 1887 | { |
1888 | if (whichVert < profile.numOuterVerts) | 1888 | if (whichVert < profile.numOuterVerts) |
1889 | { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled | 1889 | { // boxes and prisms have one texture face per side of the prim, so the U values have to be scaled |
1890 | // to reflect the entire texture width | 1890 | // to reflect the entire texture width |
1891 | u1 *= sides; | 1891 | u1 *= sides; |
1892 | u2 *= sides; | 1892 | u2 *= sides; |
1893 | u2 -= (int)u1; | 1893 | u2 -= (int)u1; |
1894 | u1 -= (int)u1; | 1894 | u1 -= (int)u1; |
1895 | if (u2 < 0.1f) | 1895 | if (u2 < 0.1f) |
1896 | u2 = 1.0f; | 1896 | u2 = 1.0f; |
1897 | //this.profileOuterFaceNumber = primFaceNum; | 1897 | //this.profileOuterFaceNumber = primFaceNum; |
1898 | } | 1898 | } |
1899 | else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) | 1899 | else if (whichVert > profile.coords.Count - profile.numHollowVerts - 1) |
1900 | { | 1900 | { |
1901 | u1 *= 2.0f; | 1901 | u1 *= 2.0f; |
1902 | u2 *= 2.0f; | 1902 | u2 *= 2.0f; |
1903 | //this.profileHollowFaceNumber = primFaceNum; | 1903 | //this.profileHollowFaceNumber = primFaceNum; |
1904 | } | 1904 | } |
1905 | } | 1905 | } |
1906 | 1906 | ||
1907 | newViewerFace1.uv1.U = u1; | 1907 | newViewerFace1.uv1.U = u1; |
1908 | newViewerFace1.uv2.U = u1; | 1908 | newViewerFace1.uv2.U = u1; |
1909 | newViewerFace1.uv3.U = u2; | 1909 | newViewerFace1.uv3.U = u2; |
1910 | 1910 | ||
1911 | newViewerFace1.uv1.V = 1.0f - node.percentOfPath; | 1911 | newViewerFace1.uv1.V = 1.0f - node.percentOfPath; |
1912 | newViewerFace1.uv2.V = lastV; | 1912 | newViewerFace1.uv2.V = lastV; |
1913 | newViewerFace1.uv3.V = lastV; | 1913 | newViewerFace1.uv3.V = lastV; |
1914 | 1914 | ||
1915 | newViewerFace2.uv1.U = u1; | 1915 | newViewerFace2.uv1.U = u1; |
1916 | newViewerFace2.uv2.U = u2; | 1916 | newViewerFace2.uv2.U = u2; |
1917 | newViewerFace2.uv3.U = u2; | 1917 | newViewerFace2.uv3.U = u2; |
1918 | 1918 | ||
1919 | newViewerFace2.uv1.V = 1.0f - node.percentOfPath; | 1919 | newViewerFace2.uv1.V = 1.0f - node.percentOfPath; |
1920 | newViewerFace2.uv2.V = lastV; | 1920 | newViewerFace2.uv2.V = lastV; |
1921 | newViewerFace2.uv3.V = 1.0f - node.percentOfPath; | 1921 | newViewerFace2.uv3.V = 1.0f - node.percentOfPath; |
1922 | 1922 | ||
1923 | newViewerFace1.v1 = this.coords[i]; | 1923 | newViewerFace1.v1 = this.coords[i]; |
1924 | newViewerFace1.v2 = this.coords[i - numVerts]; | 1924 | newViewerFace1.v2 = this.coords[i - numVerts]; |
1925 | newViewerFace1.v3 = this.coords[iNext - numVerts]; | 1925 | newViewerFace1.v3 = this.coords[iNext - numVerts]; |
1926 | 1926 | ||
1927 | newViewerFace2.v1 = this.coords[i]; | 1927 | newViewerFace2.v1 = this.coords[i]; |
1928 | newViewerFace2.v2 = this.coords[iNext - numVerts]; | 1928 | newViewerFace2.v2 = this.coords[iNext - numVerts]; |
1929 | newViewerFace2.v3 = this.coords[iNext]; | 1929 | newViewerFace2.v3 = this.coords[iNext]; |
1930 | 1930 | ||
1931 | newViewerFace1.coordIndex1 = i; | 1931 | newViewerFace1.coordIndex1 = i; |
1932 | newViewerFace1.coordIndex2 = i - numVerts; | 1932 | newViewerFace1.coordIndex2 = i - numVerts; |
1933 | newViewerFace1.coordIndex3 = iNext - numVerts; | 1933 | newViewerFace1.coordIndex3 = iNext - numVerts; |
1934 | 1934 | ||
1935 | newViewerFace2.coordIndex1 = i; | 1935 | newViewerFace2.coordIndex1 = i; |
1936 | newViewerFace2.coordIndex2 = iNext - numVerts; | 1936 | newViewerFace2.coordIndex2 = iNext - numVerts; |
1937 | newViewerFace2.coordIndex3 = iNext; | 1937 | newViewerFace2.coordIndex3 = iNext; |
1938 | 1938 | ||
1939 | // profile cut faces | 1939 | // profile cut faces |
1940 | if (whichVert == cut1Vert) | 1940 | if (whichVert == cut1Vert) |
1941 | { | 1941 | { |
1942 | newViewerFace1.n1 = newLayer.cutNormal1; | 1942 | newViewerFace1.n1 = newLayer.cutNormal1; |
1943 | newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; | 1943 | newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal1; |
1944 | 1944 | ||
1945 | newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1; | 1945 | newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal1; |
1946 | newViewerFace2.n2 = lastCutNormal1; | 1946 | newViewerFace2.n2 = lastCutNormal1; |
1947 | } | 1947 | } |
1948 | else if (whichVert == cut2Vert) | 1948 | else if (whichVert == cut2Vert) |
1949 | { | 1949 | { |
1950 | newViewerFace1.n1 = newLayer.cutNormal2; | 1950 | newViewerFace1.n1 = newLayer.cutNormal2; |
1951 | newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2; | 1951 | newViewerFace1.n2 = newViewerFace1.n3 = lastCutNormal2; |
1952 | 1952 | ||
1953 | newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2; | 1953 | newViewerFace2.n1 = newViewerFace2.n3 = newLayer.cutNormal2; |
1954 | newViewerFace2.n2 = lastCutNormal2; | 1954 | newViewerFace2.n2 = lastCutNormal2; |
1955 | } | 1955 | } |
1956 | 1956 | ||
1957 | else // outer and hollow faces | 1957 | else // outer and hollow faces |
1958 | { | 1958 | { |
1959 | if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)) | 1959 | if ((sides < 5 && whichVert < newLayer.numOuterVerts) || (hollowSides < 5 && whichVert >= newLayer.numOuterVerts)) |
1960 | { // looks terrible when path is twisted... need vertex normals here | 1960 | { // looks terrible when path is twisted... need vertex normals here |
1961 | newViewerFace1.CalcSurfaceNormal(); | 1961 | newViewerFace1.CalcSurfaceNormal(); |
1962 | newViewerFace2.CalcSurfaceNormal(); | 1962 | newViewerFace2.CalcSurfaceNormal(); |
1963 | } | 1963 | } |
1964 | else | 1964 | else |
1965 | { | 1965 | { |
1966 | newViewerFace1.n1 = this.normals[i]; | 1966 | newViewerFace1.n1 = this.normals[i]; |
1967 | newViewerFace1.n2 = this.normals[i - numVerts]; | 1967 | newViewerFace1.n2 = this.normals[i - numVerts]; |
1968 | newViewerFace1.n3 = this.normals[iNext - numVerts]; | 1968 | newViewerFace1.n3 = this.normals[iNext - numVerts]; |
1969 | 1969 | ||
1970 | newViewerFace2.n1 = this.normals[i]; | 1970 | newViewerFace2.n1 = this.normals[i]; |
1971 | newViewerFace2.n2 = this.normals[iNext - numVerts]; | 1971 | newViewerFace2.n2 = this.normals[iNext - numVerts]; |
1972 | newViewerFace2.n3 = this.normals[iNext]; | 1972 | newViewerFace2.n3 = this.normals[iNext]; |
1973 | } | 1973 | } |
1974 | } | 1974 | } |
1975 | 1975 | ||
1976 | this.viewerFaces.Add(newViewerFace1); | 1976 | this.viewerFaces.Add(newViewerFace1); |
1977 | this.viewerFaces.Add(newViewerFace2); | 1977 | this.viewerFaces.Add(newViewerFace2); |
1978 | 1978 | ||
1979 | } | 1979 | } |
1980 | } | 1980 | } |
1981 | } | 1981 | } |
1982 | 1982 | ||
1983 | lastCutNormal1 = newLayer.cutNormal1; | 1983 | lastCutNormal1 = newLayer.cutNormal1; |
1984 | lastCutNormal2 = newLayer.cutNormal2; | 1984 | lastCutNormal2 = newLayer.cutNormal2; |
1985 | lastV = 1.0f - node.percentOfPath; | 1985 | lastV = 1.0f - node.percentOfPath; |
1986 | 1986 | ||
1987 | if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) | 1987 | if (needEndFaces && nodeIndex == path.pathNodes.Count - 1 && viewerMode) |
1988 | { | 1988 | { |
1989 | // add the top faces to the viewerFaces list here | 1989 | // add the top faces to the viewerFaces list here |
1990 | Coord faceNormal = newLayer.faceNormal; | 1990 | Coord faceNormal = newLayer.faceNormal; |
1991 | ViewerFace newViewerFace = new ViewerFace(); | 1991 | ViewerFace newViewerFace = new ViewerFace(); |
1992 | newViewerFace.primFaceNumber = 0; | 1992 | newViewerFace.primFaceNumber = 0; |
1993 | int numFaces = newLayer.faces.Count; | 1993 | int numFaces = newLayer.faces.Count; |
1994 | List<Face> faces = newLayer.faces; | 1994 | List<Face> faces = newLayer.faces; |
1995 | 1995 | ||
1996 | for (int i = 0; i < numFaces; i++) | 1996 | for (int i = 0; i < numFaces; i++) |
1997 | { | 1997 | { |
1998 | Face face = faces[i]; | 1998 | Face face = faces[i]; |
1999 | newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen]; | 1999 | newViewerFace.v1 = newLayer.coords[face.v1 - coordsLen]; |
2000 | newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; | 2000 | newViewerFace.v2 = newLayer.coords[face.v2 - coordsLen]; |
2001 | newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; | 2001 | newViewerFace.v3 = newLayer.coords[face.v3 - coordsLen]; |
2002 | 2002 | ||
2003 | newViewerFace.coordIndex1 = face.v1 - coordsLen; | 2003 | newViewerFace.coordIndex1 = face.v1 - coordsLen; |
2004 | newViewerFace.coordIndex2 = face.v2 - coordsLen; | 2004 | newViewerFace.coordIndex2 = face.v2 - coordsLen; |
2005 | newViewerFace.coordIndex3 = face.v3 - coordsLen; | 2005 | newViewerFace.coordIndex3 = face.v3 - coordsLen; |
2006 | 2006 | ||
2007 | newViewerFace.n1 = faceNormal; | 2007 | newViewerFace.n1 = faceNormal; |
2008 | newViewerFace.n2 = faceNormal; | 2008 | newViewerFace.n2 = faceNormal; |
2009 | newViewerFace.n3 = faceNormal; | 2009 | newViewerFace.n3 = faceNormal; |
2010 | 2010 | ||
2011 | newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen]; | 2011 | newViewerFace.uv1 = newLayer.faceUVs[face.v1 - coordsLen]; |
2012 | newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; | 2012 | newViewerFace.uv2 = newLayer.faceUVs[face.v2 - coordsLen]; |
2013 | newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; | 2013 | newViewerFace.uv3 = newLayer.faceUVs[face.v3 - coordsLen]; |
2014 | 2014 | ||
2015 | this.viewerFaces.Add(newViewerFace); | 2015 | this.viewerFaces.Add(newViewerFace); |
2016 | } | 2016 | } |
2017 | } | 2017 | } |
2018 | 2018 | ||
2019 | 2019 | ||
2020 | } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) | 2020 | } // for (int nodeIndex = 0; nodeIndex < path.pathNodes.Count; nodeIndex++) |
2021 | 2021 | ||
2022 | } | 2022 | } |
2023 | 2023 | ||
2024 | 2024 | ||
2025 | /// <summary> | 2025 | /// <summary> |
2026 | /// DEPRICATED - use Extrude(PathType.Linear) instead | 2026 | /// DEPRICATED - use Extrude(PathType.Linear) instead |
2027 | /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. | 2027 | /// Extrudes a profile along a straight line path. Used for prim types box, cylinder, and prism. |
2028 | /// </summary> | 2028 | /// </summary> |
2029 | /// | 2029 | /// |
2030 | public void ExtrudeLinear() | 2030 | public void ExtrudeLinear() |
2031 | { | 2031 | { |
2032 | this.Extrude(PathType.Linear); | 2032 | this.Extrude(PathType.Linear); |
2033 | } | 2033 | } |
2034 | 2034 | ||
2035 | 2035 | ||
2036 | /// <summary> | 2036 | /// <summary> |
2037 | /// DEPRICATED - use Extrude(PathType.Circular) instead | 2037 | /// DEPRICATED - use Extrude(PathType.Circular) instead |
2038 | /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. | 2038 | /// Extrude a profile into a circular path prim mesh. Used for prim types torus, tube, and ring. |
2039 | /// </summary> | 2039 | /// </summary> |
2040 | /// | 2040 | /// |
2041 | public void ExtrudeCircular() | 2041 | public void ExtrudeCircular() |
2042 | { | 2042 | { |
2043 | this.Extrude(PathType.Circular); | 2043 | this.Extrude(PathType.Circular); |
2044 | } | 2044 | } |
2045 | 2045 | ||
2046 | 2046 | ||
2047 | private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3) | 2047 | private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3) |
2048 | { | 2048 | { |
2049 | Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); | 2049 | Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z); |
2050 | Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); | 2050 | Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z); |
2051 | 2051 | ||
2052 | Coord normal = Coord.Cross(edge1, edge2); | 2052 | Coord normal = Coord.Cross(edge1, edge2); |
2053 | 2053 | ||
2054 | normal.Normalize(); | 2054 | normal.Normalize(); |
2055 | 2055 | ||
2056 | return normal; | 2056 | return normal; |
2057 | } | 2057 | } |
2058 | 2058 | ||
2059 | private Coord SurfaceNormal(Face face) | 2059 | private Coord SurfaceNormal(Face face) |
2060 | { | 2060 | { |
2061 | return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]); | 2061 | return SurfaceNormal(this.coords[face.v1], this.coords[face.v2], this.coords[face.v3]); |
2062 | } | 2062 | } |
2063 | 2063 | ||
2064 | /// <summary> | 2064 | /// <summary> |
2065 | /// Calculate the surface normal for a face in the list of faces | 2065 | /// Calculate the surface normal for a face in the list of faces |
2066 | /// </summary> | 2066 | /// </summary> |
2067 | /// <param name="faceIndex"></param> | 2067 | /// <param name="faceIndex"></param> |
2068 | /// <returns></returns> | 2068 | /// <returns></returns> |
2069 | public Coord SurfaceNormal(int faceIndex) | 2069 | public Coord SurfaceNormal(int faceIndex) |
2070 | { | 2070 | { |
2071 | int numFaces = this.faces.Count; | 2071 | int numFaces = this.faces.Count; |
2072 | if (faceIndex < 0 || faceIndex >= numFaces) | 2072 | if (faceIndex < 0 || faceIndex >= numFaces) |
2073 | throw new Exception("faceIndex out of range"); | 2073 | throw new Exception("faceIndex out of range"); |
2074 | 2074 | ||
2075 | return SurfaceNormal(this.faces[faceIndex]); | 2075 | return SurfaceNormal(this.faces[faceIndex]); |
2076 | } | 2076 | } |
2077 | 2077 | ||
2078 | /// <summary> | 2078 | /// <summary> |
2079 | /// Duplicates a PrimMesh object. All object properties are copied by value, including lists. | 2079 | /// Duplicates a PrimMesh object. All object properties are copied by value, including lists. |
2080 | /// </summary> | 2080 | /// </summary> |
2081 | /// <returns></returns> | 2081 | /// <returns></returns> |
2082 | public PrimMesh Copy() | 2082 | public PrimMesh Copy() |
2083 | { | 2083 | { |
2084 | PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides); | 2084 | PrimMesh copy = new PrimMesh(this.sides, this.profileStart, this.profileEnd, this.hollow, this.hollowSides); |
2085 | copy.twistBegin = this.twistBegin; | 2085 | copy.twistBegin = this.twistBegin; |
2086 | copy.twistEnd = this.twistEnd; | 2086 | copy.twistEnd = this.twistEnd; |
2087 | copy.topShearX = this.topShearX; | 2087 | copy.topShearX = this.topShearX; |
2088 | copy.topShearY = this.topShearY; | 2088 | copy.topShearY = this.topShearY; |
2089 | copy.pathCutBegin = this.pathCutBegin; | 2089 | copy.pathCutBegin = this.pathCutBegin; |
2090 | copy.pathCutEnd = this.pathCutEnd; | 2090 | copy.pathCutEnd = this.pathCutEnd; |
2091 | copy.dimpleBegin = this.dimpleBegin; | 2091 | copy.dimpleBegin = this.dimpleBegin; |
2092 | copy.dimpleEnd = this.dimpleEnd; | 2092 | copy.dimpleEnd = this.dimpleEnd; |
2093 | copy.skew = this.skew; | 2093 | copy.skew = this.skew; |
2094 | copy.holeSizeX = this.holeSizeX; | 2094 | copy.holeSizeX = this.holeSizeX; |
2095 | copy.holeSizeY = this.holeSizeY; | 2095 | copy.holeSizeY = this.holeSizeY; |
2096 | copy.taperX = this.taperX; | 2096 | copy.taperX = this.taperX; |
2097 | copy.taperY = this.taperY; | 2097 | copy.taperY = this.taperY; |
2098 | copy.radius = this.radius; | 2098 | copy.radius = this.radius; |
2099 | copy.revolutions = this.revolutions; | 2099 | copy.revolutions = this.revolutions; |
2100 | copy.stepsPerRevolution = this.stepsPerRevolution; | 2100 | copy.stepsPerRevolution = this.stepsPerRevolution; |
2101 | copy.calcVertexNormals = this.calcVertexNormals; | 2101 | copy.calcVertexNormals = this.calcVertexNormals; |
2102 | copy.normalsProcessed = this.normalsProcessed; | 2102 | copy.normalsProcessed = this.normalsProcessed; |
2103 | copy.viewerMode = this.viewerMode; | 2103 | copy.viewerMode = this.viewerMode; |
2104 | copy.numPrimFaces = this.numPrimFaces; | 2104 | copy.numPrimFaces = this.numPrimFaces; |
2105 | copy.errorMessage = this.errorMessage; | 2105 | copy.errorMessage = this.errorMessage; |
2106 | 2106 | ||
2107 | copy.coords = new List<Coord>(this.coords); | 2107 | copy.coords = new List<Coord>(this.coords); |
2108 | copy.faces = new List<Face>(this.faces); | 2108 | copy.faces = new List<Face>(this.faces); |
2109 | copy.viewerFaces = new List<ViewerFace>(this.viewerFaces); | 2109 | copy.viewerFaces = new List<ViewerFace>(this.viewerFaces); |
2110 | copy.normals = new List<Coord>(this.normals); | 2110 | copy.normals = new List<Coord>(this.normals); |
2111 | 2111 | ||
2112 | return copy; | 2112 | return copy; |
2113 | } | 2113 | } |
2114 | 2114 | ||
2115 | /// <summary> | 2115 | /// <summary> |
2116 | /// Calculate surface normals for all of the faces in the list of faces in this mesh | 2116 | /// Calculate surface normals for all of the faces in the list of faces in this mesh |
2117 | /// </summary> | 2117 | /// </summary> |
2118 | public void CalcNormals() | 2118 | public void CalcNormals() |
2119 | { | 2119 | { |
2120 | if (normalsProcessed) | 2120 | if (normalsProcessed) |
2121 | return; | 2121 | return; |
2122 | 2122 | ||
2123 | normalsProcessed = true; | 2123 | normalsProcessed = true; |
2124 | 2124 | ||
2125 | int numFaces = faces.Count; | 2125 | int numFaces = faces.Count; |
2126 | 2126 | ||
2127 | if (!this.calcVertexNormals) | 2127 | if (!this.calcVertexNormals) |
2128 | this.normals = new List<Coord>(); | 2128 | this.normals = new List<Coord>(); |
2129 | 2129 | ||
2130 | for (int i = 0; i < numFaces; i++) | 2130 | for (int i = 0; i < numFaces; i++) |
2131 | { | 2131 | { |
2132 | Face face = faces[i]; | 2132 | Face face = faces[i]; |
2133 | 2133 | ||
2134 | this.normals.Add(SurfaceNormal(i).Normalize()); | 2134 | this.normals.Add(SurfaceNormal(i).Normalize()); |
2135 | 2135 | ||
2136 | int normIndex = normals.Count - 1; | 2136 | int normIndex = normals.Count - 1; |
2137 | face.n1 = normIndex; | 2137 | face.n1 = normIndex; |
2138 | face.n2 = normIndex; | 2138 | face.n2 = normIndex; |
2139 | face.n3 = normIndex; | 2139 | face.n3 = normIndex; |
2140 | 2140 | ||
2141 | this.faces[i] = face; | 2141 | this.faces[i] = face; |
2142 | } | 2142 | } |
2143 | } | 2143 | } |
2144 | 2144 | ||
2145 | /// <summary> | 2145 | /// <summary> |
2146 | /// Adds a value to each XYZ vertex coordinate in the mesh | 2146 | /// Adds a value to each XYZ vertex coordinate in the mesh |
2147 | /// </summary> | 2147 | /// </summary> |
2148 | /// <param name="x"></param> | 2148 | /// <param name="x"></param> |
2149 | /// <param name="y"></param> | 2149 | /// <param name="y"></param> |
2150 | /// <param name="z"></param> | 2150 | /// <param name="z"></param> |
2151 | public void AddPos(float x, float y, float z) | 2151 | public void AddPos(float x, float y, float z) |
2152 | { | 2152 | { |
2153 | int i; | 2153 | int i; |
2154 | int numVerts = this.coords.Count; | 2154 | int numVerts = this.coords.Count; |
2155 | Coord vert; | 2155 | Coord vert; |
2156 | 2156 | ||
2157 | for (i = 0; i < numVerts; i++) | 2157 | for (i = 0; i < numVerts; i++) |
2158 | { | 2158 | { |
2159 | vert = this.coords[i]; | 2159 | vert = this.coords[i]; |
2160 | vert.X += x; | 2160 | vert.X += x; |
2161 | vert.Y += y; | 2161 | vert.Y += y; |
2162 | vert.Z += z; | 2162 | vert.Z += z; |
2163 | this.coords[i] = vert; | 2163 | this.coords[i] = vert; |
2164 | } | 2164 | } |
2165 | 2165 | ||
2166 | if (this.viewerFaces != null) | 2166 | if (this.viewerFaces != null) |
2167 | { | 2167 | { |
2168 | int numViewerFaces = this.viewerFaces.Count; | 2168 | int numViewerFaces = this.viewerFaces.Count; |
2169 | 2169 | ||
2170 | for (i = 0; i < numViewerFaces; i++) | 2170 | for (i = 0; i < numViewerFaces; i++) |
2171 | { | 2171 | { |
2172 | ViewerFace v = this.viewerFaces[i]; | 2172 | ViewerFace v = this.viewerFaces[i]; |
2173 | v.AddPos(x, y, z); | 2173 | v.AddPos(x, y, z); |
2174 | this.viewerFaces[i] = v; | 2174 | this.viewerFaces[i] = v; |
2175 | } | 2175 | } |
2176 | } | 2176 | } |
2177 | } | 2177 | } |
2178 | 2178 | ||
2179 | /// <summary> | 2179 | /// <summary> |
2180 | /// Rotates the mesh | 2180 | /// Rotates the mesh |
2181 | /// </summary> | 2181 | /// </summary> |
2182 | /// <param name="q"></param> | 2182 | /// <param name="q"></param> |
2183 | public void AddRot(Quat q) | 2183 | public void AddRot(Quat q) |
2184 | { | 2184 | { |
2185 | int i; | 2185 | int i; |
2186 | int numVerts = this.coords.Count; | 2186 | int numVerts = this.coords.Count; |
2187 | 2187 | ||
2188 | for (i = 0; i < numVerts; i++) | 2188 | for (i = 0; i < numVerts; i++) |
2189 | this.coords[i] *= q; | 2189 | this.coords[i] *= q; |
2190 | 2190 | ||
2191 | if (this.normals != null) | 2191 | if (this.normals != null) |
2192 | { | 2192 | { |
2193 | int numNormals = this.normals.Count; | 2193 | int numNormals = this.normals.Count; |
2194 | for (i = 0; i < numNormals; i++) | 2194 | for (i = 0; i < numNormals; i++) |
2195 | this.normals[i] *= q; | 2195 | this.normals[i] *= q; |
2196 | } | 2196 | } |
2197 | 2197 | ||
2198 | if (this.viewerFaces != null) | 2198 | if (this.viewerFaces != null) |
2199 | { | 2199 | { |
2200 | int numViewerFaces = this.viewerFaces.Count; | 2200 | int numViewerFaces = this.viewerFaces.Count; |
2201 | 2201 | ||
2202 | for (i = 0; i < numViewerFaces; i++) | 2202 | for (i = 0; i < numViewerFaces; i++) |
2203 | { | 2203 | { |
2204 | ViewerFace v = this.viewerFaces[i]; | 2204 | ViewerFace v = this.viewerFaces[i]; |
2205 | v.v1 *= q; | 2205 | v.v1 *= q; |
2206 | v.v2 *= q; | 2206 | v.v2 *= q; |
2207 | v.v3 *= q; | 2207 | v.v3 *= q; |
2208 | 2208 | ||
2209 | v.n1 *= q; | 2209 | v.n1 *= q; |
2210 | v.n2 *= q; | 2210 | v.n2 *= q; |
2211 | v.n3 *= q; | 2211 | v.n3 *= q; |
2212 | this.viewerFaces[i] = v; | 2212 | this.viewerFaces[i] = v; |
2213 | } | 2213 | } |
2214 | } | 2214 | } |
2215 | } | 2215 | } |
2216 | 2216 | ||
2217 | #if VERTEX_INDEXER | 2217 | #if VERTEX_INDEXER |
2218 | public VertexIndexer GetVertexIndexer() | 2218 | public VertexIndexer GetVertexIndexer() |
2219 | { | 2219 | { |
2220 | if (this.viewerMode && this.viewerFaces.Count > 0) | 2220 | if (this.viewerMode && this.viewerFaces.Count > 0) |
2221 | return new VertexIndexer(this); | 2221 | return new VertexIndexer(this); |
2222 | return null; | 2222 | return null; |
2223 | } | 2223 | } |
2224 | #endif | 2224 | #endif |
2225 | 2225 | ||
2226 | /// <summary> | 2226 | /// <summary> |
2227 | /// Scales the mesh | 2227 | /// Scales the mesh |
2228 | /// </summary> | 2228 | /// </summary> |
2229 | /// <param name="x"></param> | 2229 | /// <param name="x"></param> |
2230 | /// <param name="y"></param> | 2230 | /// <param name="y"></param> |
2231 | /// <param name="z"></param> | 2231 | /// <param name="z"></param> |
2232 | public void Scale(float x, float y, float z) | 2232 | public void Scale(float x, float y, float z) |
2233 | { | 2233 | { |
2234 | int i; | 2234 | int i; |
2235 | int numVerts = this.coords.Count; | 2235 | int numVerts = this.coords.Count; |
2236 | //Coord vert; | 2236 | //Coord vert; |
2237 | 2237 | ||
2238 | Coord m = new Coord(x, y, z); | 2238 | Coord m = new Coord(x, y, z); |
2239 | for (i = 0; i < numVerts; i++) | 2239 | for (i = 0; i < numVerts; i++) |
2240 | this.coords[i] *= m; | 2240 | this.coords[i] *= m; |
2241 | 2241 | ||
2242 | if (this.viewerFaces != null) | 2242 | if (this.viewerFaces != null) |
2243 | { | 2243 | { |
2244 | int numViewerFaces = this.viewerFaces.Count; | 2244 | int numViewerFaces = this.viewerFaces.Count; |
2245 | for (i = 0; i < numViewerFaces; i++) | 2245 | for (i = 0; i < numViewerFaces; i++) |
2246 | { | 2246 | { |
2247 | ViewerFace v = this.viewerFaces[i]; | 2247 | ViewerFace v = this.viewerFaces[i]; |
2248 | v.v1 *= m; | 2248 | v.v1 *= m; |
2249 | v.v2 *= m; | 2249 | v.v2 *= m; |
2250 | v.v3 *= m; | 2250 | v.v3 *= m; |
2251 | this.viewerFaces[i] = v; | 2251 | this.viewerFaces[i] = v; |
2252 | } | 2252 | } |
2253 | 2253 | ||
2254 | } | 2254 | } |
2255 | 2255 | ||
2256 | } | 2256 | } |
2257 | 2257 | ||
2258 | /// <summary> | 2258 | /// <summary> |
2259 | /// Dumps the mesh to a Blender compatible "Raw" format file | 2259 | /// Dumps the mesh to a Blender compatible "Raw" format file |
2260 | /// </summary> | 2260 | /// </summary> |
2261 | /// <param name="path"></param> | 2261 | /// <param name="path"></param> |
2262 | /// <param name="name"></param> | 2262 | /// <param name="name"></param> |
2263 | /// <param name="title"></param> | 2263 | /// <param name="title"></param> |
2264 | public void DumpRaw(String path, String name, String title) | 2264 | public void DumpRaw(String path, String name, String title) |
2265 | { | 2265 | { |
2266 | if (path == null) | 2266 | if (path == null) |
2267 | return; | 2267 | return; |
2268 | String fileName = name + "_" + title + ".raw"; | 2268 | String fileName = name + "_" + title + ".raw"; |
2269 | String completePath = System.IO.Path.Combine(path, fileName); | 2269 | String completePath = System.IO.Path.Combine(path, fileName); |
2270 | StreamWriter sw = new StreamWriter(completePath); | 2270 | StreamWriter sw = new StreamWriter(completePath); |
2271 | 2271 | ||
2272 | for (int i = 0; i < this.faces.Count; i++) | 2272 | for (int i = 0; i < this.faces.Count; i++) |
2273 | { | 2273 | { |
2274 | string s = this.coords[this.faces[i].v1].ToString(); | 2274 | string s = this.coords[this.faces[i].v1].ToString(); |
2275 | s += " " + this.coords[this.faces[i].v2].ToString(); | 2275 | s += " " + this.coords[this.faces[i].v2].ToString(); |
2276 | s += " " + this.coords[this.faces[i].v3].ToString(); | 2276 | s += " " + this.coords[this.faces[i].v3].ToString(); |
2277 | 2277 | ||
2278 | sw.WriteLine(s); | 2278 | sw.WriteLine(s); |
2279 | } | 2279 | } |
2280 | 2280 | ||
2281 | sw.Close(); | 2281 | sw.Close(); |
2282 | } | 2282 | } |
2283 | } | 2283 | } |
2284 | } | 2284 | } |
diff --git a/OpenSim/Region/Physics/Meshing/SculptMap.cs b/OpenSim/Region/Physics/Meshing/SculptMap.cs index 4906cf6..d2d71de 100644 --- a/OpenSim/Region/Physics/Meshing/SculptMap.cs +++ b/OpenSim/Region/Physics/Meshing/SculptMap.cs | |||
@@ -1,176 +1,176 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors | 2 | * Copyright (c) Contributors |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | // to build without references to System.Drawing, comment this out | 28 | // to build without references to System.Drawing, comment this out |
29 | #define SYSTEM_DRAWING | 29 | #define SYSTEM_DRAWING |
30 | 30 | ||
31 | using System; | 31 | using System; |
32 | using System.Collections.Generic; | 32 | using System.Collections.Generic; |
33 | using System.Text; | 33 | using System.Text; |
34 | 34 | ||
35 | #if SYSTEM_DRAWING | 35 | #if SYSTEM_DRAWING |
36 | using System.Drawing; | 36 | using System.Drawing; |
37 | using System.Drawing.Imaging; | 37 | using System.Drawing.Imaging; |
38 | 38 | ||
39 | namespace PrimMesher | 39 | namespace PrimMesher |
40 | { | 40 | { |
41 | public class SculptMap | 41 | public class SculptMap |
42 | { | 42 | { |
43 | public int width; | 43 | public int width; |
44 | public int height; | 44 | public int height; |
45 | public byte[] redBytes; | 45 | public byte[] redBytes; |
46 | public byte[] greenBytes; | 46 | public byte[] greenBytes; |
47 | public byte[] blueBytes; | 47 | public byte[] blueBytes; |
48 | 48 | ||
49 | public SculptMap() | 49 | public SculptMap() |
50 | { | 50 | { |
51 | } | 51 | } |
52 | 52 | ||
53 | public SculptMap(Bitmap bm, int lod) | 53 | public SculptMap(Bitmap bm, int lod) |
54 | { | 54 | { |
55 | int bmW = bm.Width; | 55 | int bmW = bm.Width; |
56 | int bmH = bm.Height; | 56 | int bmH = bm.Height; |
57 | 57 | ||
58 | if (bmW == 0 || bmH == 0) | 58 | if (bmW == 0 || bmH == 0) |
59 | throw new Exception("SculptMap: bitmap has no data"); | 59 | throw new Exception("SculptMap: bitmap has no data"); |
60 | 60 | ||
61 | int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image | 61 | int numLodPixels = lod * 2 * lod * 2; // (32 * 2)^2 = 64^2 pixels for default sculpt map image |
62 | 62 | ||
63 | bool needsScaling = false; | 63 | bool needsScaling = false; |
64 | 64 | ||
65 | width = bmW; | 65 | width = bmW; |
66 | height = bmH; | 66 | height = bmH; |
67 | while (width * height > numLodPixels) | 67 | while (width * height > numLodPixels) |
68 | { | 68 | { |
69 | width >>= 1; | 69 | width >>= 1; |
70 | height >>= 1; | 70 | height >>= 1; |
71 | needsScaling = true; | 71 | needsScaling = true; |
72 | } | 72 | } |
73 | 73 | ||
74 | 74 | ||
75 | 75 | ||
76 | try | 76 | try |
77 | { | 77 | { |
78 | if (needsScaling) | 78 | if (needsScaling) |
79 | bm = ScaleImage(bm, width, height, | 79 | bm = ScaleImage(bm, width, height, |
80 | System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor); | 80 | System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor); |
81 | } | 81 | } |
82 | 82 | ||
83 | catch (Exception e) | 83 | catch (Exception e) |
84 | { | 84 | { |
85 | throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); | 85 | throw new Exception("Exception in ScaleImage(): e: " + e.ToString()); |
86 | } | 86 | } |
87 | 87 | ||
88 | if (width * height > lod * lod) | 88 | if (width * height > lod * lod) |
89 | { | 89 | { |
90 | width >>= 1; | 90 | width >>= 1; |
91 | height >>= 1; | 91 | height >>= 1; |
92 | } | 92 | } |
93 | 93 | ||
94 | int numBytes = (width + 1) * (height + 1); | 94 | int numBytes = (width + 1) * (height + 1); |
95 | redBytes = new byte[numBytes]; | 95 | redBytes = new byte[numBytes]; |
96 | greenBytes = new byte[numBytes]; | 96 | greenBytes = new byte[numBytes]; |
97 | blueBytes = new byte[numBytes]; | 97 | blueBytes = new byte[numBytes]; |
98 | 98 | ||
99 | int byteNdx = 0; | 99 | int byteNdx = 0; |
100 | 100 | ||
101 | try | 101 | try |
102 | { | 102 | { |
103 | for (int y = 0; y <= height; y++) | 103 | for (int y = 0; y <= height; y++) |
104 | { | 104 | { |
105 | for (int x = 0; x <= width; x++) | 105 | for (int x = 0; x <= width; x++) |
106 | { | 106 | { |
107 | int bmY = y < height ? y * 2 : y * 2 - 1; | 107 | int bmY = y < height ? y * 2 : y * 2 - 1; |
108 | int bmX = x < width ? x * 2 : x * 2 - 1; | 108 | int bmX = x < width ? x * 2 : x * 2 - 1; |
109 | Color c = bm.GetPixel(bmX, bmY); | 109 | Color c = bm.GetPixel(bmX, bmY); |
110 | 110 | ||
111 | redBytes[byteNdx] = c.R; | 111 | redBytes[byteNdx] = c.R; |
112 | greenBytes[byteNdx] = c.G; | 112 | greenBytes[byteNdx] = c.G; |
113 | blueBytes[byteNdx] = c.B; | 113 | blueBytes[byteNdx] = c.B; |
114 | 114 | ||
115 | ++byteNdx; | 115 | ++byteNdx; |
116 | } | 116 | } |
117 | } | 117 | } |
118 | } | 118 | } |
119 | catch (Exception e) | 119 | catch (Exception e) |
120 | { | 120 | { |
121 | throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString()); | 121 | throw new Exception("Caught exception processing byte arrays in SculptMap(): e: " + e.ToString()); |
122 | } | 122 | } |
123 | 123 | ||
124 | width++; | 124 | width++; |
125 | height++; | 125 | height++; |
126 | } | 126 | } |
127 | 127 | ||
128 | public List<List<Coord>> ToRows(bool mirror) | 128 | public List<List<Coord>> ToRows(bool mirror) |
129 | { | 129 | { |
130 | int numRows = height; | 130 | int numRows = height; |
131 | int numCols = width; | 131 | int numCols = width; |
132 | 132 | ||
133 | List<List<Coord>> rows = new List<List<Coord>>(numRows); | 133 | List<List<Coord>> rows = new List<List<Coord>>(numRows); |
134 | 134 | ||
135 | float pixScale = 1.0f / 255; | 135 | float pixScale = 1.0f / 255; |
136 | 136 | ||
137 | int rowNdx, colNdx; | 137 | int rowNdx, colNdx; |
138 | int smNdx = 0; | 138 | int smNdx = 0; |
139 | 139 | ||
140 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) | 140 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) |
141 | { | 141 | { |
142 | List<Coord> row = new List<Coord>(numCols); | 142 | List<Coord> row = new List<Coord>(numCols); |
143 | for (colNdx = 0; colNdx < numCols; colNdx++) | 143 | for (colNdx = 0; colNdx < numCols; colNdx++) |
144 | { | 144 | { |
145 | if (mirror) | 145 | if (mirror) |
146 | row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f)); | 146 | row.Add(new Coord(-(redBytes[smNdx] * pixScale - 0.5f), (greenBytes[smNdx] * pixScale - 0.5f), blueBytes[smNdx] * pixScale - 0.5f)); |
147 | else | 147 | else |
148 | row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f)); | 148 | row.Add(new Coord(redBytes[smNdx] * pixScale - 0.5f, greenBytes[smNdx] * pixScale - 0.5f, blueBytes[smNdx] * pixScale - 0.5f)); |
149 | 149 | ||
150 | ++smNdx; | 150 | ++smNdx; |
151 | } | 151 | } |
152 | rows.Add(row); | 152 | rows.Add(row); |
153 | } | 153 | } |
154 | return rows; | 154 | return rows; |
155 | } | 155 | } |
156 | 156 | ||
157 | private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight, | 157 | private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight, |
158 | System.Drawing.Drawing2D.InterpolationMode interpMode) | 158 | System.Drawing.Drawing2D.InterpolationMode interpMode) |
159 | { | 159 | { |
160 | Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight); | 160 | Bitmap scaledImage = new Bitmap(srcImage, destWidth, destHeight); |
161 | scaledImage.SetResolution(96.0f, 96.0f); | 161 | scaledImage.SetResolution(96.0f, 96.0f); |
162 | 162 | ||
163 | Graphics grPhoto = Graphics.FromImage(scaledImage); | 163 | Graphics grPhoto = Graphics.FromImage(scaledImage); |
164 | grPhoto.InterpolationMode = interpMode; | 164 | grPhoto.InterpolationMode = interpMode; |
165 | 165 | ||
166 | grPhoto.DrawImage(srcImage, | 166 | grPhoto.DrawImage(srcImage, |
167 | new Rectangle(0, 0, destWidth, destHeight), | 167 | new Rectangle(0, 0, destWidth, destHeight), |
168 | new Rectangle(0, 0, srcImage.Width, srcImage.Height), | 168 | new Rectangle(0, 0, srcImage.Width, srcImage.Height), |
169 | GraphicsUnit.Pixel); | 169 | GraphicsUnit.Pixel); |
170 | 170 | ||
171 | grPhoto.Dispose(); | 171 | grPhoto.Dispose(); |
172 | return scaledImage; | 172 | return scaledImage; |
173 | } | 173 | } |
174 | } | 174 | } |
175 | } | 175 | } |
176 | #endif | 176 | #endif |
diff --git a/OpenSim/Region/Physics/Meshing/SculptMesh.cs b/OpenSim/Region/Physics/Meshing/SculptMesh.cs index 06606c3..6aa8fe4 100644 --- a/OpenSim/Region/Physics/Meshing/SculptMesh.cs +++ b/OpenSim/Region/Physics/Meshing/SculptMesh.cs | |||
@@ -1,647 +1,647 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors | 2 | * Copyright (c) Contributors |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | // to build without references to System.Drawing, comment this out | 28 | // to build without references to System.Drawing, comment this out |
29 | #define SYSTEM_DRAWING | 29 | #define SYSTEM_DRAWING |
30 | 30 | ||
31 | using System; | 31 | using System; |
32 | using System.Collections.Generic; | 32 | using System.Collections.Generic; |
33 | using System.Text; | 33 | using System.Text; |
34 | using System.IO; | 34 | using System.IO; |
35 | 35 | ||
36 | #if SYSTEM_DRAWING | 36 | #if SYSTEM_DRAWING |
37 | using System.Drawing; | 37 | using System.Drawing; |
38 | using System.Drawing.Imaging; | 38 | using System.Drawing.Imaging; |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | namespace PrimMesher | 41 | namespace PrimMesher |
42 | { | 42 | { |
43 | 43 | ||
44 | public class SculptMesh | 44 | public class SculptMesh |
45 | { | 45 | { |
46 | public List<Coord> coords; | 46 | public List<Coord> coords; |
47 | public List<Face> faces; | 47 | public List<Face> faces; |
48 | 48 | ||
49 | public List<ViewerFace> viewerFaces; | 49 | public List<ViewerFace> viewerFaces; |
50 | public List<Coord> normals; | 50 | public List<Coord> normals; |
51 | public List<UVCoord> uvs; | 51 | public List<UVCoord> uvs; |
52 | 52 | ||
53 | public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; | 53 | public enum SculptType { sphere = 1, torus = 2, plane = 3, cylinder = 4 }; |
54 | 54 | ||
55 | #if SYSTEM_DRAWING | 55 | #if SYSTEM_DRAWING |
56 | 56 | ||
57 | public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) | 57 | public SculptMesh SculptMeshFromFile(string fileName, SculptType sculptType, int lod, bool viewerMode) |
58 | { | 58 | { |
59 | Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); | 59 | Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); |
60 | SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); | 60 | SculptMesh sculptMesh = new SculptMesh(bitmap, sculptType, lod, viewerMode); |
61 | bitmap.Dispose(); | 61 | bitmap.Dispose(); |
62 | return sculptMesh; | 62 | return sculptMesh; |
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
66 | public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert) | 66 | public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert) |
67 | { | 67 | { |
68 | Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); | 68 | Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName); |
69 | _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0); | 69 | _SculptMesh(bitmap, (SculptType)sculptType, lod, viewerMode != 0, mirror != 0, invert != 0); |
70 | bitmap.Dispose(); | 70 | bitmap.Dispose(); |
71 | } | 71 | } |
72 | #endif | 72 | #endif |
73 | 73 | ||
74 | /// <summary> | 74 | /// <summary> |
75 | /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications | 75 | /// ** Experimental ** May disappear from future versions ** not recommeneded for use in applications |
76 | /// Construct a sculpt mesh from a 2D array of floats | 76 | /// Construct a sculpt mesh from a 2D array of floats |
77 | /// </summary> | 77 | /// </summary> |
78 | /// <param name="zMap"></param> | 78 | /// <param name="zMap"></param> |
79 | /// <param name="xBegin"></param> | 79 | /// <param name="xBegin"></param> |
80 | /// <param name="xEnd"></param> | 80 | /// <param name="xEnd"></param> |
81 | /// <param name="yBegin"></param> | 81 | /// <param name="yBegin"></param> |
82 | /// <param name="yEnd"></param> | 82 | /// <param name="yEnd"></param> |
83 | /// <param name="viewerMode"></param> | 83 | /// <param name="viewerMode"></param> |
84 | public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) | 84 | public SculptMesh(float[,] zMap, float xBegin, float xEnd, float yBegin, float yEnd, bool viewerMode) |
85 | { | 85 | { |
86 | float xStep, yStep; | 86 | float xStep, yStep; |
87 | float uStep, vStep; | 87 | float uStep, vStep; |
88 | 88 | ||
89 | int numYElements = zMap.GetLength(0); | 89 | int numYElements = zMap.GetLength(0); |
90 | int numXElements = zMap.GetLength(1); | 90 | int numXElements = zMap.GetLength(1); |
91 | 91 | ||
92 | try | 92 | try |
93 | { | 93 | { |
94 | xStep = (xEnd - xBegin) / (float)(numXElements - 1); | 94 | xStep = (xEnd - xBegin) / (float)(numXElements - 1); |
95 | yStep = (yEnd - yBegin) / (float)(numYElements - 1); | 95 | yStep = (yEnd - yBegin) / (float)(numYElements - 1); |
96 | 96 | ||
97 | uStep = 1.0f / (numXElements - 1); | 97 | uStep = 1.0f / (numXElements - 1); |
98 | vStep = 1.0f / (numYElements - 1); | 98 | vStep = 1.0f / (numYElements - 1); |
99 | } | 99 | } |
100 | catch (DivideByZeroException) | 100 | catch (DivideByZeroException) |
101 | { | 101 | { |
102 | return; | 102 | return; |
103 | } | 103 | } |
104 | 104 | ||
105 | coords = new List<Coord>(); | 105 | coords = new List<Coord>(); |
106 | faces = new List<Face>(); | 106 | faces = new List<Face>(); |
107 | normals = new List<Coord>(); | 107 | normals = new List<Coord>(); |
108 | uvs = new List<UVCoord>(); | 108 | uvs = new List<UVCoord>(); |
109 | 109 | ||
110 | viewerFaces = new List<ViewerFace>(); | 110 | viewerFaces = new List<ViewerFace>(); |
111 | 111 | ||
112 | int p1, p2, p3, p4; | 112 | int p1, p2, p3, p4; |
113 | 113 | ||
114 | int x, y; | 114 | int x, y; |
115 | int xStart = 0, yStart = 0; | 115 | int xStart = 0, yStart = 0; |
116 | 116 | ||
117 | for (y = yStart; y < numYElements; y++) | 117 | for (y = yStart; y < numYElements; y++) |
118 | { | 118 | { |
119 | int rowOffset = y * numXElements; | 119 | int rowOffset = y * numXElements; |
120 | 120 | ||
121 | for (x = xStart; x < numXElements; x++) | 121 | for (x = xStart; x < numXElements; x++) |
122 | { | 122 | { |
123 | /* | ||
124 | * p1-----p2 | ||
125 | * | \ f2 | | ||
126 | * | \ | | ||
127 | * | f1 \| | ||
128 | * p3-----p4 | ||
129 | */ | ||
130 | |||
131 | p4 = rowOffset + x; | ||
132 | p3 = p4 - 1; | ||
133 | |||
134 | p2 = p4 - numXElements; | ||
135 | p1 = p3 - numXElements; | ||
136 | |||
137 | Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]); | ||
138 | this.coords.Add(c); | ||
139 | if (viewerMode) | ||
140 | { | ||
141 | this.normals.Add(new Coord()); | ||
142 | this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y)); | ||
143 | } | ||
144 | |||
145 | if (y > 0 && x > 0) | ||
146 | { | ||
147 | Face f1, f2; | ||
148 | |||
149 | if (viewerMode) | ||
150 | { | ||
151 | f1 = new Face(p1, p4, p3, p1, p4, p3); | ||
152 | f1.uv1 = p1; | ||
153 | f1.uv2 = p4; | ||
154 | f1.uv3 = p3; | ||
155 | |||
156 | f2 = new Face(p1, p2, p4, p1, p2, p4); | ||
157 | f2.uv1 = p1; | ||
158 | f2.uv2 = p2; | ||
159 | f2.uv3 = p4; | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | f1 = new Face(p1, p4, p3); | ||
164 | f2 = new Face(p1, p2, p4); | ||
165 | } | ||
166 | |||
167 | this.faces.Add(f1); | ||
168 | this.faces.Add(f2); | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | |||
173 | if (viewerMode) | ||
174 | calcVertexNormals(SculptType.plane, numXElements, numYElements); | ||
175 | } | ||
176 | |||
177 | #if SYSTEM_DRAWING | ||
178 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) | ||
179 | { | ||
180 | _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false); | ||
181 | } | ||
182 | |||
183 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) | ||
184 | { | ||
185 | _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); | ||
186 | } | ||
187 | #endif | ||
188 | |||
189 | public SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) | ||
190 | { | ||
191 | _SculptMesh(rows, sculptType, viewerMode, mirror, invert); | ||
192 | } | ||
193 | |||
194 | #if SYSTEM_DRAWING | ||
195 | /// <summary> | ||
196 | /// converts a bitmap to a list of lists of coords, while scaling the image. | ||
197 | /// the scaling is done in floating point so as to allow for reduced vertex position | ||
198 | /// quantization as the position will be averaged between pixel values. this routine will | ||
199 | /// likely fail if the bitmap width and height are not powers of 2. | ||
200 | /// </summary> | ||
201 | /// <param name="bitmap"></param> | ||
202 | /// <param name="scale"></param> | ||
203 | /// <param name="mirror"></param> | ||
204 | /// <returns></returns> | ||
205 | private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror) | ||
206 | { | ||
207 | int numRows = bitmap.Height / scale; | ||
208 | int numCols = bitmap.Width / scale; | ||
209 | List<List<Coord>> rows = new List<List<Coord>>(numRows); | ||
210 | |||
211 | float pixScale = 1.0f / (scale * scale); | ||
212 | pixScale /= 255; | ||
213 | |||
214 | int imageX, imageY = 0; | ||
215 | |||
216 | int rowNdx, colNdx; | ||
217 | |||
218 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) | ||
219 | { | ||
220 | List<Coord> row = new List<Coord>(numCols); | ||
221 | for (colNdx = 0; colNdx < numCols; colNdx++) | ||
222 | { | ||
223 | imageX = colNdx * scale; | ||
224 | int imageYStart = rowNdx * scale; | ||
225 | int imageYEnd = imageYStart + scale; | ||
226 | int imageXEnd = imageX + scale; | ||
227 | float rSum = 0.0f; | ||
228 | float gSum = 0.0f; | ||
229 | float bSum = 0.0f; | ||
230 | for (; imageX < imageXEnd; imageX++) | ||
231 | { | ||
232 | for (imageY = imageYStart; imageY < imageYEnd; imageY++) | ||
233 | { | ||
234 | Color c = bitmap.GetPixel(imageX, imageY); | ||
235 | if (c.A != 255) | ||
236 | { | ||
237 | bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); | ||
238 | c = bitmap.GetPixel(imageX, imageY); | ||
239 | } | ||
240 | rSum += c.R; | ||
241 | gSum += c.G; | ||
242 | bSum += c.B; | ||
243 | } | ||
244 | } | ||
245 | if (mirror) | ||
246 | row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); | ||
247 | else | ||
248 | row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); | ||
249 | |||
250 | } | ||
251 | rows.Add(row); | ||
252 | } | ||
253 | return rows; | ||
254 | } | ||
255 | |||
256 | private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror) | ||
257 | { | ||
258 | int numRows = bitmap.Height / scale; | ||
259 | int numCols = bitmap.Width / scale; | ||
260 | List<List<Coord>> rows = new List<List<Coord>>(numRows); | ||
261 | |||
262 | float pixScale = 1.0f / 256.0f; | ||
263 | |||
264 | int imageX, imageY = 0; | ||
265 | |||
266 | int rowNdx, colNdx; | ||
267 | |||
268 | for (rowNdx = 0; rowNdx <= numRows; rowNdx++) | ||
269 | { | ||
270 | List<Coord> row = new List<Coord>(numCols); | ||
271 | imageY = rowNdx * scale; | ||
272 | if (rowNdx == numRows) imageY--; | ||
273 | for (colNdx = 0; colNdx <= numCols; colNdx++) | ||
274 | { | ||
275 | imageX = colNdx * scale; | ||
276 | if (colNdx == numCols) imageX--; | ||
277 | |||
278 | Color c = bitmap.GetPixel(imageX, imageY); | ||
279 | if (c.A != 255) | ||
280 | { | ||
281 | bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); | ||
282 | c = bitmap.GetPixel(imageX, imageY); | ||
283 | } | ||
284 | |||
285 | if (mirror) | ||
286 | row.Add(new Coord(-(c.R * pixScale - 0.5f), c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); | ||
287 | else | ||
288 | row.Add(new Coord(c.R * pixScale - 0.5f, c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); | ||
289 | |||
290 | } | ||
291 | rows.Add(row); | ||
292 | } | ||
293 | return rows; | ||
294 | } | ||
295 | |||
296 | |||
297 | void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) | ||
298 | { | ||
299 | _SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert); | ||
300 | } | ||
301 | #endif | ||
302 | |||
303 | void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) | ||
304 | { | ||
305 | coords = new List<Coord>(); | ||
306 | faces = new List<Face>(); | ||
307 | normals = new List<Coord>(); | ||
308 | uvs = new List<UVCoord>(); | ||
309 | |||
310 | sculptType = (SculptType)(((int)sculptType) & 0x07); | ||
311 | |||
312 | if (mirror) | ||
313 | if (sculptType == SculptType.plane) | ||
314 | invert = !invert; | ||
315 | |||
316 | viewerFaces = new List<ViewerFace>(); | ||
317 | |||
318 | int width = rows[0].Count; | ||
319 | |||
320 | int p1, p2, p3, p4; | ||
321 | |||
322 | int imageX, imageY; | ||
323 | |||
324 | if (sculptType != SculptType.plane) | ||
325 | { | ||
326 | if (rows.Count % 2 == 0) | ||
327 | { | ||
328 | for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++) | ||
329 | rows[rowNdx].Add(rows[rowNdx][0]); | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | int lastIndex = rows[0].Count - 1; | ||
334 | |||
335 | for (int i = 0; i < rows.Count; i++) | ||
336 | rows[i][0] = rows[i][lastIndex]; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | Coord topPole = rows[0][width / 2]; | ||
341 | Coord bottomPole = rows[rows.Count - 1][width / 2]; | ||
342 | |||
343 | if (sculptType == SculptType.sphere) | ||
344 | { | ||
345 | if (rows.Count % 2 == 0) | ||
346 | { | ||
347 | int count = rows[0].Count; | ||
348 | List<Coord> topPoleRow = new List<Coord>(count); | ||
349 | List<Coord> bottomPoleRow = new List<Coord>(count); | ||
350 | |||
351 | for (int i = 0; i < count; i++) | ||
352 | { | ||
353 | topPoleRow.Add(topPole); | ||
354 | bottomPoleRow.Add(bottomPole); | ||
355 | } | ||
356 | rows.Insert(0, topPoleRow); | ||
357 | rows.Add(bottomPoleRow); | ||
358 | } | ||
359 | else | ||
360 | { | ||
361 | int count = rows[0].Count; | ||
362 | |||
363 | List<Coord> topPoleRow = rows[0]; | ||
364 | List<Coord> bottomPoleRow = rows[rows.Count - 1]; | ||
365 | |||
366 | for (int i = 0; i < count; i++) | ||
367 | { | ||
368 | topPoleRow[i] = topPole; | ||
369 | bottomPoleRow[i] = bottomPole; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | if (sculptType == SculptType.torus) | ||
375 | rows.Add(rows[0]); | ||
376 | |||
377 | int coordsDown = rows.Count; | ||
378 | int coordsAcross = rows[0].Count; | ||
379 | int lastColumn = coordsAcross - 1; | ||
380 | |||
381 | float widthUnit = 1.0f / (coordsAcross - 1); | ||
382 | float heightUnit = 1.0f / (coordsDown - 1); | ||
383 | |||
384 | for (imageY = 0; imageY < coordsDown; imageY++) | ||
385 | { | ||
386 | int rowOffset = imageY * coordsAcross; | ||
387 | |||
388 | for (imageX = 0; imageX < coordsAcross; imageX++) | ||
389 | { | ||
390 | /* | 123 | /* |
391 | * p1-----p2 | 124 | * p1-----p2 |
392 | * | \ f2 | | 125 | * | \ f2 | |
393 | * | \ | | 126 | * | \ | |
394 | * | f1 \| | 127 | * | f1 \| |
395 | * p3-----p4 | 128 | * p3-----p4 |
396 | */ | 129 | */ |
397 | 130 | ||
398 | p4 = rowOffset + imageX; | 131 | p4 = rowOffset + x; |
399 | p3 = p4 - 1; | 132 | p3 = p4 - 1; |
400 | 133 | ||
401 | p2 = p4 - coordsAcross; | 134 | p2 = p4 - numXElements; |
402 | p1 = p3 - coordsAcross; | 135 | p1 = p3 - numXElements; |
403 | 136 | ||
404 | this.coords.Add(rows[imageY][imageX]); | 137 | Coord c = new Coord(xBegin + x * xStep, yBegin + y * yStep, zMap[y, x]); |
405 | if (viewerMode) | 138 | this.coords.Add(c); |
406 | { | 139 | if (viewerMode) |
407 | this.normals.Add(new Coord()); | 140 | { |
408 | this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); | 141 | this.normals.Add(new Coord()); |
409 | } | 142 | this.uvs.Add(new UVCoord(uStep * x, 1.0f - vStep * y)); |
410 | 143 | } | |
411 | if (imageY > 0 && imageX > 0) | 144 | |
412 | { | 145 | if (y > 0 && x > 0) |
413 | Face f1, f2; | 146 | { |
414 | 147 | Face f1, f2; | |
415 | if (viewerMode) | 148 | |
416 | { | 149 | if (viewerMode) |
417 | if (invert) | 150 | { |
418 | { | 151 | f1 = new Face(p1, p4, p3, p1, p4, p3); |
419 | f1 = new Face(p1, p4, p3, p1, p4, p3); | 152 | f1.uv1 = p1; |
420 | f1.uv1 = p1; | 153 | f1.uv2 = p4; |
421 | f1.uv2 = p4; | 154 | f1.uv3 = p3; |
422 | f1.uv3 = p3; | 155 | |
423 | 156 | f2 = new Face(p1, p2, p4, p1, p2, p4); | |
424 | f2 = new Face(p1, p2, p4, p1, p2, p4); | 157 | f2.uv1 = p1; |
425 | f2.uv1 = p1; | 158 | f2.uv2 = p2; |
426 | f2.uv2 = p2; | 159 | f2.uv3 = p4; |
427 | f2.uv3 = p4; | 160 | } |
428 | } | 161 | else |
429 | else | 162 | { |
430 | { | 163 | f1 = new Face(p1, p4, p3); |
431 | f1 = new Face(p1, p3, p4, p1, p3, p4); | 164 | f2 = new Face(p1, p2, p4); |
432 | f1.uv1 = p1; | 165 | } |
433 | f1.uv2 = p3; | 166 | |
434 | f1.uv3 = p4; | 167 | this.faces.Add(f1); |
435 | 168 | this.faces.Add(f2); | |
436 | f2 = new Face(p1, p4, p2, p1, p4, p2); | 169 | } |
437 | f2.uv1 = p1; | 170 | } |
438 | f2.uv2 = p4; | 171 | } |
439 | f2.uv3 = p2; | 172 | |
440 | } | 173 | if (viewerMode) |
441 | } | 174 | calcVertexNormals(SculptType.plane, numXElements, numYElements); |
442 | else | 175 | } |
443 | { | 176 | |
444 | if (invert) | 177 | #if SYSTEM_DRAWING |
445 | { | 178 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode) |
446 | f1 = new Face(p1, p4, p3); | 179 | { |
447 | f2 = new Face(p1, p2, p4); | 180 | _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, false, false); |
448 | } | 181 | } |
449 | else | 182 | |
450 | { | 183 | public SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) |
451 | f1 = new Face(p1, p3, p4); | 184 | { |
452 | f2 = new Face(p1, p4, p2); | 185 | _SculptMesh(sculptBitmap, sculptType, lod, viewerMode, mirror, invert); |
453 | } | 186 | } |
454 | } | 187 | #endif |
455 | 188 | ||
456 | this.faces.Add(f1); | 189 | public SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) |
457 | this.faces.Add(f2); | 190 | { |
458 | } | 191 | _SculptMesh(rows, sculptType, viewerMode, mirror, invert); |
459 | } | 192 | } |
460 | } | 193 | |
461 | 194 | #if SYSTEM_DRAWING | |
462 | if (viewerMode) | 195 | /// <summary> |
463 | calcVertexNormals(sculptType, coordsAcross, coordsDown); | 196 | /// converts a bitmap to a list of lists of coords, while scaling the image. |
464 | } | 197 | /// the scaling is done in floating point so as to allow for reduced vertex position |
465 | 198 | /// quantization as the position will be averaged between pixel values. this routine will | |
466 | /// <summary> | 199 | /// likely fail if the bitmap width and height are not powers of 2. |
467 | /// Duplicates a SculptMesh object. All object properties are copied by value, including lists. | 200 | /// </summary> |
468 | /// </summary> | 201 | /// <param name="bitmap"></param> |
469 | /// <returns></returns> | 202 | /// <param name="scale"></param> |
470 | public SculptMesh Copy() | 203 | /// <param name="mirror"></param> |
471 | { | 204 | /// <returns></returns> |
472 | return new SculptMesh(this); | 205 | private List<List<Coord>> bitmap2Coords(Bitmap bitmap, int scale, bool mirror) |
473 | } | 206 | { |
474 | 207 | int numRows = bitmap.Height / scale; | |
475 | public SculptMesh(SculptMesh sm) | 208 | int numCols = bitmap.Width / scale; |
476 | { | 209 | List<List<Coord>> rows = new List<List<Coord>>(numRows); |
477 | coords = new List<Coord>(sm.coords); | 210 | |
478 | faces = new List<Face>(sm.faces); | 211 | float pixScale = 1.0f / (scale * scale); |
479 | viewerFaces = new List<ViewerFace>(sm.viewerFaces); | 212 | pixScale /= 255; |
480 | normals = new List<Coord>(sm.normals); | 213 | |
481 | uvs = new List<UVCoord>(sm.uvs); | 214 | int imageX, imageY = 0; |
482 | } | 215 | |
483 | 216 | int rowNdx, colNdx; | |
484 | private void calcVertexNormals(SculptType sculptType, int xSize, int ySize) | 217 | |
485 | { // compute vertex normals by summing all the surface normals of all the triangles sharing | 218 | for (rowNdx = 0; rowNdx < numRows; rowNdx++) |
486 | // each vertex and then normalizing | 219 | { |
487 | int numFaces = this.faces.Count; | 220 | List<Coord> row = new List<Coord>(numCols); |
488 | for (int i = 0; i < numFaces; i++) | 221 | for (colNdx = 0; colNdx < numCols; colNdx++) |
489 | { | 222 | { |
490 | Face face = this.faces[i]; | 223 | imageX = colNdx * scale; |
491 | Coord surfaceNormal = face.SurfaceNormal(this.coords); | 224 | int imageYStart = rowNdx * scale; |
492 | this.normals[face.n1] += surfaceNormal; | 225 | int imageYEnd = imageYStart + scale; |
493 | this.normals[face.n2] += surfaceNormal; | 226 | int imageXEnd = imageX + scale; |
494 | this.normals[face.n3] += surfaceNormal; | 227 | float rSum = 0.0f; |
495 | } | 228 | float gSum = 0.0f; |
496 | 229 | float bSum = 0.0f; | |
497 | int numNormals = this.normals.Count; | 230 | for (; imageX < imageXEnd; imageX++) |
498 | for (int i = 0; i < numNormals; i++) | 231 | { |
499 | this.normals[i] = this.normals[i].Normalize(); | 232 | for (imageY = imageYStart; imageY < imageYEnd; imageY++) |
500 | 233 | { | |
501 | if (sculptType != SculptType.plane) | 234 | Color c = bitmap.GetPixel(imageX, imageY); |
502 | { // blend the vertex normals at the cylinder seam | 235 | if (c.A != 255) |
503 | for (int y = 0; y < ySize; y++) | 236 | { |
504 | { | 237 | bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); |
505 | int rowOffset = y * xSize; | 238 | c = bitmap.GetPixel(imageX, imageY); |
506 | 239 | } | |
507 | this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); | 240 | rSum += c.R; |
508 | } | 241 | gSum += c.G; |
509 | } | 242 | bSum += c.B; |
510 | 243 | } | |
511 | foreach (Face face in this.faces) | 244 | } |
512 | { | 245 | if (mirror) |
513 | ViewerFace vf = new ViewerFace(0); | 246 | row.Add(new Coord(-(rSum * pixScale - 0.5f), gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); |
514 | vf.v1 = this.coords[face.v1]; | 247 | else |
515 | vf.v2 = this.coords[face.v2]; | 248 | row.Add(new Coord(rSum * pixScale - 0.5f, gSum * pixScale - 0.5f, bSum * pixScale - 0.5f)); |
516 | vf.v3 = this.coords[face.v3]; | 249 | |
517 | 250 | } | |
518 | vf.coordIndex1 = face.v1; | 251 | rows.Add(row); |
519 | vf.coordIndex2 = face.v2; | 252 | } |
520 | vf.coordIndex3 = face.v3; | 253 | return rows; |
521 | 254 | } | |
522 | vf.n1 = this.normals[face.n1]; | 255 | |
523 | vf.n2 = this.normals[face.n2]; | 256 | private List<List<Coord>> bitmap2CoordsSampled(Bitmap bitmap, int scale, bool mirror) |
524 | vf.n3 = this.normals[face.n3]; | 257 | { |
525 | 258 | int numRows = bitmap.Height / scale; | |
526 | vf.uv1 = this.uvs[face.uv1]; | 259 | int numCols = bitmap.Width / scale; |
527 | vf.uv2 = this.uvs[face.uv2]; | 260 | List<List<Coord>> rows = new List<List<Coord>>(numRows); |
528 | vf.uv3 = this.uvs[face.uv3]; | 261 | |
529 | 262 | float pixScale = 1.0f / 256.0f; | |
530 | this.viewerFaces.Add(vf); | 263 | |
531 | } | 264 | int imageX, imageY = 0; |
532 | } | 265 | |
533 | 266 | int rowNdx, colNdx; | |
534 | /// <summary> | 267 | |
535 | /// Adds a value to each XYZ vertex coordinate in the mesh | 268 | for (rowNdx = 0; rowNdx <= numRows; rowNdx++) |
536 | /// </summary> | 269 | { |
537 | /// <param name="x"></param> | 270 | List<Coord> row = new List<Coord>(numCols); |
538 | /// <param name="y"></param> | 271 | imageY = rowNdx * scale; |
539 | /// <param name="z"></param> | 272 | if (rowNdx == numRows) imageY--; |
540 | public void AddPos(float x, float y, float z) | 273 | for (colNdx = 0; colNdx <= numCols; colNdx++) |
541 | { | 274 | { |
542 | int i; | 275 | imageX = colNdx * scale; |
543 | int numVerts = this.coords.Count; | 276 | if (colNdx == numCols) imageX--; |
544 | Coord vert; | 277 | |
545 | 278 | Color c = bitmap.GetPixel(imageX, imageY); | |
546 | for (i = 0; i < numVerts; i++) | 279 | if (c.A != 255) |
547 | { | 280 | { |
548 | vert = this.coords[i]; | 281 | bitmap.SetPixel(imageX, imageY, Color.FromArgb(255, c.R, c.G, c.B)); |
549 | vert.X += x; | 282 | c = bitmap.GetPixel(imageX, imageY); |
550 | vert.Y += y; | 283 | } |
551 | vert.Z += z; | 284 | |
552 | this.coords[i] = vert; | 285 | if (mirror) |
553 | } | 286 | row.Add(new Coord(-(c.R * pixScale - 0.5f), c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); |
554 | 287 | else | |
555 | if (this.viewerFaces != null) | 288 | row.Add(new Coord(c.R * pixScale - 0.5f, c.G * pixScale - 0.5f, c.B * pixScale - 0.5f)); |
556 | { | 289 | |
557 | int numViewerFaces = this.viewerFaces.Count; | 290 | } |
558 | 291 | rows.Add(row); | |
559 | for (i = 0; i < numViewerFaces; i++) | 292 | } |
560 | { | 293 | return rows; |
561 | ViewerFace v = this.viewerFaces[i]; | 294 | } |
562 | v.AddPos(x, y, z); | 295 | |
563 | this.viewerFaces[i] = v; | 296 | |
564 | } | 297 | void _SculptMesh(Bitmap sculptBitmap, SculptType sculptType, int lod, bool viewerMode, bool mirror, bool invert) |
565 | } | 298 | { |
566 | } | 299 | _SculptMesh(new SculptMap(sculptBitmap, lod).ToRows(mirror), sculptType, viewerMode, mirror, invert); |
567 | 300 | } | |
568 | /// <summary> | 301 | #endif |
569 | /// Rotates the mesh | 302 | |
570 | /// </summary> | 303 | void _SculptMesh(List<List<Coord>> rows, SculptType sculptType, bool viewerMode, bool mirror, bool invert) |
571 | /// <param name="q"></param> | 304 | { |
572 | public void AddRot(Quat q) | 305 | coords = new List<Coord>(); |
573 | { | 306 | faces = new List<Face>(); |
574 | int i; | 307 | normals = new List<Coord>(); |
575 | int numVerts = this.coords.Count; | 308 | uvs = new List<UVCoord>(); |
576 | 309 | ||
577 | for (i = 0; i < numVerts; i++) | 310 | sculptType = (SculptType)(((int)sculptType) & 0x07); |
578 | this.coords[i] *= q; | 311 | |
579 | 312 | if (mirror) | |
580 | int numNormals = this.normals.Count; | 313 | if (sculptType == SculptType.plane) |
581 | for (i = 0; i < numNormals; i++) | 314 | invert = !invert; |
582 | this.normals[i] *= q; | 315 | |
583 | 316 | viewerFaces = new List<ViewerFace>(); | |
584 | if (this.viewerFaces != null) | 317 | |
585 | { | 318 | int width = rows[0].Count; |
586 | int numViewerFaces = this.viewerFaces.Count; | 319 | |
587 | 320 | int p1, p2, p3, p4; | |
588 | for (i = 0; i < numViewerFaces; i++) | 321 | |
589 | { | 322 | int imageX, imageY; |
590 | ViewerFace v = this.viewerFaces[i]; | 323 | |
591 | v.v1 *= q; | 324 | if (sculptType != SculptType.plane) |
592 | v.v2 *= q; | 325 | { |
593 | v.v3 *= q; | 326 | if (rows.Count % 2 == 0) |
594 | 327 | { | |
595 | v.n1 *= q; | 328 | for (int rowNdx = 0; rowNdx < rows.Count; rowNdx++) |
596 | v.n2 *= q; | 329 | rows[rowNdx].Add(rows[rowNdx][0]); |
597 | v.n3 *= q; | 330 | } |
598 | 331 | else | |
599 | this.viewerFaces[i] = v; | 332 | { |
600 | } | 333 | int lastIndex = rows[0].Count - 1; |
601 | } | 334 | |
602 | } | 335 | for (int i = 0; i < rows.Count; i++) |
603 | 336 | rows[i][0] = rows[i][lastIndex]; | |
604 | public void Scale(float x, float y, float z) | 337 | } |
605 | { | 338 | } |
606 | int i; | 339 | |
607 | int numVerts = this.coords.Count; | 340 | Coord topPole = rows[0][width / 2]; |
608 | 341 | Coord bottomPole = rows[rows.Count - 1][width / 2]; | |
609 | Coord m = new Coord(x, y, z); | 342 | |
610 | for (i = 0; i < numVerts; i++) | 343 | if (sculptType == SculptType.sphere) |
611 | this.coords[i] *= m; | 344 | { |
612 | 345 | if (rows.Count % 2 == 0) | |
613 | if (this.viewerFaces != null) | 346 | { |
614 | { | 347 | int count = rows[0].Count; |
615 | int numViewerFaces = this.viewerFaces.Count; | 348 | List<Coord> topPoleRow = new List<Coord>(count); |
616 | for (i = 0; i < numViewerFaces; i++) | 349 | List<Coord> bottomPoleRow = new List<Coord>(count); |
617 | { | 350 | |
618 | ViewerFace v = this.viewerFaces[i]; | 351 | for (int i = 0; i < count; i++) |
619 | v.v1 *= m; | 352 | { |
620 | v.v2 *= m; | 353 | topPoleRow.Add(topPole); |
621 | v.v3 *= m; | 354 | bottomPoleRow.Add(bottomPole); |
622 | this.viewerFaces[i] = v; | 355 | } |
623 | } | 356 | rows.Insert(0, topPoleRow); |
624 | } | 357 | rows.Add(bottomPoleRow); |
625 | } | 358 | } |
626 | 359 | else | |
627 | public void DumpRaw(String path, String name, String title) | 360 | { |
628 | { | 361 | int count = rows[0].Count; |
629 | if (path == null) | 362 | |
630 | return; | 363 | List<Coord> topPoleRow = rows[0]; |
631 | String fileName = name + "_" + title + ".raw"; | 364 | List<Coord> bottomPoleRow = rows[rows.Count - 1]; |
632 | String completePath = System.IO.Path.Combine(path, fileName); | 365 | |
633 | StreamWriter sw = new StreamWriter(completePath); | 366 | for (int i = 0; i < count; i++) |
634 | 367 | { | |
635 | for (int i = 0; i < this.faces.Count; i++) | 368 | topPoleRow[i] = topPole; |
636 | { | 369 | bottomPoleRow[i] = bottomPole; |
637 | string s = this.coords[this.faces[i].v1].ToString(); | 370 | } |
638 | s += " " + this.coords[this.faces[i].v2].ToString(); | 371 | } |
639 | s += " " + this.coords[this.faces[i].v3].ToString(); | 372 | } |
640 | 373 | ||
641 | sw.WriteLine(s); | 374 | if (sculptType == SculptType.torus) |
642 | } | 375 | rows.Add(rows[0]); |
643 | 376 | ||
644 | sw.Close(); | 377 | int coordsDown = rows.Count; |
645 | } | 378 | int coordsAcross = rows[0].Count; |
646 | } | 379 | int lastColumn = coordsAcross - 1; |
647 | } | 380 | |
381 | float widthUnit = 1.0f / (coordsAcross - 1); | ||
382 | float heightUnit = 1.0f / (coordsDown - 1); | ||
383 | |||
384 | for (imageY = 0; imageY < coordsDown; imageY++) | ||
385 | { | ||
386 | int rowOffset = imageY * coordsAcross; | ||
387 | |||
388 | for (imageX = 0; imageX < coordsAcross; imageX++) | ||
389 | { | ||
390 | /* | ||
391 | * p1-----p2 | ||
392 | * | \ f2 | | ||
393 | * | \ | | ||
394 | * | f1 \| | ||
395 | * p3-----p4 | ||
396 | */ | ||
397 | |||
398 | p4 = rowOffset + imageX; | ||
399 | p3 = p4 - 1; | ||
400 | |||
401 | p2 = p4 - coordsAcross; | ||
402 | p1 = p3 - coordsAcross; | ||
403 | |||
404 | this.coords.Add(rows[imageY][imageX]); | ||
405 | if (viewerMode) | ||
406 | { | ||
407 | this.normals.Add(new Coord()); | ||
408 | this.uvs.Add(new UVCoord(widthUnit * imageX, heightUnit * imageY)); | ||
409 | } | ||
410 | |||
411 | if (imageY > 0 && imageX > 0) | ||
412 | { | ||
413 | Face f1, f2; | ||
414 | |||
415 | if (viewerMode) | ||
416 | { | ||
417 | if (invert) | ||
418 | { | ||
419 | f1 = new Face(p1, p4, p3, p1, p4, p3); | ||
420 | f1.uv1 = p1; | ||
421 | f1.uv2 = p4; | ||
422 | f1.uv3 = p3; | ||
423 | |||
424 | f2 = new Face(p1, p2, p4, p1, p2, p4); | ||
425 | f2.uv1 = p1; | ||
426 | f2.uv2 = p2; | ||
427 | f2.uv3 = p4; | ||
428 | } | ||
429 | else | ||
430 | { | ||
431 | f1 = new Face(p1, p3, p4, p1, p3, p4); | ||
432 | f1.uv1 = p1; | ||
433 | f1.uv2 = p3; | ||
434 | f1.uv3 = p4; | ||
435 | |||
436 | f2 = new Face(p1, p4, p2, p1, p4, p2); | ||
437 | f2.uv1 = p1; | ||
438 | f2.uv2 = p4; | ||
439 | f2.uv3 = p2; | ||
440 | } | ||
441 | } | ||
442 | else | ||
443 | { | ||
444 | if (invert) | ||
445 | { | ||
446 | f1 = new Face(p1, p4, p3); | ||
447 | f2 = new Face(p1, p2, p4); | ||
448 | } | ||
449 | else | ||
450 | { | ||
451 | f1 = new Face(p1, p3, p4); | ||
452 | f2 = new Face(p1, p4, p2); | ||
453 | } | ||
454 | } | ||
455 | |||
456 | this.faces.Add(f1); | ||
457 | this.faces.Add(f2); | ||
458 | } | ||
459 | } | ||
460 | } | ||
461 | |||
462 | if (viewerMode) | ||
463 | calcVertexNormals(sculptType, coordsAcross, coordsDown); | ||
464 | } | ||
465 | |||
466 | /// <summary> | ||
467 | /// Duplicates a SculptMesh object. All object properties are copied by value, including lists. | ||
468 | /// </summary> | ||
469 | /// <returns></returns> | ||
470 | public SculptMesh Copy() | ||
471 | { | ||
472 | return new SculptMesh(this); | ||
473 | } | ||
474 | |||
475 | public SculptMesh(SculptMesh sm) | ||
476 | { | ||
477 | coords = new List<Coord>(sm.coords); | ||
478 | faces = new List<Face>(sm.faces); | ||
479 | viewerFaces = new List<ViewerFace>(sm.viewerFaces); | ||
480 | normals = new List<Coord>(sm.normals); | ||
481 | uvs = new List<UVCoord>(sm.uvs); | ||
482 | } | ||
483 | |||
484 | private void calcVertexNormals(SculptType sculptType, int xSize, int ySize) | ||
485 | { // compute vertex normals by summing all the surface normals of all the triangles sharing | ||
486 | // each vertex and then normalizing | ||
487 | int numFaces = this.faces.Count; | ||
488 | for (int i = 0; i < numFaces; i++) | ||
489 | { | ||
490 | Face face = this.faces[i]; | ||
491 | Coord surfaceNormal = face.SurfaceNormal(this.coords); | ||
492 | this.normals[face.n1] += surfaceNormal; | ||
493 | this.normals[face.n2] += surfaceNormal; | ||
494 | this.normals[face.n3] += surfaceNormal; | ||
495 | } | ||
496 | |||
497 | int numNormals = this.normals.Count; | ||
498 | for (int i = 0; i < numNormals; i++) | ||
499 | this.normals[i] = this.normals[i].Normalize(); | ||
500 | |||
501 | if (sculptType != SculptType.plane) | ||
502 | { // blend the vertex normals at the cylinder seam | ||
503 | for (int y = 0; y < ySize; y++) | ||
504 | { | ||
505 | int rowOffset = y * xSize; | ||
506 | |||
507 | this.normals[rowOffset] = this.normals[rowOffset + xSize - 1] = (this.normals[rowOffset] + this.normals[rowOffset + xSize - 1]).Normalize(); | ||
508 | } | ||
509 | } | ||
510 | |||
511 | foreach (Face face in this.faces) | ||
512 | { | ||
513 | ViewerFace vf = new ViewerFace(0); | ||
514 | vf.v1 = this.coords[face.v1]; | ||
515 | vf.v2 = this.coords[face.v2]; | ||
516 | vf.v3 = this.coords[face.v3]; | ||
517 | |||
518 | vf.coordIndex1 = face.v1; | ||
519 | vf.coordIndex2 = face.v2; | ||
520 | vf.coordIndex3 = face.v3; | ||
521 | |||
522 | vf.n1 = this.normals[face.n1]; | ||
523 | vf.n2 = this.normals[face.n2]; | ||
524 | vf.n3 = this.normals[face.n3]; | ||
525 | |||
526 | vf.uv1 = this.uvs[face.uv1]; | ||
527 | vf.uv2 = this.uvs[face.uv2]; | ||
528 | vf.uv3 = this.uvs[face.uv3]; | ||
529 | |||
530 | this.viewerFaces.Add(vf); | ||
531 | } | ||
532 | } | ||
533 | |||
534 | /// <summary> | ||
535 | /// Adds a value to each XYZ vertex coordinate in the mesh | ||
536 | /// </summary> | ||
537 | /// <param name="x"></param> | ||
538 | /// <param name="y"></param> | ||
539 | /// <param name="z"></param> | ||
540 | public void AddPos(float x, float y, float z) | ||
541 | { | ||
542 | int i; | ||
543 | int numVerts = this.coords.Count; | ||
544 | Coord vert; | ||
545 | |||
546 | for (i = 0; i < numVerts; i++) | ||
547 | { | ||
548 | vert = this.coords[i]; | ||
549 | vert.X += x; | ||
550 | vert.Y += y; | ||
551 | vert.Z += z; | ||
552 | this.coords[i] = vert; | ||
553 | } | ||
554 | |||
555 | if (this.viewerFaces != null) | ||
556 | { | ||
557 | int numViewerFaces = this.viewerFaces.Count; | ||
558 | |||
559 | for (i = 0; i < numViewerFaces; i++) | ||
560 | { | ||
561 | ViewerFace v = this.viewerFaces[i]; | ||
562 | v.AddPos(x, y, z); | ||
563 | this.viewerFaces[i] = v; | ||
564 | } | ||
565 | } | ||
566 | } | ||
567 | |||
568 | /// <summary> | ||
569 | /// Rotates the mesh | ||
570 | /// </summary> | ||
571 | /// <param name="q"></param> | ||
572 | public void AddRot(Quat q) | ||
573 | { | ||
574 | int i; | ||
575 | int numVerts = this.coords.Count; | ||
576 | |||
577 | for (i = 0; i < numVerts; i++) | ||
578 | this.coords[i] *= q; | ||
579 | |||
580 | int numNormals = this.normals.Count; | ||
581 | for (i = 0; i < numNormals; i++) | ||
582 | this.normals[i] *= q; | ||
583 | |||
584 | if (this.viewerFaces != null) | ||
585 | { | ||
586 | int numViewerFaces = this.viewerFaces.Count; | ||
587 | |||
588 | for (i = 0; i < numViewerFaces; i++) | ||
589 | { | ||
590 | ViewerFace v = this.viewerFaces[i]; | ||
591 | v.v1 *= q; | ||
592 | v.v2 *= q; | ||
593 | v.v3 *= q; | ||
594 | |||
595 | v.n1 *= q; | ||
596 | v.n2 *= q; | ||
597 | v.n3 *= q; | ||
598 | |||
599 | this.viewerFaces[i] = v; | ||
600 | } | ||
601 | } | ||
602 | } | ||
603 | |||
604 | public void Scale(float x, float y, float z) | ||
605 | { | ||
606 | int i; | ||
607 | int numVerts = this.coords.Count; | ||
608 | |||
609 | Coord m = new Coord(x, y, z); | ||
610 | for (i = 0; i < numVerts; i++) | ||
611 | this.coords[i] *= m; | ||
612 | |||
613 | if (this.viewerFaces != null) | ||
614 | { | ||
615 | int numViewerFaces = this.viewerFaces.Count; | ||
616 | for (i = 0; i < numViewerFaces; i++) | ||
617 | { | ||
618 | ViewerFace v = this.viewerFaces[i]; | ||
619 | v.v1 *= m; | ||
620 | v.v2 *= m; | ||
621 | v.v3 *= m; | ||
622 | this.viewerFaces[i] = v; | ||
623 | } | ||
624 | } | ||
625 | } | ||
626 | |||
627 | public void DumpRaw(String path, String name, String title) | ||
628 | { | ||
629 | if (path == null) | ||
630 | return; | ||
631 | String fileName = name + "_" + title + ".raw"; | ||
632 | String completePath = System.IO.Path.Combine(path, fileName); | ||
633 | StreamWriter sw = new StreamWriter(completePath); | ||
634 | |||
635 | for (int i = 0; i < this.faces.Count; i++) | ||
636 | { | ||
637 | string s = this.coords[this.faces[i].v1].ToString(); | ||
638 | s += " " + this.coords[this.faces[i].v2].ToString(); | ||
639 | s += " " + this.coords[this.faces[i].v3].ToString(); | ||
640 | |||
641 | sw.WriteLine(s); | ||
642 | } | ||
643 | |||
644 | sw.Close(); | ||
645 | } | ||
646 | } | ||
647 | } | ||
diff --git a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs index 4ebf933..3104917 100644 --- a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs | |||
@@ -90,8 +90,6 @@ namespace OpenSim.Server.Handlers.Presence | |||
90 | return GetAgent(request); | 90 | return GetAgent(request); |
91 | case "getagents": | 91 | case "getagents": |
92 | return GetAgents(request); | 92 | return GetAgents(request); |
93 | case "sethome": | ||
94 | return SetHome(request); | ||
95 | } | 93 | } |
96 | m_log.DebugFormat("[PRESENCE HANDLER]: unknown method request: {0}", method); | 94 | m_log.DebugFormat("[PRESENCE HANDLER]: unknown method request: {0}", method); |
97 | } | 95 | } |
@@ -140,12 +138,7 @@ namespace OpenSim.Server.Handlers.Presence | |||
140 | if (!UUID.TryParse(request["SessionID"].ToString(), out session)) | 138 | if (!UUID.TryParse(request["SessionID"].ToString(), out session)) |
141 | return FailureResult(); | 139 | return FailureResult(); |
142 | 140 | ||
143 | if (request.ContainsKey("Position") && request["Position"] != null) | 141 | if (m_PresenceService.LogoutAgent(session)) |
144 | Vector3.TryParse(request["Position"].ToString(), out position); | ||
145 | if (request.ContainsKey("LookAt") && request["Position"] != null) | ||
146 | Vector3.TryParse(request["LookAt"].ToString(), out lookat); | ||
147 | |||
148 | if (m_PresenceService.LogoutAgent(session, position, lookat)) | ||
149 | return SuccessResult(); | 142 | return SuccessResult(); |
150 | 143 | ||
151 | return FailureResult(); | 144 | return FailureResult(); |
@@ -171,8 +164,6 @@ namespace OpenSim.Server.Handlers.Presence | |||
171 | { | 164 | { |
172 | UUID session = UUID.Zero; | 165 | UUID session = UUID.Zero; |
173 | UUID region = UUID.Zero; | 166 | UUID region = UUID.Zero; |
174 | Vector3 position = new Vector3(128, 128, 70); | ||
175 | Vector3 look = Vector3.Zero; | ||
176 | 167 | ||
177 | if (!request.ContainsKey("SessionID") || !request.ContainsKey("RegionID")) | 168 | if (!request.ContainsKey("SessionID") || !request.ContainsKey("RegionID")) |
178 | return FailureResult(); | 169 | return FailureResult(); |
@@ -183,13 +174,7 @@ namespace OpenSim.Server.Handlers.Presence | |||
183 | if (!UUID.TryParse(request["RegionID"].ToString(), out region)) | 174 | if (!UUID.TryParse(request["RegionID"].ToString(), out region)) |
184 | return FailureResult(); | 175 | return FailureResult(); |
185 | 176 | ||
186 | if (request.ContainsKey("position")) | 177 | if (m_PresenceService.ReportAgent(session, region)) |
187 | Vector3.TryParse(request["position"].ToString(), out position); | ||
188 | |||
189 | if (request.ContainsKey("lookAt")) | ||
190 | Vector3.TryParse(request["lookAt"].ToString(), out look); | ||
191 | |||
192 | if (m_PresenceService.ReportAgent(session, region, position, look)) | ||
193 | { | 178 | { |
194 | return SuccessResult(); | 179 | return SuccessResult(); |
195 | } | 180 | } |
@@ -318,31 +303,5 @@ namespace OpenSim.Server.Handlers.Presence | |||
318 | return ms.ToArray(); | 303 | return ms.ToArray(); |
319 | } | 304 | } |
320 | 305 | ||
321 | byte[] SetHome(Dictionary<string, object> request) | ||
322 | { | ||
323 | UUID region = UUID.Zero; | ||
324 | Vector3 position = new Vector3(128, 128, 70); | ||
325 | Vector3 look = Vector3.Zero; | ||
326 | |||
327 | if (!request.ContainsKey("UserID") || !request.ContainsKey("RegionID")) | ||
328 | return FailureResult(); | ||
329 | |||
330 | string user = request["UserID"].ToString(); | ||
331 | |||
332 | if (!UUID.TryParse(request["RegionID"].ToString(), out region)) | ||
333 | return FailureResult(); | ||
334 | |||
335 | if (request.ContainsKey("position")) | ||
336 | Vector3.TryParse(request["position"].ToString(), out position); | ||
337 | |||
338 | if (request.ContainsKey("lookAt")) | ||
339 | Vector3.TryParse(request["lookAt"].ToString(), out look); | ||
340 | |||
341 | if (m_PresenceService.SetHomeLocation(user, region, position, look)) | ||
342 | return SuccessResult(); | ||
343 | |||
344 | return FailureResult(); | ||
345 | } | ||
346 | |||
347 | } | 306 | } |
348 | } | 307 | } |
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs index 0e85067..b4500a5 100644 --- a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs +++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs | |||
@@ -25,14 +25,206 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using log4net; | ||
28 | using System; | 29 | using System; |
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Reflection; | ||
33 | using Nini.Config; | ||
34 | using OpenSim.Framework; | ||
35 | using OpenSim.Framework.Communications; | ||
36 | using OpenSim.Framework.Servers.HttpServer; | ||
37 | using OpenSim.Services.Interfaces; | ||
38 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | ||
39 | using OpenSim.Server.Base; | ||
40 | using OpenMetaverse; | ||
29 | 41 | ||
30 | namespace OpenSim.Services.Connectors | 42 | namespace OpenSim.Services.Connectors |
31 | { | 43 | { |
32 | public class GridUserServiceConnector | 44 | public class GridUserServicesConnector : IGridUserService |
33 | { | 45 | { |
34 | public GridUserServiceConnector() | 46 | private static readonly ILog m_log = |
47 | LogManager.GetLogger( | ||
48 | MethodBase.GetCurrentMethod().DeclaringType); | ||
49 | |||
50 | private string m_ServerURI = String.Empty; | ||
51 | |||
52 | public GridUserServicesConnector() | ||
53 | { | ||
54 | } | ||
55 | |||
56 | public GridUserServicesConnector(string serverURI) | ||
57 | { | ||
58 | m_ServerURI = serverURI.TrimEnd('/'); | ||
59 | } | ||
60 | |||
61 | public GridUserServicesConnector(IConfigSource source) | ||
62 | { | ||
63 | Initialise(source); | ||
64 | } | ||
65 | |||
66 | public virtual void Initialise(IConfigSource source) | ||
67 | { | ||
68 | IConfig gridConfig = source.Configs["GridUserService"]; | ||
69 | if (gridConfig == null) | ||
70 | { | ||
71 | m_log.Error("[GRID USER CONNECTOR]: GridUserService missing from OpenSim.ini"); | ||
72 | throw new Exception("GridUser connector init error"); | ||
73 | } | ||
74 | |||
75 | string serviceURI = gridConfig.GetString("GridUserServerURI", | ||
76 | String.Empty); | ||
77 | |||
78 | if (serviceURI == String.Empty) | ||
79 | { | ||
80 | m_log.Error("[GRID USER CONNECTOR]: No Server URI named in section GridUserService"); | ||
81 | throw new Exception("GridUser connector init error"); | ||
82 | } | ||
83 | m_ServerURI = serviceURI; | ||
84 | } | ||
85 | |||
86 | |||
87 | #region IPresenceService | ||
88 | |||
89 | |||
90 | public GridUserInfo LoggedIn(string userID) | ||
91 | { | ||
92 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||
93 | //sendData["SCOPEID"] = scopeID.ToString(); | ||
94 | sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); | ||
95 | sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); | ||
96 | sendData["METHOD"] = "loggedin"; | ||
97 | |||
98 | sendData["UserID"] = userID; | ||
99 | |||
100 | return Get(sendData); | ||
101 | |||
102 | } | ||
103 | |||
104 | public bool LoggedOut(string userID, UUID region, Vector3 position, Vector3 lookat) | ||
105 | { | ||
106 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||
107 | //sendData["SCOPEID"] = scopeID.ToString(); | ||
108 | sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); | ||
109 | sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); | ||
110 | sendData["METHOD"] = "loggedout"; | ||
111 | |||
112 | return Set(sendData, userID, region, position, lookat); | ||
113 | } | ||
114 | |||
115 | public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
116 | { | ||
117 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||
118 | //sendData["SCOPEID"] = scopeID.ToString(); | ||
119 | sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); | ||
120 | sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); | ||
121 | sendData["METHOD"] = "sethome"; | ||
122 | |||
123 | return Set(sendData, userID, regionID, position, lookAt); | ||
124 | } | ||
125 | |||
126 | public bool SetLastPosition(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
127 | { | ||
128 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||
129 | //sendData["SCOPEID"] = scopeID.ToString(); | ||
130 | sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); | ||
131 | sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); | ||
132 | sendData["METHOD"] = "setposition"; | ||
133 | |||
134 | return Set(sendData, userID, regionID, position, lookAt); | ||
135 | } | ||
136 | |||
137 | public GridUserInfo GetGridUserInfo(string userID) | ||
138 | { | ||
139 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||
140 | //sendData["SCOPEID"] = scopeID.ToString(); | ||
141 | sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); | ||
142 | sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); | ||
143 | sendData["METHOD"] = "getgriduserinfo"; | ||
144 | |||
145 | sendData["UserID"] = userID; | ||
146 | |||
147 | return Get(sendData); | ||
148 | } | ||
149 | |||
150 | #endregion | ||
151 | |||
152 | protected bool Set(Dictionary<string, object> sendData, string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
153 | { | ||
154 | sendData["UserID"] = userID; | ||
155 | sendData["RegionID"] = regionID.ToString(); | ||
156 | sendData["Position"] = position.ToString(); | ||
157 | sendData["LookAt"] = lookAt.ToString(); | ||
158 | |||
159 | string reqString = ServerUtils.BuildQueryString(sendData); | ||
160 | // m_log.DebugFormat("[GRID USER CONNECTOR]: queryString = {0}", reqString); | ||
161 | try | ||
162 | { | ||
163 | string reply = SynchronousRestFormsRequester.MakeRequest("POST", | ||
164 | m_ServerURI + "/griduser", | ||
165 | reqString); | ||
166 | if (reply != string.Empty) | ||
167 | { | ||
168 | Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply); | ||
169 | |||
170 | if (replyData.ContainsKey("result")) | ||
171 | { | ||
172 | if (replyData["result"].ToString().ToLower() == "success") | ||
173 | return true; | ||
174 | else | ||
175 | return false; | ||
176 | } | ||
177 | else | ||
178 | m_log.DebugFormat("[GRID USER CONNECTOR]: SetPosition reply data does not contain result field"); | ||
179 | |||
180 | } | ||
181 | else | ||
182 | m_log.DebugFormat("[GRID USER CONNECTOR]: SetPosition received empty reply"); | ||
183 | } | ||
184 | catch (Exception e) | ||
185 | { | ||
186 | m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server: {0}", e.Message); | ||
187 | } | ||
188 | |||
189 | return false; | ||
190 | } | ||
191 | |||
192 | protected GridUserInfo Get(Dictionary<string, object> sendData) | ||
35 | { | 193 | { |
194 | string reqString = ServerUtils.BuildQueryString(sendData); | ||
195 | // m_log.DebugFormat("[GRID USER CONNECTOR]: queryString = {0}", reqString); | ||
196 | try | ||
197 | { | ||
198 | string reply = SynchronousRestFormsRequester.MakeRequest("POST", | ||
199 | m_ServerURI + "/griduser", | ||
200 | reqString); | ||
201 | if (reply != string.Empty) | ||
202 | { | ||
203 | Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply); | ||
204 | GridUserInfo guinfo = null; | ||
205 | |||
206 | if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null)) | ||
207 | { | ||
208 | if (replyData["result"] is Dictionary<string, object>) | ||
209 | { | ||
210 | guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | return guinfo; | ||
215 | |||
216 | } | ||
217 | else | ||
218 | m_log.DebugFormat("[GRID USER CONNECTOR]: Loggedin received empty reply"); | ||
219 | } | ||
220 | catch (Exception e) | ||
221 | { | ||
222 | m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server: {0}", e.Message); | ||
223 | } | ||
224 | |||
225 | return null; | ||
226 | |||
36 | } | 227 | } |
228 | |||
37 | } | 229 | } |
38 | } | 230 | } |
diff --git a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs index 23621b7..41ebeaf 100644 --- a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs | |||
@@ -132,7 +132,7 @@ namespace OpenSim.Services.Connectors | |||
132 | 132 | ||
133 | } | 133 | } |
134 | 134 | ||
135 | public bool LogoutAgent(UUID sessionID, Vector3 position, Vector3 lookat) | 135 | public bool LogoutAgent(UUID sessionID) |
136 | { | 136 | { |
137 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | 137 | Dictionary<string, object> sendData = new Dictionary<string, object>(); |
138 | //sendData["SCOPEID"] = scopeID.ToString(); | 138 | //sendData["SCOPEID"] = scopeID.ToString(); |
@@ -141,8 +141,6 @@ namespace OpenSim.Services.Connectors | |||
141 | sendData["METHOD"] = "logout"; | 141 | sendData["METHOD"] = "logout"; |
142 | 142 | ||
143 | sendData["SessionID"] = sessionID.ToString(); | 143 | sendData["SessionID"] = sessionID.ToString(); |
144 | sendData["Position"] = position.ToString(); | ||
145 | sendData["LookAt"] = lookat.ToString(); | ||
146 | 144 | ||
147 | string reqString = ServerUtils.BuildQueryString(sendData); | 145 | string reqString = ServerUtils.BuildQueryString(sendData); |
148 | // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); | 146 | // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); |
@@ -220,7 +218,7 @@ namespace OpenSim.Services.Connectors | |||
220 | return false; | 218 | return false; |
221 | } | 219 | } |
222 | 220 | ||
223 | public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) | 221 | public bool ReportAgent(UUID sessionID, UUID regionID) |
224 | { | 222 | { |
225 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | 223 | Dictionary<string, object> sendData = new Dictionary<string, object>(); |
226 | //sendData["SCOPEID"] = scopeID.ToString(); | 224 | //sendData["SCOPEID"] = scopeID.ToString(); |
@@ -230,8 +228,6 @@ namespace OpenSim.Services.Connectors | |||
230 | 228 | ||
231 | sendData["SessionID"] = sessionID.ToString(); | 229 | sendData["SessionID"] = sessionID.ToString(); |
232 | sendData["RegionID"] = regionID.ToString(); | 230 | sendData["RegionID"] = regionID.ToString(); |
233 | sendData["position"] = position.ToString(); | ||
234 | sendData["lookAt"] = lookAt.ToString(); | ||
235 | 231 | ||
236 | string reqString = ServerUtils.BuildQueryString(sendData); | 232 | string reqString = ServerUtils.BuildQueryString(sendData); |
237 | // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); | 233 | // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); |
@@ -371,52 +367,6 @@ namespace OpenSim.Services.Connectors | |||
371 | } | 367 | } |
372 | 368 | ||
373 | 369 | ||
374 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
375 | { | ||
376 | Dictionary<string, object> sendData = new Dictionary<string, object>(); | ||
377 | //sendData["SCOPEID"] = scopeID.ToString(); | ||
378 | sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); | ||
379 | sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); | ||
380 | sendData["METHOD"] = "sethome"; | ||
381 | |||
382 | sendData["UserID"] = userID; | ||
383 | sendData["RegionID"] = regionID.ToString(); | ||
384 | sendData["position"] = position.ToString(); | ||
385 | sendData["lookAt"] = lookAt.ToString(); | ||
386 | |||
387 | string reqString = ServerUtils.BuildQueryString(sendData); | ||
388 | // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); | ||
389 | try | ||
390 | { | ||
391 | string reply = SynchronousRestFormsRequester.MakeRequest("POST", | ||
392 | m_ServerURI + "/presence", | ||
393 | reqString); | ||
394 | if (reply != string.Empty) | ||
395 | { | ||
396 | Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply); | ||
397 | |||
398 | if (replyData.ContainsKey("result")) | ||
399 | { | ||
400 | if (replyData["result"].ToString().ToLower() == "success") | ||
401 | return true; | ||
402 | else | ||
403 | return false; | ||
404 | } | ||
405 | else | ||
406 | m_log.DebugFormat("[PRESENCE CONNECTOR]: SetHomeLocation reply data does not contain result field"); | ||
407 | |||
408 | } | ||
409 | else | ||
410 | m_log.DebugFormat("[PRESENCE CONNECTOR]: SetHomeLocation received empty reply"); | ||
411 | } | ||
412 | catch (Exception e) | ||
413 | { | ||
414 | m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message); | ||
415 | } | ||
416 | |||
417 | return false; | ||
418 | } | ||
419 | |||
420 | #endregion | 370 | #endregion |
421 | 371 | ||
422 | } | 372 | } |
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index c324272..e48b7de 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs | |||
@@ -51,7 +51,7 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
51 | /// message routing) to the SimianGrid backend | 51 | /// message routing) to the SimianGrid backend |
52 | /// </summary> | 52 | /// </summary> |
53 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] | 53 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] |
54 | public class SimianPresenceServiceConnector : IPresenceService, ISharedRegionModule | 54 | public class SimianPresenceServiceConnector : IPresenceService, IGridUserService, ISharedRegionModule |
55 | { | 55 | { |
56 | private static readonly ILog m_log = | 56 | private static readonly ILog m_log = |
57 | LogManager.GetLogger( | 57 | LogManager.GetLogger( |
@@ -73,6 +73,7 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
73 | if (!String.IsNullOrEmpty(m_serverUrl)) | 73 | if (!String.IsNullOrEmpty(m_serverUrl)) |
74 | { | 74 | { |
75 | scene.RegisterModuleInterface<IPresenceService>(this); | 75 | scene.RegisterModuleInterface<IPresenceService>(this); |
76 | scene.RegisterModuleInterface<IGridUserService>(this); | ||
76 | 77 | ||
77 | scene.EventManager.OnMakeRootAgent += MakeRootAgentHandler; | 78 | scene.EventManager.OnMakeRootAgent += MakeRootAgentHandler; |
78 | scene.EventManager.OnNewClient += NewClientHandler; | 79 | scene.EventManager.OnNewClient += NewClientHandler; |
@@ -86,6 +87,7 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
86 | if (!String.IsNullOrEmpty(m_serverUrl)) | 87 | if (!String.IsNullOrEmpty(m_serverUrl)) |
87 | { | 88 | { |
88 | scene.UnregisterModuleInterface<IPresenceService>(this); | 89 | scene.UnregisterModuleInterface<IPresenceService>(this); |
90 | scene.UnregisterModuleInterface<IGridUserService>(this); | ||
89 | 91 | ||
90 | scene.EventManager.OnMakeRootAgent -= MakeRootAgentHandler; | 92 | scene.EventManager.OnMakeRootAgent -= MakeRootAgentHandler; |
91 | scene.EventManager.OnNewClient -= NewClientHandler; | 93 | scene.EventManager.OnNewClient -= NewClientHandler; |
@@ -151,7 +153,7 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
151 | return success; | 153 | return success; |
152 | } | 154 | } |
153 | 155 | ||
154 | public bool LogoutAgent(UUID sessionID, Vector3 position, Vector3 lookAt) | 156 | public bool LogoutAgent(UUID sessionID) |
155 | { | 157 | { |
156 | m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); | 158 | m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); |
157 | 159 | ||
@@ -189,7 +191,12 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
189 | return success; | 191 | return success; |
190 | } | 192 | } |
191 | 193 | ||
192 | public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) | 194 | public bool ReportAgent(UUID sessionID, UUID regionID) |
195 | { | ||
196 | return ReportAgent(sessionID, regionID, Vector3.Zero, Vector3.Zero); | ||
197 | } | ||
198 | |||
199 | protected bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
193 | { | 200 | { |
194 | //m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Updating session data for agent with sessionID " + sessionID); | 201 | //m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Updating session data for agent with sessionID " + sessionID); |
195 | 202 | ||
@@ -261,7 +268,23 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
261 | return presences.ToArray(); | 268 | return presences.ToArray(); |
262 | } | 269 | } |
263 | 270 | ||
264 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | 271 | #endregion IPresenceService |
272 | |||
273 | #region IGridUserService | ||
274 | |||
275 | public GridUserInfo LoggedIn(string userID) | ||
276 | { | ||
277 | // never implemented at the sim | ||
278 | return null; | ||
279 | } | ||
280 | |||
281 | public bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) | ||
282 | { | ||
283 | // Not needed for simian grid, event handler is doing it | ||
284 | return true; | ||
285 | } | ||
286 | |||
287 | public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
265 | { | 288 | { |
266 | m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID); | 289 | m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID); |
267 | 290 | ||
@@ -281,7 +304,35 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
281 | return success; | 304 | return success; |
282 | } | 305 | } |
283 | 306 | ||
284 | #endregion IPresenceService | 307 | public bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) |
308 | { | ||
309 | // Not needed for simian grid, presence detection is doing it | ||
310 | return true; | ||
311 | } | ||
312 | |||
313 | public GridUserInfo GetGridUserInfo(string user) | ||
314 | { | ||
315 | m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user); | ||
316 | |||
317 | UUID userID = new UUID(user); | ||
318 | m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); | ||
319 | |||
320 | NameValueCollection requestArgs = new NameValueCollection | ||
321 | { | ||
322 | { "RequestMethod", "GetUser" }, | ||
323 | { "UserID", userID.ToString() } | ||
324 | }; | ||
325 | |||
326 | OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs); | ||
327 | if (userResponse["Success"].AsBoolean()) | ||
328 | return ResponseToGridUserInfo(userResponse); | ||
329 | else | ||
330 | m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString()); | ||
331 | |||
332 | return null; | ||
333 | } | ||
334 | |||
335 | #endregion | ||
285 | 336 | ||
286 | #region Presence Detection | 337 | #region Presence Detection |
287 | 338 | ||
@@ -325,7 +376,7 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
325 | SetLastLocation(client.SessionId); | 376 | SetLastLocation(client.SessionId); |
326 | } | 377 | } |
327 | 378 | ||
328 | LogoutAgent(client.SessionId, Vector3.Zero, Vector3.UnitX); | 379 | LogoutAgent(client.SessionId); |
329 | } | 380 | } |
330 | } | 381 | } |
331 | 382 | ||
@@ -478,6 +529,31 @@ namespace OpenSim.Services.Connectors.SimianGrid | |||
478 | return info; | 529 | return info; |
479 | } | 530 | } |
480 | 531 | ||
532 | private GridUserInfo ResponseToGridUserInfo(OSDMap userResponse) | ||
533 | { | ||
534 | if (userResponse != null && userResponse["User"] is OSDMap) | ||
535 | { | ||
536 | |||
537 | GridUserInfo info = new GridUserInfo(); | ||
538 | |||
539 | info.Online = true; | ||
540 | info.UserID = userResponse["UserID"].AsUUID().ToString(); | ||
541 | info.LastRegionID = userResponse["SceneID"].AsUUID(); | ||
542 | info.LastPosition = userResponse["ScenePosition"].AsVector3(); | ||
543 | info.LastLookAt = userResponse["SceneLookAt"].AsVector3(); | ||
544 | |||
545 | OSDMap user = (OSDMap)userResponse["User"]; | ||
546 | |||
547 | info.Login = user["LastLoginDate"].AsDate(); | ||
548 | info.Logout = user["LastLogoutDate"].AsDate(); | ||
549 | DeserializeLocation(user["HomeLocation"].AsString(), out info.HomeRegionID, out info.HomePosition, out info.HomeLookAt); | ||
550 | |||
551 | return info; | ||
552 | } | ||
553 | |||
554 | return null; | ||
555 | } | ||
556 | |||
481 | private string SerializeLocation(UUID regionID, Vector3 position, Vector3 lookAt) | 557 | private string SerializeLocation(UUID regionID, Vector3 position, Vector3 lookAt) |
482 | { | 558 | { |
483 | return "{" + String.Format("\"SceneID\":\"{0}\",\"Position\":\"{1}\",\"LookAt\":\"{2}\"", regionID, position, lookAt) + "}"; | 559 | return "{" + String.Format("\"SceneID\":\"{0}\",\"Position\":\"{1}\",\"LookAt\":\"{2}\"", regionID, position, lookAt) + "}"; |
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 26f211b..3af7ef9 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs | |||
@@ -59,7 +59,7 @@ namespace OpenSim.Services.HypergridService | |||
59 | 59 | ||
60 | static bool m_Initialized = false; | 60 | static bool m_Initialized = false; |
61 | 61 | ||
62 | protected static IPresenceService m_PresenceService; | 62 | protected static IGridUserService m_GridUserService; |
63 | protected static IGridService m_GridService; | 63 | protected static IGridService m_GridService; |
64 | protected static GatekeeperServiceConnector m_GatekeeperConnector; | 64 | protected static GatekeeperServiceConnector m_GatekeeperConnector; |
65 | 65 | ||
@@ -74,14 +74,14 @@ namespace OpenSim.Services.HypergridService | |||
74 | throw new Exception(String.Format("No section UserAgentService in config file")); | 74 | throw new Exception(String.Format("No section UserAgentService in config file")); |
75 | 75 | ||
76 | string gridService = serverConfig.GetString("GridService", String.Empty); | 76 | string gridService = serverConfig.GetString("GridService", String.Empty); |
77 | string presenceService = serverConfig.GetString("PresenceService", String.Empty); | 77 | string gridUserService = serverConfig.GetString("GridUserService", String.Empty); |
78 | 78 | ||
79 | if (gridService == string.Empty || presenceService == string.Empty) | 79 | if (gridService == string.Empty || gridUserService == string.Empty) |
80 | throw new Exception(String.Format("Incomplete specifications, UserAgent Service cannot function.")); | 80 | throw new Exception(String.Format("Incomplete specifications, UserAgent Service cannot function.")); |
81 | 81 | ||
82 | Object[] args = new Object[] { config }; | 82 | Object[] args = new Object[] { config }; |
83 | m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); | 83 | m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); |
84 | m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); | 84 | m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); |
85 | m_GatekeeperConnector = new GatekeeperServiceConnector(); | 85 | m_GatekeeperConnector = new GatekeeperServiceConnector(); |
86 | 86 | ||
87 | m_Initialized = true; | 87 | m_Initialized = true; |
@@ -95,15 +95,14 @@ namespace OpenSim.Services.HypergridService | |||
95 | m_log.DebugFormat("[USER AGENT SERVICE]: Request to get home region of user {0}", userID); | 95 | m_log.DebugFormat("[USER AGENT SERVICE]: Request to get home region of user {0}", userID); |
96 | 96 | ||
97 | GridRegion home = null; | 97 | GridRegion home = null; |
98 | PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { userID.ToString() }); | 98 | GridUserInfo uinfo = m_GridUserService.GetGridUserInfo(userID.ToString()); |
99 | if (presences != null && presences.Length > 0) | 99 | if (uinfo != null) |
100 | { | 100 | { |
101 | UUID homeID = presences[0].HomeRegionID; | 101 | if (uinfo.HomeRegionID != UUID.Zero) |
102 | if (homeID != UUID.Zero) | ||
103 | { | 102 | { |
104 | home = m_GridService.GetRegionByUUID(UUID.Zero, homeID); | 103 | home = m_GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); |
105 | position = presences[0].HomePosition; | 104 | position = uinfo.HomePosition; |
106 | lookAt = presences[0].HomeLookAt; | 105 | lookAt = uinfo.HomeLookAt; |
107 | } | 106 | } |
108 | if (home == null) | 107 | if (home == null) |
109 | { | 108 | { |
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs index a7c2c6f..e629dff 100644 --- a/OpenSim/Services/Interfaces/IGridUserService.cs +++ b/OpenSim/Services/Interfaces/IGridUserService.cs | |||
@@ -37,39 +37,79 @@ namespace OpenSim.Services.Interfaces | |||
37 | public class GridUserInfo | 37 | public class GridUserInfo |
38 | { | 38 | { |
39 | public string UserID; | 39 | public string UserID; |
40 | |||
40 | public UUID HomeRegionID; | 41 | public UUID HomeRegionID; |
41 | public Vector3 HomePosition; | 42 | public Vector3 HomePosition; |
42 | public Vector3 HomeLookAt; | 43 | public Vector3 HomeLookAt; |
43 | 44 | ||
45 | public UUID LastRegionID; | ||
46 | public Vector3 LastPosition; | ||
47 | public Vector3 LastLookAt; | ||
48 | |||
49 | public bool Online; | ||
50 | public DateTime Login; | ||
51 | public DateTime Logout; | ||
52 | |||
44 | public GridUserInfo() {} | 53 | public GridUserInfo() {} |
45 | 54 | ||
46 | public GridUserInfo(Dictionary<string, object> kvp) | 55 | public GridUserInfo(Dictionary<string, object> kvp) |
47 | { | 56 | { |
48 | if (kvp.ContainsKey("UserID")) | 57 | if (kvp.ContainsKey("UserID")) |
49 | UserID = kvp["UserID"].ToString(); | 58 | UserID = kvp["UserID"].ToString(); |
59 | |||
50 | if (kvp.ContainsKey("HomeRegionID")) | 60 | if (kvp.ContainsKey("HomeRegionID")) |
51 | UUID.TryParse(kvp["HomeRegionID"].ToString(), out HomeRegionID); | 61 | UUID.TryParse(kvp["HomeRegionID"].ToString(), out HomeRegionID); |
52 | if (kvp.ContainsKey("HomePosition")) | 62 | if (kvp.ContainsKey("HomePosition")) |
53 | Vector3.TryParse(kvp["HomePosition"].ToString(), out HomePosition); | 63 | Vector3.TryParse(kvp["HomePosition"].ToString(), out HomePosition); |
54 | if (kvp.ContainsKey("HomeLookAt")) | 64 | if (kvp.ContainsKey("HomeLookAt")) |
55 | Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt); | 65 | Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt); |
66 | |||
67 | if (kvp.ContainsKey("LastRegionID")) | ||
68 | UUID.TryParse(kvp["LastRegionID"].ToString(), out HomeRegionID); | ||
69 | if (kvp.ContainsKey("LastPosition")) | ||
70 | Vector3.TryParse(kvp["LastPosition"].ToString(), out LastPosition); | ||
71 | if (kvp.ContainsKey("LastLookAt")) | ||
72 | Vector3.TryParse(kvp["LastLookAt"].ToString(), out LastLookAt); | ||
73 | |||
74 | if (kvp.ContainsKey("Login")) | ||
75 | DateTime.TryParse(kvp["Login"].ToString(), out Login); | ||
76 | if (kvp.ContainsKey("Logout")) | ||
77 | DateTime.TryParse(kvp["Logout"].ToString(), out Logout); | ||
78 | if (kvp.ContainsKey("Online")) | ||
79 | Boolean.TryParse(kvp["Online"].ToString(), out Online); | ||
80 | |||
56 | } | 81 | } |
57 | 82 | ||
58 | public Dictionary<string, object> ToKeyValuePairs() | 83 | public Dictionary<string, object> ToKeyValuePairs() |
59 | { | 84 | { |
60 | Dictionary<string, object> result = new Dictionary<string, object>(); | 85 | Dictionary<string, object> result = new Dictionary<string, object>(); |
61 | result["UserID"] = UserID; | 86 | result["UserID"] = UserID; |
87 | |||
62 | result["HomeRegionID"] = HomeRegionID.ToString(); | 88 | result["HomeRegionID"] = HomeRegionID.ToString(); |
63 | result["HomePosition"] = HomePosition.ToString(); | 89 | result["HomePosition"] = HomePosition.ToString(); |
64 | result["HomeLookAt"] = HomeLookAt.ToString(); | 90 | result["HomeLookAt"] = HomeLookAt.ToString(); |
65 | 91 | ||
92 | result["LastRegionID"] = LastRegionID.ToString(); | ||
93 | result["LastPosition"] = LastPosition.ToString(); | ||
94 | result["LastLookAt"] = LastLookAt.ToString(); | ||
95 | |||
96 | result["Online"] = Online.ToString(); | ||
97 | result["Login"] = Login.ToString(); | ||
98 | result["Logout"] = Logout.ToString(); | ||
99 | |||
100 | |||
66 | return result; | 101 | return result; |
67 | } | 102 | } |
68 | } | 103 | } |
69 | 104 | ||
70 | public interface IGridUserService | 105 | public interface IGridUserService |
71 | { | 106 | { |
107 | GridUserInfo LoggedIn(string userID); | ||
108 | bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt); | ||
109 | |||
110 | bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt); | ||
111 | bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt); | ||
112 | |||
72 | GridUserInfo GetGridUserInfo(string userID); | 113 | GridUserInfo GetGridUserInfo(string userID); |
73 | bool StoreGridUserInfo(GridUserInfo info); | ||
74 | } | 114 | } |
75 | } \ No newline at end of file | 115 | } \ No newline at end of file |
diff --git a/OpenSim/Services/Interfaces/IPresenceService.cs b/OpenSim/Services/Interfaces/IPresenceService.cs index b4c1859..9687d22 100644 --- a/OpenSim/Services/Interfaces/IPresenceService.cs +++ b/OpenSim/Services/Interfaces/IPresenceService.cs | |||
@@ -55,23 +55,10 @@ namespace OpenSim.Services.Interfaces | |||
55 | UserID = kvp["UserID"].ToString(); | 55 | UserID = kvp["UserID"].ToString(); |
56 | if (kvp.ContainsKey("RegionID")) | 56 | if (kvp.ContainsKey("RegionID")) |
57 | UUID.TryParse(kvp["RegionID"].ToString(), out RegionID); | 57 | UUID.TryParse(kvp["RegionID"].ToString(), out RegionID); |
58 | if (kvp.ContainsKey("login")) | ||
59 | DateTime.TryParse(kvp["login"].ToString(), out Login); | ||
60 | if (kvp.ContainsKey("logout")) | ||
61 | DateTime.TryParse(kvp["logout"].ToString(), out Logout); | ||
62 | if (kvp.ContainsKey("lookAt")) | 58 | if (kvp.ContainsKey("lookAt")) |
63 | Vector3.TryParse(kvp["lookAt"].ToString(), out LookAt); | 59 | Vector3.TryParse(kvp["lookAt"].ToString(), out LookAt); |
64 | if (kvp.ContainsKey("online")) | ||
65 | Boolean.TryParse(kvp["online"].ToString(), out Online); | ||
66 | if (kvp.ContainsKey("position")) | 60 | if (kvp.ContainsKey("position")) |
67 | Vector3.TryParse(kvp["position"].ToString(), out Position); | 61 | Vector3.TryParse(kvp["position"].ToString(), out Position); |
68 | if (kvp.ContainsKey("HomeRegionID")) | ||
69 | UUID.TryParse(kvp["HomeRegionID"].ToString(), out HomeRegionID); | ||
70 | if (kvp.ContainsKey("HomePosition")) | ||
71 | Vector3.TryParse(kvp["HomePosition"].ToString(), out HomePosition); | ||
72 | if (kvp.ContainsKey("HomeLookAt")) | ||
73 | Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt); | ||
74 | |||
75 | } | 62 | } |
76 | 63 | ||
77 | public Dictionary<string, object> ToKeyValuePairs() | 64 | public Dictionary<string, object> ToKeyValuePairs() |
@@ -79,14 +66,8 @@ namespace OpenSim.Services.Interfaces | |||
79 | Dictionary<string, object> result = new Dictionary<string, object>(); | 66 | Dictionary<string, object> result = new Dictionary<string, object>(); |
80 | result["UserID"] = UserID; | 67 | result["UserID"] = UserID; |
81 | result["RegionID"] = RegionID.ToString(); | 68 | result["RegionID"] = RegionID.ToString(); |
82 | result["online"] = Online.ToString(); | ||
83 | result["login"] = Login.ToString(); | ||
84 | result["logout"] = Logout.ToString(); | ||
85 | result["position"] = Position.ToString(); | 69 | result["position"] = Position.ToString(); |
86 | result["lookAt"] = LookAt.ToString(); | 70 | result["lookAt"] = LookAt.ToString(); |
87 | result["HomeRegionID"] = HomeRegionID.ToString(); | ||
88 | result["HomePosition"] = HomePosition.ToString(); | ||
89 | result["HomeLookAt"] = HomeLookAt.ToString(); | ||
90 | 71 | ||
91 | return result; | 72 | return result; |
92 | } | 73 | } |
@@ -115,11 +96,10 @@ namespace OpenSim.Services.Interfaces | |||
115 | public interface IPresenceService | 96 | public interface IPresenceService |
116 | { | 97 | { |
117 | bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID); | 98 | bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID); |
118 | bool LogoutAgent(UUID sessionID, Vector3 position, Vector3 lookAt); | 99 | bool LogoutAgent(UUID sessionID); |
119 | bool LogoutRegionAgents(UUID regionID); | 100 | bool LogoutRegionAgents(UUID regionID); |
120 | 101 | ||
121 | bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt); | 102 | bool ReportAgent(UUID sessionID, UUID regionID); |
122 | bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt); | ||
123 | 103 | ||
124 | PresenceInfo GetAgent(UUID sessionID); | 104 | PresenceInfo GetAgent(UUID sessionID); |
125 | PresenceInfo[] GetAgents(string[] userIDs); | 105 | PresenceInfo[] GetAgents(string[] userIDs); |
diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index ee30fa3..d1dcfe7 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs | |||
@@ -215,7 +215,7 @@ namespace OpenSim.Services.LLLoginService | |||
215 | SetDefaultValues(); | 215 | SetDefaultValues(); |
216 | } | 216 | } |
217 | 217 | ||
218 | public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, PresenceInfo pinfo, | 218 | public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, GridUserInfo pinfo, |
219 | GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService, | 219 | GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService, |
220 | string where, string startlocation, Vector3 position, Vector3 lookAt, string message, | 220 | string where, string startlocation, Vector3 position, Vector3 lookAt, string message, |
221 | GridRegion home, IPEndPoint clientIP) | 221 | GridRegion home, IPEndPoint clientIP) |
@@ -283,7 +283,7 @@ namespace OpenSim.Services.LLLoginService | |||
283 | } | 283 | } |
284 | } | 284 | } |
285 | 285 | ||
286 | private void FillOutHomeData(PresenceInfo pinfo, GridRegion home) | 286 | private void FillOutHomeData(GridUserInfo pinfo, GridRegion home) |
287 | { | 287 | { |
288 | int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize; | 288 | int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize; |
289 | if (home != null) | 289 | if (home != null) |
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index be90d38..f97222e 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs | |||
@@ -53,6 +53,7 @@ namespace OpenSim.Services.LLLoginService | |||
53 | private static bool Initialized = false; | 53 | private static bool Initialized = false; |
54 | 54 | ||
55 | protected IUserAccountService m_UserAccountService; | 55 | protected IUserAccountService m_UserAccountService; |
56 | protected IGridUserService m_GridUserService; | ||
56 | protected IAuthenticationService m_AuthenticationService; | 57 | protected IAuthenticationService m_AuthenticationService; |
57 | protected IInventoryService m_InventoryService; | 58 | protected IInventoryService m_InventoryService; |
58 | protected IGridService m_GridService; | 59 | protected IGridService m_GridService; |
@@ -82,6 +83,7 @@ namespace OpenSim.Services.LLLoginService | |||
82 | throw new Exception(String.Format("No section LoginService in config file")); | 83 | throw new Exception(String.Format("No section LoginService in config file")); |
83 | 84 | ||
84 | string accountService = m_LoginServerConfig.GetString("UserAccountService", String.Empty); | 85 | string accountService = m_LoginServerConfig.GetString("UserAccountService", String.Empty); |
86 | string gridUserService = m_LoginServerConfig.GetString("GridUserService", String.Empty); | ||
85 | string agentService = m_LoginServerConfig.GetString("UserAgentService", String.Empty); | 87 | string agentService = m_LoginServerConfig.GetString("UserAgentService", String.Empty); |
86 | string authService = m_LoginServerConfig.GetString("AuthenticationService", String.Empty); | 88 | string authService = m_LoginServerConfig.GetString("AuthenticationService", String.Empty); |
87 | string invService = m_LoginServerConfig.GetString("InventoryService", String.Empty); | 89 | string invService = m_LoginServerConfig.GetString("InventoryService", String.Empty); |
@@ -105,8 +107,10 @@ namespace OpenSim.Services.LLLoginService | |||
105 | 107 | ||
106 | Object[] args = new Object[] { config }; | 108 | Object[] args = new Object[] { config }; |
107 | m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); | 109 | m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); |
110 | m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); | ||
108 | m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args); | 111 | m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args); |
109 | m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args); | 112 | m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args); |
113 | |||
110 | if (gridService != string.Empty) | 114 | if (gridService != string.Empty) |
111 | m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); | 115 | m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); |
112 | if (presenceService != string.Empty) | 116 | if (presenceService != string.Empty) |
@@ -271,8 +275,6 @@ namespace OpenSim.Services.LLLoginService | |||
271 | // | 275 | // |
272 | // Login the presence | 276 | // Login the presence |
273 | // | 277 | // |
274 | PresenceInfo presence = null; | ||
275 | GridRegion home = null; | ||
276 | if (m_PresenceService != null) | 278 | if (m_PresenceService != null) |
277 | { | 279 | { |
278 | success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession); | 280 | success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession); |
@@ -281,28 +283,35 @@ namespace OpenSim.Services.LLLoginService | |||
281 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: could not login presence"); | 283 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: could not login presence"); |
282 | return LLFailedLoginResponse.GridProblem; | 284 | return LLFailedLoginResponse.GridProblem; |
283 | } | 285 | } |
284 | |||
285 | // Get the updated presence info | ||
286 | presence = m_PresenceService.GetAgent(session); | ||
287 | |||
288 | // Get the home region | ||
289 | if ((presence.HomeRegionID != UUID.Zero) && m_GridService != null) | ||
290 | { | ||
291 | home = m_GridService.GetRegionByUUID(scopeID, presence.HomeRegionID); | ||
292 | } | ||
293 | } | 286 | } |
294 | 287 | ||
295 | // | 288 | // |
289 | // Change Online status and get the home region | ||
290 | // | ||
291 | GridRegion home = null; | ||
292 | GridUserInfo guinfo = m_GridUserService.LoggedIn(account.PrincipalID.ToString()); | ||
293 | if (guinfo != null && (guinfo.HomeRegionID != UUID.Zero) && m_GridService != null) | ||
294 | { | ||
295 | home = m_GridService.GetRegionByUUID(scopeID, guinfo.HomeRegionID); | ||
296 | } | ||
297 | if (guinfo == null) | ||
298 | { | ||
299 | // something went wrong, make something up, so that we don't have to test this anywhere else | ||
300 | guinfo = new GridUserInfo(); | ||
301 | guinfo.LastPosition = guinfo.HomePosition = new Vector3(128, 128, 30); | ||
302 | } | ||
303 | |||
304 | // | ||
296 | // Find the destination region/grid | 305 | // Find the destination region/grid |
297 | // | 306 | // |
298 | string where = string.Empty; | 307 | string where = string.Empty; |
299 | Vector3 position = Vector3.Zero; | 308 | Vector3 position = Vector3.Zero; |
300 | Vector3 lookAt = Vector3.Zero; | 309 | Vector3 lookAt = Vector3.Zero; |
301 | GridRegion gatekeeper = null; | 310 | GridRegion gatekeeper = null; |
302 | GridRegion destination = FindDestination(account, scopeID, presence, session, startLocation, out gatekeeper, out where, out position, out lookAt); | 311 | GridRegion destination = FindDestination(account, scopeID, guinfo, session, startLocation, home, out gatekeeper, out where, out position, out lookAt); |
303 | if (destination == null) | 312 | if (destination == null) |
304 | { | 313 | { |
305 | m_PresenceService.LogoutAgent(session, presence.Position, presence.LookAt); | 314 | m_PresenceService.LogoutAgent(session); |
306 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: destination not found"); | 315 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: destination not found"); |
307 | return LLFailedLoginResponse.GridProblem; | 316 | return LLFailedLoginResponse.GridProblem; |
308 | } | 317 | } |
@@ -324,7 +333,7 @@ namespace OpenSim.Services.LLLoginService | |||
324 | 333 | ||
325 | if (aCircuit == null) | 334 | if (aCircuit == null) |
326 | { | 335 | { |
327 | m_PresenceService.LogoutAgent(session, presence.Position, presence.LookAt); | 336 | m_PresenceService.LogoutAgent(session); |
328 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: {0}", reason); | 337 | m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: {0}", reason); |
329 | return LLFailedLoginResponse.AuthorizationProblem; | 338 | return LLFailedLoginResponse.AuthorizationProblem; |
330 | 339 | ||
@@ -340,7 +349,7 @@ namespace OpenSim.Services.LLLoginService | |||
340 | // | 349 | // |
341 | // Finally, fill out the response and return it | 350 | // Finally, fill out the response and return it |
342 | // | 351 | // |
343 | LLLoginResponse response = new LLLoginResponse(account, aCircuit, presence, destination, inventorySkel, friendsList, m_LibraryService, | 352 | LLLoginResponse response = new LLLoginResponse(account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, |
344 | where, startLocation, position, lookAt, m_WelcomeMessage, home, clientIP); | 353 | where, startLocation, position, lookAt, m_WelcomeMessage, home, clientIP); |
345 | 354 | ||
346 | m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to client."); | 355 | m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to client."); |
@@ -350,12 +359,12 @@ namespace OpenSim.Services.LLLoginService | |||
350 | { | 359 | { |
351 | m_log.WarnFormat("[LLOGIN SERVICE]: Exception processing login for {0} {1}: {2} {3}", firstName, lastName, e.ToString(), e.StackTrace); | 360 | m_log.WarnFormat("[LLOGIN SERVICE]: Exception processing login for {0} {1}: {2} {3}", firstName, lastName, e.ToString(), e.StackTrace); |
352 | if (m_PresenceService != null) | 361 | if (m_PresenceService != null) |
353 | m_PresenceService.LogoutAgent(session, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); | 362 | m_PresenceService.LogoutAgent(session); |
354 | return LLFailedLoginResponse.InternalError; | 363 | return LLFailedLoginResponse.InternalError; |
355 | } | 364 | } |
356 | } | 365 | } |
357 | 366 | ||
358 | protected GridRegion FindDestination(UserAccount account, UUID scopeID, PresenceInfo pinfo, UUID sessionID, string startLocation, out GridRegion gatekeeper, out string where, out Vector3 position, out Vector3 lookAt) | 367 | protected GridRegion FindDestination(UserAccount account, UUID scopeID, GridUserInfo pinfo, UUID sessionID, string startLocation, GridRegion home, out GridRegion gatekeeper, out string where, out Vector3 position, out Vector3 lookAt) |
359 | { | 368 | { |
360 | m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation); | 369 | m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation); |
361 | 370 | ||
@@ -377,7 +386,7 @@ namespace OpenSim.Services.LLLoginService | |||
377 | 386 | ||
378 | bool tryDefaults = false; | 387 | bool tryDefaults = false; |
379 | 388 | ||
380 | if (pinfo.HomeRegionID.Equals(UUID.Zero)) | 389 | if (home == null) |
381 | { | 390 | { |
382 | m_log.WarnFormat( | 391 | m_log.WarnFormat( |
383 | "[LLOGIN SERVICE]: User {0} {1} tried to login to a 'home' start location but they have none set", | 392 | "[LLOGIN SERVICE]: User {0} {1} tried to login to a 'home' start location but they have none set", |
@@ -387,16 +396,10 @@ namespace OpenSim.Services.LLLoginService | |||
387 | } | 396 | } |
388 | else | 397 | else |
389 | { | 398 | { |
390 | region = m_GridService.GetRegionByUUID(scopeID, pinfo.HomeRegionID); | 399 | region = home; |
391 | 400 | ||
392 | if (null == region) | 401 | position = pinfo.HomePosition; |
393 | { | 402 | lookAt = pinfo.HomeLookAt; |
394 | m_log.WarnFormat( | ||
395 | "[LLOGIN SERVICE]: User {0} {1} has a recorded home region of {2} but this cannot be found by the grid service", | ||
396 | account.FirstName, account.LastName, pinfo.HomeRegionID); | ||
397 | |||
398 | tryDefaults = true; | ||
399 | } | ||
400 | } | 403 | } |
401 | 404 | ||
402 | if (tryDefaults) | 405 | if (tryDefaults) |
@@ -432,7 +435,7 @@ namespace OpenSim.Services.LLLoginService | |||
432 | 435 | ||
433 | GridRegion region = null; | 436 | GridRegion region = null; |
434 | 437 | ||
435 | if (pinfo.RegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(scopeID, pinfo.RegionID)) == null) | 438 | if (pinfo.LastRegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(scopeID, pinfo.LastRegionID)) == null) |
436 | { | 439 | { |
437 | List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); | 440 | List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); |
438 | if (defaults != null && defaults.Count > 0) | 441 | if (defaults != null && defaults.Count > 0) |
@@ -454,8 +457,8 @@ namespace OpenSim.Services.LLLoginService | |||
454 | } | 457 | } |
455 | else | 458 | else |
456 | { | 459 | { |
457 | position = pinfo.Position; | 460 | position = pinfo.LastPosition; |
458 | lookAt = pinfo.LookAt; | 461 | lookAt = pinfo.LastLookAt; |
459 | } | 462 | } |
460 | 463 | ||
461 | return region; | 464 | return region; |
diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs index ea8d673..7e7e98e 100644 --- a/OpenSim/Services/PresenceService/PresenceService.cs +++ b/OpenSim/Services/PresenceService/PresenceService.cs | |||
@@ -54,8 +54,6 @@ namespace OpenSim.Services.PresenceService | |||
54 | public bool LoginAgent(string userID, UUID sessionID, | 54 | public bool LoginAgent(string userID, UUID sessionID, |
55 | UUID secureSessionID) | 55 | UUID secureSessionID) |
56 | { | 56 | { |
57 | m_Database.Prune(userID); | ||
58 | |||
59 | PresenceData[] d = m_Database.Get("UserID", userID); | 57 | PresenceData[] d = m_Database.Get("UserID", userID); |
60 | 58 | ||
61 | PresenceData data = new PresenceData(); | 59 | PresenceData data = new PresenceData(); |
@@ -65,24 +63,6 @@ namespace OpenSim.Services.PresenceService | |||
65 | data.SessionID = sessionID; | 63 | data.SessionID = sessionID; |
66 | data.Data = new Dictionary<string, string>(); | 64 | data.Data = new Dictionary<string, string>(); |
67 | data.Data["SecureSessionID"] = secureSessionID.ToString(); | 65 | data.Data["SecureSessionID"] = secureSessionID.ToString(); |
68 | data.Data["Online"] = "true"; | ||
69 | data.Data["Login"] = Util.UnixTimeSinceEpoch().ToString(); | ||
70 | if (d != null && d.Length > 0) | ||
71 | { | ||
72 | data.Data["HomeRegionID"] = d[0].Data["HomeRegionID"]; | ||
73 | data.Data["HomePosition"] = d[0].Data["HomePosition"]; | ||
74 | data.Data["HomeLookAt"] = d[0].Data["HomeLookAt"]; | ||
75 | data.Data["Position"] = d[0].Data["Position"]; | ||
76 | data.Data["LookAt"] = d[0].Data["LookAt"]; | ||
77 | |||
78 | data.RegionID = d[0].RegionID; | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | data.Data["HomeRegionID"] = UUID.Zero.ToString(); | ||
83 | data.Data["HomePosition"] = new Vector3(128, 128, 0).ToString(); | ||
84 | data.Data["HomeLookAt"] = new Vector3(0, 1, 0).ToString(); | ||
85 | } | ||
86 | 66 | ||
87 | m_Database.Store(data); | 67 | m_Database.Store(data); |
88 | 68 | ||
@@ -91,28 +71,10 @@ namespace OpenSim.Services.PresenceService | |||
91 | return true; | 71 | return true; |
92 | } | 72 | } |
93 | 73 | ||
94 | public bool LogoutAgent(UUID sessionID, Vector3 position, Vector3 lookat) | 74 | public bool LogoutAgent(UUID sessionID) |
95 | { | 75 | { |
96 | PresenceData data = m_Database.Get(sessionID); | 76 | m_log.DebugFormat("[PRESENCE SERVICE]: Session {0} logout", sessionID); |
97 | if (data == null) | 77 | return m_Database.Delete("SessionID", sessionID.ToString()); |
98 | return false; | ||
99 | |||
100 | PresenceData[] d = m_Database.Get("UserID", data.UserID); | ||
101 | |||
102 | m_log.DebugFormat("[PRESENCE SERVICE]: LogoutAgent {0} with {1} sessions currently present", data.UserID, d.Length); | ||
103 | if (d.Length > 1) | ||
104 | { | ||
105 | m_Database.Delete("UserID", data.UserID); | ||
106 | } | ||
107 | |||
108 | data.Data["Online"] = "false"; | ||
109 | data.Data["Logout"] = Util.UnixTimeSinceEpoch().ToString(); | ||
110 | data.Data["Position"] = position.ToString(); | ||
111 | data.Data["LookAt"] = lookat.ToString(); | ||
112 | |||
113 | m_Database.Store(data); | ||
114 | |||
115 | return true; | ||
116 | } | 78 | } |
117 | 79 | ||
118 | public bool LogoutRegionAgents(UUID regionID) | 80 | public bool LogoutRegionAgents(UUID regionID) |
@@ -123,7 +85,7 @@ namespace OpenSim.Services.PresenceService | |||
123 | } | 85 | } |
124 | 86 | ||
125 | 87 | ||
126 | public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) | 88 | public bool ReportAgent(UUID sessionID, UUID regionID) |
127 | { | 89 | { |
128 | m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent with session {0} in region {1}", sessionID, regionID); | 90 | m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent with session {0} in region {1}", sessionID, regionID); |
129 | try | 91 | try |
@@ -134,14 +96,7 @@ namespace OpenSim.Services.PresenceService | |||
134 | if (pdata.Data == null) | 96 | if (pdata.Data == null) |
135 | return false; | 97 | return false; |
136 | 98 | ||
137 | if (!pdata.Data.ContainsKey("Online") || (pdata.Data.ContainsKey("Online") && pdata.Data["Online"] == "false")) | 99 | return m_Database.ReportAgent(sessionID, regionID); |
138 | { | ||
139 | m_log.WarnFormat("[PRESENCE SERVICE]: Someone tried to report presence of an agent who's not online"); | ||
140 | return false; | ||
141 | } | ||
142 | |||
143 | return m_Database.ReportAgent(sessionID, regionID, | ||
144 | position.ToString(), lookAt.ToString()); | ||
145 | } | 100 | } |
146 | catch (Exception e) | 101 | catch (Exception e) |
147 | { | 102 | { |
@@ -160,22 +115,10 @@ namespace OpenSim.Services.PresenceService | |||
160 | 115 | ||
161 | ret.UserID = data.UserID; | 116 | ret.UserID = data.UserID; |
162 | ret.RegionID = data.RegionID; | 117 | ret.RegionID = data.RegionID; |
163 | if (data.Data.ContainsKey("Online")) | ||
164 | ret.Online = bool.Parse(data.Data["Online"]); | ||
165 | if (data.Data.ContainsKey("Login")) | ||
166 | ret.Login = Util.ToDateTime(Convert.ToInt32(data.Data["Login"])); | ||
167 | if (data.Data.ContainsKey("Logout")) | ||
168 | ret.Logout = Util.ToDateTime(Convert.ToInt32(data.Data["Logout"])); | ||
169 | if (data.Data.ContainsKey("Position")) | 118 | if (data.Data.ContainsKey("Position")) |
170 | ret.Position = Vector3.Parse(data.Data["Position"]); | 119 | ret.Position = Vector3.Parse(data.Data["Position"]); |
171 | if (data.Data.ContainsKey("LookAt")) | 120 | if (data.Data.ContainsKey("LookAt")) |
172 | ret.LookAt = Vector3.Parse(data.Data["LookAt"]); | 121 | ret.LookAt = Vector3.Parse(data.Data["LookAt"]); |
173 | if (data.Data.ContainsKey("HomeRegionID")) | ||
174 | ret.HomeRegionID = new UUID(data.Data["HomeRegionID"]); | ||
175 | if (data.Data.ContainsKey("HomePosition")) | ||
176 | ret.HomePosition = Vector3.Parse(data.Data["HomePosition"]); | ||
177 | if (data.Data.ContainsKey("HomeLookAt")) | ||
178 | ret.HomeLookAt = Vector3.Parse(data.Data["HomeLookAt"]); | ||
179 | 122 | ||
180 | return ret; | 123 | return ret; |
181 | } | 124 | } |
@@ -195,16 +138,8 @@ namespace OpenSim.Services.PresenceService | |||
195 | 138 | ||
196 | ret.UserID = d.UserID; | 139 | ret.UserID = d.UserID; |
197 | ret.RegionID = d.RegionID; | 140 | ret.RegionID = d.RegionID; |
198 | ret.Online = bool.Parse(d.Data["Online"]); | ||
199 | ret.Login = Util.ToDateTime(Convert.ToInt32( | ||
200 | d.Data["Login"])); | ||
201 | ret.Logout = Util.ToDateTime(Convert.ToInt32( | ||
202 | d.Data["Logout"])); | ||
203 | ret.Position = Vector3.Parse(d.Data["Position"]); | 141 | ret.Position = Vector3.Parse(d.Data["Position"]); |
204 | ret.LookAt = Vector3.Parse(d.Data["LookAt"]); | 142 | ret.LookAt = Vector3.Parse(d.Data["LookAt"]); |
205 | ret.HomeRegionID = new UUID(d.Data["HomeRegionID"]); | ||
206 | ret.HomePosition = Vector3.Parse(d.Data["HomePosition"]); | ||
207 | ret.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]); | ||
208 | 143 | ||
209 | info.Add(ret); | 144 | info.Add(ret); |
210 | } | 145 | } |
@@ -214,9 +149,5 @@ namespace OpenSim.Services.PresenceService | |||
214 | return info.ToArray(); | 149 | return info.ToArray(); |
215 | } | 150 | } |
216 | 151 | ||
217 | public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) | ||
218 | { | ||
219 | return m_Database.SetHomeLocation(userID, regionID, position, lookAt); | ||
220 | } | ||
221 | } | 152 | } |
222 | } | 153 | } |
diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs index c6e33bb..697ba63 100644 --- a/OpenSim/Services/UserAccountService/GridUserService.cs +++ b/OpenSim/Services/UserAccountService/GridUserService.cs | |||
@@ -31,6 +31,7 @@ using System.Reflection; | |||
31 | using Nini.Config; | 31 | using Nini.Config; |
32 | using OpenSim.Data; | 32 | using OpenSim.Data; |
33 | using OpenSim.Services.Interfaces; | 33 | using OpenSim.Services.Interfaces; |
34 | using OpenSim.Framework; | ||
34 | using OpenSim.Framework.Console; | 35 | using OpenSim.Framework.Console; |
35 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | 36 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; |
36 | 37 | ||
@@ -50,27 +51,109 @@ namespace OpenSim.Services.UserAccountService | |||
50 | 51 | ||
51 | public GridUserInfo GetGridUserInfo(string userID) | 52 | public GridUserInfo GetGridUserInfo(string userID) |
52 | { | 53 | { |
53 | GridUserData d = m_Database.GetGridUserData(userID); | 54 | GridUserData d = m_Database.Get(userID); |
54 | 55 | ||
56 | if (d == null) | ||
57 | return null; | ||
58 | |||
55 | GridUserInfo info = new GridUserInfo(); | 59 | GridUserInfo info = new GridUserInfo(); |
56 | info.UserID = d.UserID; | 60 | info.UserID = d.UserID; |
57 | info.HomeRegionID = new UUID(d.Data["HomeRegionID"]); | 61 | info.HomeRegionID = new UUID(d.Data["HomeRegionID"]); |
58 | info.HomePosition = Vector3.Parse(d.Data["HomePosition"]); | 62 | info.HomePosition = Vector3.Parse(d.Data["HomePosition"]); |
59 | info.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]); | 63 | info.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]); |
60 | 64 | ||
65 | info.LastRegionID = new UUID(d.Data["LastRegionID"]); | ||
66 | info.LastPosition = Vector3.Parse(d.Data["LastPosition"]); | ||
67 | info.LastLookAt = Vector3.Parse(d.Data["LastLookAt"]); | ||
68 | |||
69 | info.Online = bool.Parse(d.Data["Online"]); | ||
70 | info.Login = Util.ToDateTime(Convert.ToInt32(d.Data["Login"])); | ||
71 | info.Logout = Util.ToDateTime(Convert.ToInt32(d.Data["Logout"])); | ||
72 | |||
61 | return info; | 73 | return info; |
62 | } | 74 | } |
63 | 75 | ||
64 | public bool StoreGridUserInfo(GridUserInfo info) | 76 | public GridUserInfo LoggedIn(string userID) |
77 | { | ||
78 | m_log.DebugFormat("[GRID USER SERVICE]: User {0} is online", userID); | ||
79 | GridUserData d = m_Database.Get(userID); | ||
80 | |||
81 | if (d == null) | ||
82 | { | ||
83 | d = new GridUserData(); | ||
84 | d.UserID = userID; | ||
85 | } | ||
86 | |||
87 | d.Data["Online"] = true.ToString(); | ||
88 | d.Data["Login"] = Util.UnixTimeSinceEpoch().ToString(); | ||
89 | |||
90 | m_Database.Store(d); | ||
91 | |||
92 | return GetGridUserInfo(userID); | ||
93 | } | ||
94 | |||
95 | public bool LoggedOut(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) | ||
96 | { | ||
97 | m_log.DebugFormat("[GRID USER SERVICE]: User {0} is offline", userID); | ||
98 | GridUserData d = m_Database.Get(userID); | ||
99 | |||
100 | if (d == null) | ||
101 | { | ||
102 | d = new GridUserData(); | ||
103 | d.UserID = userID; | ||
104 | } | ||
105 | |||
106 | d.Data["Online"] = false.ToString(); | ||
107 | d.Data["Logout"] = Util.UnixTimeSinceEpoch().ToString(); | ||
108 | d.Data["LastRegionID"] = regionID.ToString(); | ||
109 | d.Data["LastPosition"] = lastPosition.ToString(); | ||
110 | d.Data["LastLookAt"] = lastLookAt.ToString(); | ||
111 | |||
112 | return m_Database.Store(d); | ||
113 | } | ||
114 | |||
115 | protected bool StoreGridUserInfo(GridUserInfo info) | ||
65 | { | 116 | { |
66 | GridUserData d = new GridUserData(); | 117 | GridUserData d = new GridUserData(); |
67 | 118 | ||
68 | d.Data["UserID"] = info.UserID; | ||
69 | d.Data["HomeRegionID"] = info.HomeRegionID.ToString(); | 119 | d.Data["HomeRegionID"] = info.HomeRegionID.ToString(); |
70 | d.Data["HomePosition"] = info.HomePosition.ToString(); | 120 | d.Data["HomePosition"] = info.HomePosition.ToString(); |
71 | d.Data["HomeLookAt"] = info.HomeLookAt.ToString(); | 121 | d.Data["HomeLookAt"] = info.HomeLookAt.ToString(); |
72 | 122 | ||
73 | return m_Database.StoreGridUserData(d); | 123 | return m_Database.Store(d); |
124 | } | ||
125 | |||
126 | public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt) | ||
127 | { | ||
128 | GridUserData d = m_Database.Get(userID); | ||
129 | if (d == null) | ||
130 | { | ||
131 | d = new GridUserData(); | ||
132 | d.UserID = userID; | ||
133 | } | ||
134 | |||
135 | d.Data["HomeRegionID"] = homeID.ToString(); | ||
136 | d.Data["HomePosition"] = homePosition.ToString(); | ||
137 | d.Data["HomeLookAt"] = homeLookAt.ToString(); | ||
138 | |||
139 | return m_Database.Store(d); | ||
140 | } | ||
141 | |||
142 | public bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) | ||
143 | { | ||
144 | //m_log.DebugFormat("[Grid User Service]: SetLastPosition for {0}", userID); | ||
145 | GridUserData d = m_Database.Get(userID); | ||
146 | if (d == null) | ||
147 | { | ||
148 | d = new GridUserData(); | ||
149 | d.UserID = userID; | ||
150 | } | ||
151 | |||
152 | d.Data["LastRegionID"] = regionID.ToString(); | ||
153 | d.Data["LastPosition"] = lastPosition.ToString(); | ||
154 | d.Data["LastLookAt"] = lastLookAt.ToString(); | ||
155 | |||
156 | return m_Database.Store(d); | ||
74 | } | 157 | } |
75 | } | 158 | } |
76 | } \ No newline at end of file | 159 | } \ No newline at end of file |
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 35e2826..6923293 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs | |||
@@ -46,7 +46,7 @@ namespace OpenSim.Services.UserAccountService | |||
46 | 46 | ||
47 | protected IGridService m_GridService; | 47 | protected IGridService m_GridService; |
48 | protected IAuthenticationService m_AuthenticationService; | 48 | protected IAuthenticationService m_AuthenticationService; |
49 | protected IPresenceService m_PresenceService; | 49 | protected IGridUserService m_GridUserService; |
50 | protected IInventoryService m_InventoryService; | 50 | protected IInventoryService m_InventoryService; |
51 | 51 | ||
52 | public UserAccountService(IConfigSource config) | 52 | public UserAccountService(IConfigSource config) |
@@ -69,9 +69,9 @@ namespace OpenSim.Services.UserAccountService | |||
69 | if (authServiceDll != string.Empty) | 69 | if (authServiceDll != string.Empty) |
70 | m_AuthenticationService = LoadPlugin<IAuthenticationService>(authServiceDll, new Object[] { config }); | 70 | m_AuthenticationService = LoadPlugin<IAuthenticationService>(authServiceDll, new Object[] { config }); |
71 | 71 | ||
72 | string presenceServiceDll = userConfig.GetString("PresenceService", string.Empty); | 72 | string presenceServiceDll = userConfig.GetString("GridUserService", string.Empty); |
73 | if (presenceServiceDll != string.Empty) | 73 | if (presenceServiceDll != string.Empty) |
74 | m_PresenceService = LoadPlugin<IPresenceService>(presenceServiceDll, new Object[] { config }); | 74 | m_GridUserService = LoadPlugin<IGridUserService>(presenceServiceDll, new Object[] { config }); |
75 | 75 | ||
76 | string invServiceDll = userConfig.GetString("InventoryService", string.Empty); | 76 | string invServiceDll = userConfig.GetString("InventoryService", string.Empty); |
77 | if (invServiceDll != string.Empty) | 77 | if (invServiceDll != string.Empty) |
@@ -333,8 +333,8 @@ namespace OpenSim.Services.UserAccountService | |||
333 | if (defaultRegions != null && defaultRegions.Count >= 1) | 333 | if (defaultRegions != null && defaultRegions.Count >= 1) |
334 | home = defaultRegions[0]; | 334 | home = defaultRegions[0]; |
335 | 335 | ||
336 | if (m_PresenceService != null && home != null) | 336 | if (m_GridUserService != null && home != null) |
337 | m_PresenceService.SetHomeLocation(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); | 337 | m_GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); |
338 | else | 338 | else |
339 | m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.", | 339 | m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.", |
340 | firstName, lastName); | 340 | firstName, lastName); |
diff --git a/OpenSim/Tests/Clients/Presence/PresenceClient.cs b/OpenSim/Tests/Clients/Presence/PresenceClient.cs index 4f959f6..0f6b80e 100644 --- a/OpenSim/Tests/Clients/Presence/PresenceClient.cs +++ b/OpenSim/Tests/Clients/Presence/PresenceClient.cs | |||
@@ -77,7 +77,7 @@ namespace OpenSim.Tests.Clients.PresenceClient | |||
77 | pinfo.UserID, pinfo.Online, pinfo.RegionID, pinfo.HomeRegionID); | 77 | pinfo.UserID, pinfo.Online, pinfo.RegionID, pinfo.HomeRegionID); |
78 | 78 | ||
79 | System.Console.WriteLine("\n"); | 79 | System.Console.WriteLine("\n"); |
80 | success = m_Connector.ReportAgent(session1, region1, new Vector3(128, 128, 128), new Vector3(4, 5, 6)); | 80 | success = m_Connector.ReportAgent(session1, region1); |
81 | if (success) | 81 | if (success) |
82 | m_log.InfoFormat("[PRESENCE CLIENT]: Successfully reported session {0} in region {1}", user1, region1); | 82 | m_log.InfoFormat("[PRESENCE CLIENT]: Successfully reported session {0} in region {1}", user1, region1); |
83 | else | 83 | else |
@@ -90,20 +90,7 @@ namespace OpenSim.Tests.Clients.PresenceClient | |||
90 | pinfo.UserID, pinfo.Online, pinfo.RegionID, pinfo.HomeRegionID); | 90 | pinfo.UserID, pinfo.Online, pinfo.RegionID, pinfo.HomeRegionID); |
91 | 91 | ||
92 | System.Console.WriteLine("\n"); | 92 | System.Console.WriteLine("\n"); |
93 | success = m_Connector.SetHomeLocation(user1.ToString(), region1, new Vector3(128, 128, 128), new Vector3(4, 5, 6)); | 93 | success = m_Connector.LogoutAgent(session1); |
94 | if (success) | ||
95 | m_log.InfoFormat("[PRESENCE CLIENT]: Successfully set home for user {0} in region {1}", user1, region1); | ||
96 | else | ||
97 | m_log.InfoFormat("[PRESENCE CLIENT]: failed to set home for user {0}", user1); | ||
98 | pinfo = m_Connector.GetAgent(session1); | ||
99 | if (pinfo == null) | ||
100 | m_log.InfoFormat("[PRESENCE CLIENT]: Unable to retrieve presence for {0} for third time", user1); | ||
101 | else | ||
102 | m_log.InfoFormat("[PRESENCE CLIENT]: Presence retrieved correctly: userID={0}; Online={1}; regionID={2}; homeRegion={3}", | ||
103 | pinfo.UserID, pinfo.Online, pinfo.RegionID, pinfo.HomeRegionID); | ||
104 | |||
105 | System.Console.WriteLine("\n"); | ||
106 | success = m_Connector.LogoutAgent(session1, Vector3.Zero, Vector3.UnitY); | ||
107 | if (success) | 94 | if (success) |
108 | m_log.InfoFormat("[PRESENCE CLIENT]: Successfully logged out user {0}", user1); | 95 | m_log.InfoFormat("[PRESENCE CLIENT]: Successfully logged out user {0}", user1); |
109 | else | 96 | else |
@@ -116,7 +103,7 @@ namespace OpenSim.Tests.Clients.PresenceClient | |||
116 | pinfo.UserID, pinfo.Online, pinfo.RegionID, pinfo.HomeRegionID); | 103 | pinfo.UserID, pinfo.Online, pinfo.RegionID, pinfo.HomeRegionID); |
117 | 104 | ||
118 | System.Console.WriteLine("\n"); | 105 | System.Console.WriteLine("\n"); |
119 | success = m_Connector.ReportAgent(session1, UUID.Random(), Vector3.Zero, Vector3.Zero); | 106 | success = m_Connector.ReportAgent(session1, UUID.Random()); |
120 | if (success) | 107 | if (success) |
121 | m_log.InfoFormat("[PRESENCE CLIENT]: Report agent succeeded, but this is wrong"); | 108 | m_log.InfoFormat("[PRESENCE CLIENT]: Report agent succeeded, but this is wrong"); |
122 | else | 109 | else |